April 7-9, 2025
Directions North America 2025
Virgin Hotels Las Vegas
Recognized as the most anticipated partners-only event in the region, Directions NA 2025 promises to skyrocket your business - it's all about Microsoft Dynamics 365 Business Central, its integrations, partnerships, and all the incredible solutions we can offer together as a community!
We look forward to seeing you at Directions North America 2025, April 7-9, at Virgin Hotels Las Vegas.
Register for Directions in 3 simple steps:
- Create Company & Individual Profile
- Purchase Passes & Receive Registration Codes Email
- Register Individual Attendees
Find more information in our Instructions.

Error executing template "Designs/Swift/Paragraph/COMM_Schedule.cshtml" System.NullReferenceException: Object reference not set to an instance of an object. at CompiledRazorTemplates.Dynamic.RazorEngine_0948c4d11d6f4433aaa465ae9f98c097.<>c__DisplayClass15_5.<Execute>b__11(Item room) in F:\Domains\Sites\dir-na.mydwsitec.com\Files\Templates\Designs\Swift\Paragraph\COMM_Schedule.cshtml:line 301 at System.Linq.Enumerable.WhereListIterator`1.MoveNext() at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source) at CompiledRazorTemplates.Dynamic.RazorEngine_0948c4d11d6f4433aaa465ae9f98c097.Execute() in F:\Domains\Sites\dir-na.mydwsitec.com\Files\Templates\Designs\Swift\Paragraph\COMM_Schedule.cshtml:line 301 at RazorEngine.Templating.TemplateBase.RazorEngine.Templating.ITemplate.Run(ExecuteContext context, TextWriter reader) at RazorEngine.Templating.RazorEngineService.RunCompile(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass16_0.<RunCompile>b__0(TextWriter writer) at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter) at Dynamicweb.Rendering.RazorTemplateRenderingProvider.Render(Template template) at Dynamicweb.Rendering.TemplateRenderingService.Render(Template template) at Dynamicweb.Rendering.Template.RenderRazorTemplate()
1 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.ParagraphViewModel> 2 @using Dynamicweb.Frontend.Navigation 3 @using Dynamicweb.Content.Items 4 @using Dynamicweb.Frontend 5 @using System.Web.Helpers 6 @using System.Web 7 @using System.Text 8 @using System.Net 9 @using System.Linq 10 @using System 11 @using System.Globalization 12 @using Newtonsoft.Json 13 @using Newtonsoft.Json.Linq 14 15 @functions{ 16 static string GetJson(string address) 17 { 18 using (var client = new WebClient()) 19 { 20 client.Headers.Add("Content-Type", "application/json"); 21 try { 22 return client.DownloadString(address); 23 } catch (InvalidCastException e) 24 { 25 return ""; 26 } 27 } 28 } 29 30 string makeStringReadable(string data){ 31 string response = ""; 32 if(data != "") 33 { 34 string myStr = data; 35 myStr = myStr.Replace('’', '\'').Replace('‘', '\'').Replace('–','-'); 36 byte[] bytes = Encoding.UTF8.GetBytes(myStr); 37 response = Encoding.UTF8.GetString(bytes); 38 response = response.Replace("\r\n", "<br>"); 39 response = response.Replace("’", "'"); 40 response = response.Replace("–","-"); 41 } 42 return response; 43 } 44 45 46 47 public class Root 48 { 49 public List<Session> sessions {get; set;} 50 public List<Speaker> speakers {get; set;} 51 //public List<Question> questions {get; set;} 52 public List<Category> categories {get; set;} 53 public List<Item> rooms {get; set;} 54 } 55 56 public class Session 57 { 58 public string id {get; set;} 59 public string title {get; set;} 60 public string description {get; set;} 61 public DateTime? startsAt {get; set;} 62 public DateTime? endsAt {get; set;} 63 public bool isServiceSession {get; set;} 64 public bool isPlenumSession {get; set;} 65 public List<string> speakers {get; set;} 66 public List<int> categoryItems {get; set;} 67 public List<QuestionAnswers> questionAnswers {get; set;} 68 public int? roomId {get; set;} 69 public string room {get; set;} 70 public string liveUrl {get; set;} 71 public string recordingUrl {get; set;} 72 public string status {get; set;} 73 } 74 75 public class Speaker 76 { 77 public string id {get; set;} 78 public string firstName {get; set;} 79 public string lastName {get; set;} 80 public string bio {get; set;} 81 public string tagLine {get; set;} 82 public string profilePicture {get; set;} 83 public bool isTopSpeaker {get; set;} 84 public List<Link> links {get; set;} 85 public List<string> sessions {get; set;} 86 public string fullName {get; set;} 87 public List<int> categoryItems {get; set;} 88 public List<QuestionAnswers> questionAnswers {get; set;} 89 } 90 91 public class Category 92 { 93 public int id {get; set;} 94 public string title {get; set;} 95 public List<Item> items {get; set;} 96 public int sort {get; set;} 97 public string type {get; set;} 98 } 99 100 public class Link 101 { 102 public string title {get; set;} 103 public string url {get; set;} 104 public string linType {get; set;} 105 } 106 107 public class Item 108 { 109 public int id {get; set;} 110 public string name {get; set;} 111 public int sort {get; set;} 112 } 113 114 public class Timeslot 115 { 116 public string Code {get; set;} 117 public DateTime? DateAndStart {get; set;} 118 public DateTime? SlotDate {get; set;} 119 public DateTime SlotDuration {get; set;} 120 public string SlotEnd {get; set;} 121 public string SlotStart {get; set;} 122 public string Status {get; set;} 123 124 } 125 126 public class Attribute 127 { 128 public string categoryTitle {get; set;} 129 public int categoryId {get; set;} 130 public int categorySort {get; set;} 131 public int attributeId {get; set;} 132 public string attributeName {get; set;} 133 public int attributeSort {get; set;} 134 } 135 136 public string GetTimeslot(Session session) 137 { 138 string code = session.startsAt != null && session.endsAt != null ? session.startsAt.ToString().GetHashCode().ToString("x") + session.endsAt.ToString().GetHashCode().ToString("x") : "UNDEFINED"; 139 return code; 140 } 141 142 public class QuestionAnswers 143 { 144 public string questionId {get; set;} 145 public string answerValue {get; set;} 146 } 147 148 public class Test 149 { 150 public List<QuestionAnswers> questionAnswers { get; set; } 151 } 152 } 153 154 @{ 155 var parentPages = Dynamicweb.Content.Services.Pages.GetAncestors(Pageview.Page.ID, true); 156 Dynamicweb.Content.Page rootPage = parentPages.Any() ? parentPages.Where(x => x.ItemType == "COMM_EventSection").FirstOrDefault() : new Dynamicweb.Content.Page(); 157 var item = Dynamicweb.Content.Services.Items.GetItem(rootPage.ItemType, rootPage.ItemId); 158 var sessionizeCode = item?["SessionizeCode"].ToString() ?? ""; 159 var eventCode = !string.IsNullOrEmpty(Model.Item?.GetString("SessionizeCode")) ? Model.Item?.GetString("SessionizeCode") : sessionizeCode; 160 var title = Model.Item?.GetString("Title"); 161 string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("Theme")) && Model.Item.GetRawValueString("Theme") != "no-theme" ? " theme " + Model.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : ""; 162 string detailTheme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("DetailTheme")) && Model.Item.GetRawValueString("DetailTheme") != "no-theme" ? " theme " + Model.Item.GetRawValueString("DetailTheme").Replace(" ", "").Trim().ToLower() : ""; 163 detailTheme = detailTheme != "" ? detailTheme : theme; 164 string parentContainerCss = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["session"]) ? "" : "shadow rounded-7"; 165 string sessionQueryParameter = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["session"]) ? 166 Dynamicweb.Context.Current.Request.QueryString["session"] : string.Empty; 167 string sessionDetailCss = !string.IsNullOrEmpty(sessionQueryParameter) ? "p-4 rounded-7" : string.Empty; 168 169 theme = sessionQueryParameter != "" ? detailTheme : theme; 170 171 var dateTimeFormatField = !string.IsNullOrEmpty(Model.Item?.GetString("DateFormat")) ? Model.Item?.GetString("DateFormat") : ""; 172 bool isUsDateTime = dateTimeFormatField == "us"; 173 string dateTimeFormat = isUsDateTime ? "MM-dd-yyyy" : "dd-MM-yyyy"; 174 string timeFormat = isUsDateTime ? "hh:mm tt" : "HH:mm"; 175 176 } 177 178 <div class="h-100 @parentContainerCss @(theme) @sessionDetailCss schedule-container [email protected]()"> 179 @if (!string.IsNullOrEmpty(eventCode)) 180 { 181 int dayCounter = 1; 182 int dayCounterTab = 1; 183 string sessionizeAll = "https://sessionize.com/api/v2/" + eventCode + "/view/All"; 184 string responseSessionizeAll = GetJson(sessionizeAll).ToString(); 185 //responseSessionizeAll = makeStringReadable(responseSessionizeAll); 186 Root responseResult = Newtonsoft.Json.JsonConvert.DeserializeObject<Root>(responseSessionizeAll); 187 188 var sessionizeSessions = responseResult.sessions; 189 var sessionizeCategories = responseResult.categories; 190 //filter categories 191 sessionizeCategories = sessionizeCategories.Any() ? sessionizeCategories.Where(x => (x.id != 34553) && (x.id != 34539)).ToList() :sessionizeCategories; 192 var sessionizeSpeakers = responseResult.speakers; 193 var sessionizeRooms = responseResult.rooms; 194 var sessionizeDays = sessionizeSessions.Where(x => x.startsAt != null).Select(x => x.startsAt?.Date).Distinct(); 195 196 List<Timeslot> sessionizeTimeslots = new List<Timeslot>(); 197 foreach(var session in sessionizeSessions) 198 { 199 Timeslot slot = new Timeslot(); 200 slot.Code = GetTimeslot(session); 201 slot.DateAndStart = session.startsAt; 202 slot.SlotDate = session.startsAt?.Date; 203 slot.SlotEnd = session.endsAt?.ToString(timeFormat); // take into consideration US & EU time 204 slot.SlotStart = session.startsAt?.ToString(timeFormat); // take into consideration US & EU time 205 slot.Status = session.isServiceSession ? "SERVICE" : "SESSION"; 206 sessionizeTimeslots.Add(slot); 207 } 208 209 List<Attribute> sessionizeAttributes = new List<Attribute>(); 210 var filteredAttributes = new string []{"Product Category"}; 211 List<string> filteredAttributesId = new List<string>{"35602","186478","186480","186481"}; 212 List<string> filteredAttributesNames = new List<string>{"No","Yes"}; 213 foreach(var category in sessionizeCategories) 214 { 215 foreach(var i in category.items) 216 { 217 if(!filteredAttributesNames.Contains(i.name)) 218 { 219 Attribute attribute = new Attribute(); 220 attribute.categoryTitle = category.title; 221 attribute.categoryId = category.id; 222 attribute.categorySort = category.sort; 223 attribute.attributeId = i.id; 224 attribute.attributeName = i.name; 225 attribute.attributeSort = i.sort; 226 sessionizeAttributes.Add(attribute); 227 } 228 } 229 } 230 231 string sessionDetailLink = Dynamicweb.Context.Current.Request.RawUrl; 232 //var filtersList = new string []{"CONTENT OWNER","PRODUCT","LEVEL","SESSION TYPE","TARGET AUDIENCE","LEARNING PATH"}; 233 var filtersList = new string []{"SESSION TYPE","TARGET AUDIENCE","PRODUCT"}; 234 var sessionTimeslots = sessionizeTimeslots.GroupBy(x => x.Code) 235 .Select(grp => grp.First()).OrderBy(x => x.SlotDate) 236 .ToList(); 237 238 string[] dayNames = {"Pre-day","Day 1","Day 2","Day 3"}; 239 240 241 int tabHeadingCount = 1; 242 int tabContentCount = 1; 243 int accordionCount = 1; 244 245 string categoriesQueryParameter = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["categories"]) ? 246 Dynamicweb.Context.Current.Request.QueryString["categories"] : string.Empty; 247 string dayQueryParameter = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["day"]) ? 248 DateTime.ParseExact(Dynamicweb.Context.Current.Request.QueryString["day"], dateTimeFormat, CultureInfo.InvariantCulture).ToString(dateTimeFormat) : string.Empty; 249 250 251 252 List<Session> sessions = new List<Session>(); 253 for (int i = 0; i < sessionizeSessions.Count; i++) 254 { 255 if (!string.IsNullOrEmpty(categoriesQueryParameter)) 256 { 257 var categories = categoriesQueryParameter?.Split(',')?.Select(Int32.Parse)?.ToList(); 258 var sessionDay = sessionizeSessions[i].startsAt.Value.ToString(dateTimeFormat); // take into consideration US & EU time 259 260 if (sessionDay == dayQueryParameter) 261 { 262 @* Filter current selected day's sessions based on applied category filters *@ 263 if (sessionizeSessions[i].categoryItems.Any(cat => categories.Contains(cat))) 264 { 265 sessions.Add(sessionizeSessions[i]); 266 } 267 else 268 { 269 sessions.Remove(sessionizeSessions[i]); 270 } 271 } 272 else 273 { 274 @* Keep sessions for other days *@ 275 sessions.Add(sessionizeSessions[i]); 276 } 277 } 278 else 279 { 280 @* Keep all sessions if no category filter is applied *@ 281 sessions.Add(sessionizeSessions[i]); 282 } 283 } 284 285 @* Filter current selected day sessions based on categories *@ 286 if (!string.IsNullOrEmpty(categoriesQueryParameter)) 287 { 288 @* Filter only current selected date sessions *@ 289 if (!string.IsNullOrEmpty(dayQueryParameter)) 290 { 291 // sessionizeSessions = sessionizeSessions.Where(session => session.startsAt.ToString("dd-MM-yyyy") == DateTime.Parse(dayQueryParameter)).ToList(); 292 } 293 var categories = categoriesQueryParameter?.Split(',')?.Select(Int32.Parse)?.ToList(); 294 sessionizeSessions = sessionizeSessions.Where(session => categories.Any(cat => session.categoryItems.Contains(cat))).ToList(); 295 } 296 297 @* Session details page logic *@ 298 if (!string.IsNullOrEmpty(sessionQueryParameter)) 299 { 300 var session = sessionizeSessions.Where(session => session.id == sessionQueryParameter).FirstOrDefault(); 301 var room = sessionizeRooms.Where(room => room.id == session.roomId).FirstOrDefault(); 302 303 var speakers = sessionizeSpeakers.Where(speaker => session.speakers.Contains(speaker.id)).ToList(); 304 var sessionDay = session.startsAt?.ToString(dateTimeFormat); // take into consideration US & EU time 305 var startTime = session.startsAt?.ToString(timeFormat); // take into consideration US & EU time 306 var endTime = session.endsAt?.ToString(timeFormat); // take into consideration US & EU time 307 var sessionTitle = makeStringReadable(!string.IsNullOrEmpty(session.title) ? session.title : "TBD"); 308 var sessionDescription = session.description != null ? makeStringReadable(session.description) : ""; 309 var roomName = room.name != null ? makeStringReadable(room.name) : ""; 310 var currentPageUrl = Dynamicweb.Context.Current.Request.RawUrl.Split('?')[0]; 311 var clearFiltersUrl = currentPageUrl + "?" + "day=" + sessionDay + "&session=" + session.id; 312 var seeScheduleUrl = currentPageUrl + "?" + "day=" + sessionDay; 313 314 string requestTypeParam = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["RequestType"]) ? 315 "&RequestType=" + Dynamicweb.Context.Current.Request.QueryString["RequestType"] : ""; 316 string layoutTemplate = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["LayoutTemplate"]) ? 317 "&LayoutTemplate=" + Dynamicweb.Context.Current.Request.QueryString["LayoutTemplate"] : ""; 318 319 seeScheduleUrl = seeScheduleUrl + requestTypeParam; 320 seeScheduleUrl = seeScheduleUrl + layoutTemplate; 321 322 bool renderPresentationContainer = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["RequestType"]) && Dynamicweb.Context.Current.Request.QueryString["RequestType"] == "External"; 323 324 string recordingUrl = session.recordingUrl; 325 string liveUrl = session.liveUrl; 326 327 <div class="grid w-100"> 328 <div class="g-col-lg-6 g-col-12 mb-3"> 329 <p class="mb-3 fw-bold">@sessionDay</p> 330 <h1 class="mb-3">@sessionTitle</h1> 331 332 <div class="d-flex align-items-center gap-lg-4 gap-2 flex-wrap"> 333 <span> 334 @RenderIcon("/Files/Templates/Designs/Swift/Assets/icons/clock.svg") 335 @startTime - @endTime 336 </span> 337 <span> 338 @RenderIcon("/Files/Templates/Designs/Swift/Assets/icons/map-pin.svg") 339 @roomName 340 </span> 341 <span> 342 343 <a class="btn btn-secondary" href="@seeScheduleUrl">@RenderIcon("/Files/Templates/Designs/Swift/Assets/icons/calendar.svg") @Translate("Back to event schedule")</a> 344 </span> 345 </div> 346 347 @if (renderPresentationContainer) 348 { 349 string sessionsUrl = "https://sessionize.com/api/v2/"+ eventCode + "/view/Sessions"; 350 string response = GetJson(sessionsUrl).ToString(); 351 352 JArray data = JArray.Parse(response); 353 JObject[] currentSession = data[0]["sessions"].Where(o => (string)o["id"] == session.id).Select(o => (JObject)o).ToArray(); 354 JArray questionsAndAnswers = currentSession[0]["questionAnswers"] != null ? 355 (JArray)currentSession[0]["questionAnswers"] : null; 356 357 <div class="presentation-container mt-3"> 358 @if (questionsAndAnswers != null) 359 { 360 foreach (var element in questionsAndAnswers) 361 { 362 bool renderDownloadLink = element["answer"] != null && !string.IsNullOrEmpty(element["answer"].ToString()); 363 if (renderDownloadLink) 364 { 365 <a class="btn btn-primary" href="@element["answer"]">@Translate("Download presentation")</a> 366 } 367 } 368 } 369 </div> 370 } 371 </div> 372 <div class="g-col-lg-6 g-col-12 mb-3 pt-5"> 373 374 @if(liveUrl != "" && liveUrl != null) 375 { 376 <div><p>@Translate("MeetMicrosoft_Text")</p></div> 377 <div><p><a class="btn btn-primary" href="@liveUrl">@Translate("Booth Schedule")</a></p></div> 378 379 } 380 @if (sessionDescription != null) 381 { 382 <div> 383 <p>@sessionDescription</p> 384 </div> 385 } 386 </div> 387 388 @if (speakers.Any()) 389 { 390 int categoryParameter = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["Category"]) ? 391 Convert.ToInt32(Dynamicweb.Context.Current.Request.QueryString["Category"]) : 0; 392 var groupedAttributes = sessionizeAttributes.GroupBy( 393 attr => attr.categoryTitle, 394 (key, g) => new { Title = key, Items = g.ToList() }); 395 speakers = categoryParameter != 0 ? speakers.Where(speaker => speaker.categoryItems.Contains(categoryParameter)).ToList() : speakers; 396 string headerTitle = Translate("Speakers") + ":"; 397 398 <div class="g-col-12"> 399 <div class="w-100"> 400 <h4 class="mb-4">@headerTitle</h4> 401 </div> 402 403 @* Speakers wall *@ 404 <div class="grid"> 405 @for (int i = 0; i < speakers.Count(); i++) 406 { 407 var columnSize = "grid g-col-12"; 408 409 string viewSpeakerInfoTranslate = Translate("View") + " " + speakers[i].fullName + " " + Translate("info"); 410 string speakerName = speakers[i].fullName != null ? speakers[i].fullName.ToString() : ""; 411 string speakerBio = speakers[i].bio != null ? speakers[i].bio.ToString() : ""; 412 string speakerTagLine = speakers[i].tagLine != null ? speakers[i].tagLine.ToString() : ""; 413 string speakerProfilePicture = speakers[i].profilePicture != null ? speakers[i].profilePicture.ToString() : ""; 414 string speakerCategories = speakers[i].categoryItems != null ? String.Join(",", speakers[i].categoryItems) : ""; 415 var speakerSession = sessions.Where(session => speakers[i].sessions.Contains(session.id)).FirstOrDefault(); 416 var speakerSessions = sessions.Where(session => speakers[i].sessions.Contains(session.id)).ToList(); 417 var sessionsTranslate = speakerSessions.Count() > 1 ? Translate("Sessions") : Translate("Session"); 418 419 <div class="speaker @theme @columnSize gap-0 position-relative rounded-7" data-categories="@speakerCategories"> 420 <div class="h-100 g-col-lg-7 g-col-12 order-last order-md-first max-h-45-em"> 421 <div class="h-100 py-4 max-h-30-em"> 422 <div> 423 <a href="#" class="btn btn-link p-0 text-decoration-none" title="@viewSpeakerInfoTranslate" onclick="event.preventDefault(); new bootstrap.Modal(document.getElementById('SpeakerModal_@i')).show()"> 424 <h4 class="text-start">@makeStringReadable(speakerName)</h4> 425 </a> 426 <p>@speakerTagLine</p> 427 </div> 428 <div class="d-flex flex-column gap-3 justify-content-between max-h-15-em overflow-auto"> 429 <p class="m-0 pb-4">@makeStringReadable(speakerBio)</p> 430 </div> 431 @if (speakers[i].links.Any()) 432 { 433 <div class="d-flex gap-3 align-items-end position-absolute top-100 mt-negative-3-em"> 434 @foreach (var link in speakers[i].links) 435 { 436 string icon = "/Files/Templates/Designs/Swift/Assets/icons/"; 437 438 if (link.url.Contains("twitter")) 439 { 440 icon += "twitter.svg"; 441 } 442 else if (link.url.Contains("linkedin")) 443 { 444 icon += "linkedin.svg"; 445 } 446 else 447 { 448 icon += "link.svg"; 449 } 450 451 <a href="@link.url" title="@link.title" target="_blank"> 452 @RenderIcon(icon) 453 </a> 454 } 455 </div> 456 } 457 </div> 458 </div> 459 <div class="h-100 ratio g-col-lg-5 g-col-12 rounded-7" style="--bs-aspect-ratio: 100%;"> 460 <a class="btn btn-link p-4" title="@viewSpeakerInfoTranslate" onclick="new bootstrap.Modal(document.getElementById('SpeakerModal_@i')).show()"> 461 <img src="@speakerProfilePicture" class="w-100 h-100 rounded-7"></img> 462 </a> 463 </div> 464 <div class="h-100 w-100 position-absolute cursor-pointer d-none"> 465 <a class="btn btn-link stretched-link" title="@viewSpeakerInfoTranslate" onclick="new bootstrap.Modal(document.getElementById('SpeakerModal_@i')).show()"></a> 466 </div> 467 </div> 468 469 <div class="modal fade modal-xl" id="SpeakerModal_@i"> 470 <div class="modal-dialog"> 471 <div class="modal-content @theme rounded-7"> 472 <div class="modal-body p-0" id="SpeakerModalBodyContainer_@i"> 473 <div class="close-container position-absolute p-3 end-0 m-3 bg-white rounded-7 z-index-9"> 474 <button type="button" class="btn-close bg-dark z-index-9" data-bs-dismiss="modal" aria-label="Close"></button> 475 </div> 476 <div class="grid @theme gap-0 rounded-7"> 477 <div class="h-100 g-col-lg-7 g-col-12 order-last order-md-first"> 478 <div class="h-100 p-4 overflow-auto max-h-30-em"> 479 <div> 480 <h4>@makeStringReadable(speakerName)</h4> 481 <p>@speakerTagLine</p> 482 </div> 483 <div class="d-flex flex-column gap-3 justify-content-between"> 484 <p class="m-0">@makeStringReadable(speakerBio)</p> 485 </div> 486 <div class="mt-4 d-grid"> 487 <p class="m-0 fw-bold">@sessionsTranslate</p> 488 @foreach (var _item in speakerSessions) 489 { 490 var sessionLink = currentPageUrl.IndexOf("?") > 0 ? currentPageUrl + "&session=" + _item.id : currentPageUrl + "?session=" + _item.id; 491 <a class="btn btn-link text-start p-0 mb-2" title="@_item.title" href="@sessionLink"> 492 @_item.title 493 </a> 494 } 495 </div> 496 @if (speakers[i].links.Any()) 497 { 498 <div class="d-flex gap-3 align-items-end"> 499 @foreach (var link in speakers[i].links) 500 { 501 string icon = "/Files/Templates/Designs/Swift/Assets/icons/"; 502 503 if (link.url.Contains("twitter")) 504 { 505 icon += "twitter.svg"; 506 } 507 else if (link.url.Contains("linkedin")) 508 { 509 icon += "linkedin.svg"; 510 } 511 else 512 { 513 icon += "link.svg"; 514 } 515 516 <a href="@link.url" title="@link.title" target="_blank"> 517 @RenderIcon(icon) 518 </a> 519 } 520 </div> 521 } 522 </div> 523 </div> 524 <div class="h-100 ratio g-col-lg-5 g-col-12" style="--bs-aspect-ratio: 100%"> 525 <img src="@speakerProfilePicture" class="rounded-7"></img> 526 </div> 527 </div> 528 </div> 529 </div> 530 </div> 531 </div> 532 533 } 534 </div> 535 </div> 536 } 537 </div> 538 } 539 else 540 { 541 <nav class="tabs rounded-7"> 542 <ul class="nav nav-tabs days-tabs bg-light-grey rounded-7-top" role="tablist"> 543 @foreach (var day in sessionizeDays) 544 { 545 string dayDate = day?.ToString(dateTimeFormat); // take into consideration US & EU time 546 string dayName = dayNames[tabHeadingCount - 1]; 547 bool showCounterWithTabName = dayName == "Training" ? true : false; 548 string tabAnchorRaw = showCounterWithTabName ? dayName + tabHeadingCount : dayName; 549 string tabAnchor = "tabname" + tabAnchorRaw + tabHeadingCount; 550 bool hasDayParam = !string.IsNullOrEmpty(dayQueryParameter); 551 string activeClass = hasDayParam && dayQueryParameter == dayDate ? 552 "active" : tabHeadingCount == 1 && !hasDayParam ? "active" : ""; 553 554 string firstTabCss = tabHeadingCount == 1 ? "rounded-7-top-left" : ""; 555 556 <li class="flex-mobile-auto @(firstTabCss)" role="presentation"> 557 <a class="session-tab nav-link d-grid text-decoration-none p-3 pe-4 @(activeClass) @(firstTabCss)" href="@("#" + tabAnchor)" aria-controls="@tabAnchor" role="tab" data-toggle="tab" data-date="@dayDate"> 558 <span class="fw-bold">@dayName</span> <span>@dayDate</span> 559 </a> 560 </li> 561 tabHeadingCount += 1; 562 } 563 </ul> 564 </nav> 565 566 <div class="tab-content days-tabs-container p-lg-4 p-2 rounded-7-bottom"> 567 @foreach (var day in sessionizeDays) 568 { 569 string dayClass = tabContentCount == 1 ? "active" : ""; 570 string timeslotsDay = day?.ToString(dateTimeFormat); // take into consideration US & EU time 571 string dayName = dayNames[tabContentCount - 1]; 572 bool showCounterWithTabName = dayName == "Training" ? true : false; 573 string tabAnchorRaw = showCounterWithTabName ? dayName + tabContentCount : dayName; 574 string tabAnchor = "tabname" + tabAnchorRaw + tabContentCount; 575 string dayAnchor = showCounterWithTabName ? dayName + tabContentCount : dayName; 576 string dayID = "day" + tabContentCount; 577 578 var daySessionsList = sessionizeSessions.Where(x => x.startsAt?.Date == day); 579 var dayAttributes = new List<int>(); 580 foreach(var daySession in daySessionsList) 581 { 582 dayAttributes.AddRange(daySession.categoryItems); 583 } 584 585 var dayAttributesFiltered = sessionizeAttributes.Where(item => dayAttributes.Any(filter => filter.Equals(item.attributeId))); 586 //remove attribute categories based on filtersList 587 dayAttributesFiltered = dayAttributesFiltered.Where(item => filtersList.Contains(item.categoryTitle.ToUpper())).ToList(); 588 var dayAttributesCategories = dayAttributesFiltered.Select(item => item.categoryTitle).Distinct(); 589 590 bool hasDayParam = !string.IsNullOrEmpty(dayQueryParameter); 591 bool matchingDate = hasDayParam && (dayQueryParameter == timeslotsDay); 592 var activeTabClass = matchingDate ? 593 "active" : tabContentCount == 1 && !hasDayParam ? "active" : ""; 594 595 var activeTabContainerClass = matchingDate ? 596 "show" : tabContentCount == 1 && !hasDayParam ? "show" : ""; 597 598 <div id="@tabAnchor" role="tabpanel" class="tab-pane @activeTabClass"> 599 600 @*<!--Filters--> 601 @if (dayAttributesFiltered.Any()) 602 { 603 <div class="grid"> 604 <div class="g-col-lg-4 g-col-12"> 605 <label class="fw-bold" for="filter-sessions-1">@Translate("Filter Sessions")</label> 606 <select id="filter-sessions-@tabContentCount" name="filter-sessions" class="form-control select2-multiple filter-session-ref filter-session-trigger" multiple="multiple" data-date="@timeslotsDay"> 607 @foreach (var category in dayAttributesFiltered) 608 { 609 //Take into consideration the dayParam 610 var categories = !string.IsNullOrEmpty(categoriesQueryParameter) ? categoriesQueryParameter?.Split(',')?.Select(Int32.Parse)?.ToList() : null; 611 var selected = !string.IsNullOrEmpty(categoriesQueryParameter) && categories.Contains(category.attributeId) ? "selected" : ""; 612 <option @selected value='@category.attributeId'>@category.attributeName @category.categoryTitle</option> 613 } 614 </select> 615 @if (!string.IsNullOrEmpty(categoriesQueryParameter)) 616 { 617 var clearFiltersUrl = Dynamicweb.Context.Current.Request.RawUrl.Split('?')[0] + "?" + "day=" + timeslotsDay; 618 //include RequestType & LayoutTemplate params if present (embedded page scenario) 619 string requestTypeParam = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["RequestType"]) ? 620 "&RequestType=" + Dynamicweb.Context.Current.Request.QueryString["RequestType"] : ""; 621 string layoutTemplate = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["LayoutTemplate"]) ? 622 "&LayoutTemplate=" + Dynamicweb.Context.Current.Request.QueryString["LayoutTemplate"] : ""; 623 624 clearFiltersUrl = clearFiltersUrl + requestTypeParam; 625 clearFiltersUrl = clearFiltersUrl + layoutTemplate; 626 <a class="btn btn-link" href="@clearFiltersUrl" title="Clear filters"> 627 @Translate("Clear filters") 628 </a> 629 } 630 </div> 631 </div> 632 } 633 634 <div class="hidden"> 635 <div class="filterData"> 636 @foreach (var filter in filtersList) 637 { 638 string filterName = filter; 639 } 640 </div> 641 </div> 642 643 <!--FiltersEnd-->*@ 644 645 <!--Filters--> 646 @if (dayAttributesFiltered.Any()) 647 { 648 <div class="grid"> 649 @foreach(var filterCategory in dayAttributesCategories) 650 { 651 string filterCategoryName = filterCategory; 652 string filterLabel = Translate("Filter " + filterCategoryName); 653 filterCategoryName = filterCategoryName.Replace(" ","-").ToLower(); 654 var dayAttributesList = dayAttributesFiltered.OrderBy(item=>item.attributeName).Where(item=>item.categoryTitle == filterCategory).ToList(); 655 656 <div class="g-col-lg-4 g-col-12"> 657 <label class="fw-bold" for="filter-@filterCategoryName-@tabContentCount">@filterLabel</label> 658 <select id="filter-@filterCategoryName-@tabContentCount" name="filter-@filterCategoryName" class="filter-dropdown form-control select2-multiple filter-@filterCategoryName-ref filter-@filterCategoryName-trigger" multiple="multiple" data-date="@timeslotsDay"> 659 @foreach (var category in dayAttributesList) 660 { 661 @* Take into consideration the dayParam *@ 662 var categories = !string.IsNullOrEmpty(categoriesQueryParameter) ? categoriesQueryParameter?.Split(',')?.Select(Int32.Parse)?.ToList() : null; 663 var selected = !string.IsNullOrEmpty(categoriesQueryParameter) && categories.Contains(category.attributeId) ? "selected" : ""; 664 <option @selected value='@category.attributeId'>@category.attributeName @category.categoryTitle</option> 665 } 666 </select> 667 @if (!string.IsNullOrEmpty(categoriesQueryParameter)) 668 { 669 var clearFiltersUrl = Dynamicweb.Context.Current.Request.RawUrl.Split('?')[0] + "?" + "day=" + timeslotsDay; 670 @* include RequestType & LayoutTemplate params if present (embedded page scenario) *@ 671 string requestTypeParam = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["RequestType"]) ? 672 "&RequestType=" + Dynamicweb.Context.Current.Request.QueryString["RequestType"] : ""; 673 string layoutTemplate = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["LayoutTemplate"]) ? 674 "&LayoutTemplate=" + Dynamicweb.Context.Current.Request.QueryString["LayoutTemplate"] : ""; 675 676 clearFiltersUrl = clearFiltersUrl + requestTypeParam; 677 clearFiltersUrl = clearFiltersUrl + layoutTemplate; 678 <a class="btn btn-link clear-filters" href="@clearFiltersUrl" title="Clear filters" data-target-dropdown="filter-@filterCategoryName-@tabContentCount"> 679 @Translate("Clear filters") 680 </a> 681 } 682 </div> 683 684 } 685 </div> 686 } 687 688 <div class="hidden"> 689 <div class="filterData"> 690 @foreach (var filter in filtersList) 691 { 692 string filterName = filter; 693 } 694 </div> 695 </div> 696 697 <!--FiltersEnd--> 698 699 700 <!-- Second level content start --> 701 <div class="tab-content2 tab-content-schedule"> 702 <!-- All sessions start --> 703 <div id='@(dayID + "_allsessions")' class="tab-pane fade in @activeTabContainerClass"> 704 <div class="panel-group mt-4" id="@(dayID + "_allsessions_timeline")"> 705 <p class="not-found mb-0 d-none">@Translate("No items found.")</p> 706 @foreach (var timeslot in sessionTimeslots.Where(x => x.SlotDate == day).OrderBy(x => x.DateAndStart)) 707 { 708 string timeslotCode = timeslot.Code; 709 var start = timeslot.SlotStart; // take into consideration US & EU time 710 var end = timeslot.SlotEnd; // take into consideration US & EU time 711 var currentSessions = sessions.Where(x => GetTimeslot(x) == timeslotCode); // filtered sessions list by day & categories [based on sessionizeSessions] 712 713 if (currentSessions.Any()) 714 { 715 string breakSessionTheme = currentSessions.Any(session => session.isServiceSession) ? "theme ice-blue" : ""; 716 string isBreakSession = currentSessions.Any(session => session.isServiceSession) ? "is-break" : ""; 717 <!-- Lecture start --> 718 <div class="grid gap-lg-4 panel schedule-item border p-4 pt-6 mb-3 position-relative rounded-7 grid-auto-rows-1-fr @timeslotCode @isBreakSession" data-duration="" data-status=""> 719 <div class="g-col-12 time-wrapper position-absolute py-3 px-4 ms-4 rounded-7-bottom"> 720 <strong class="time" data-debug="">@start - @end</strong> 721 </div> 722 @foreach (var session in currentSessions) 723 { 724 725 var sessionRoom = sessionizeRooms.Where(x => x.id == session.roomId).FirstOrDefault(); 726 string sessionRoomName = sessionRoom != null ? makeStringReadable(sessionRoom.name) : "N/A"; 727 var isBreak = session.isServiceSession ? "full" : ""; 728 var test = session.isServiceSession ? "tested" : ""; // Check data structure here 729 var publishingStatus = "FULL"; 730 var approvalStatus = "approved"; 731 var categoriesList = session.categoryItems; 732 var _categories = String.Join(",", categoriesList.ToArray()); 733 string categories = ""; 734 735 var attributes = sessionizeAttributes.Where(item => categoriesList.Any(category => category == item.attributeId)); 736 string sessionDetailLinkAdjusted = sessionDetailLink.IndexOf("?") > 0 ? sessionDetailLink + "&session=" + session.id : sessionDetailLink + "?session=" + session.id; 737 string sessionTitle = makeStringReadable(!string.IsNullOrEmpty(session.title) ? session.title : "TBD"); 738 string columnCss = currentSessions.Count() == 1 ? "g-col-12" : "g-col-lg-6 g-col-12"; 739 <div class="d-grid gap-3 @columnCss title border-bottom my-3 pb-3 @test"> 740 <div class="session-name" data-publishing="@publishingStatus" data-categories="@_categories" data-approval="@approvalStatus" data-code="@session.id"> 741 @if (publishingStatus == "FULL" && isBreak == "") 742 { 743 <a class="text-decoration-none fw-bold" href='@sessionDetailLinkAdjusted' data-id="@session.id"><h5 class="session-header">@sessionTitle</h5></a> 744 } 745 else 746 { 747 <h5 class="session-header fw-bold">@sessionTitle</h5> 748 } 749 </div> 750 751 <div class="mb-2"> 752 @RenderIcon("/Files/Templates/Designs/Swift/Assets/icons/map-pin.svg") 753 <span class="speaker-name">@sessionRoomName</span> 754 </div> 755 756 @if (attributes.Any()) 757 { 758 <div> 759 <p class="fw-bold mb-2 tags-text">@Translate("Tags")</p> 760 <div class="d-flex flex-wrap gap-2"> 761 @foreach (var attr in attributes) 762 { 763 <a class="session-tags text-decoration-underline fs-7" href="#" data-target="filter-sessions-@tabContentCount" id="@attr.attributeId">@attr.attributeName</a> 764 } 765 </div> 766 </div> 767 } 768 769 </div> 770 } 771 </div> 772 <!--Lecture end--> 773 } 774 } 775 </div> 776 </div> 777 </div> 778 </div> 779 780 tabContentCount += 1; 781 } 782 </div> 783 } 784 } 785 786 </div> 787 788 789 @helper RenderIcon(string icon) 790 { 791 if (System.IO.Path.GetExtension(icon).ToLower() == ".svg") 792 { 793 if (!icon.ToLower().Contains("none") && icon != string.Empty) 794 { 795 <span class="icon-auto"> 796 @ReadFile(icon) 797 </span> 798 } 799 } 800 } 801 <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/slim-select/2.6.0/slimselect.css" integrity="sha512-ijXMfMV6D0xH0UfHpPnqrwbw9cjd4AbjtWbdfVd204tXEtJtvL3TTNztvqqr9AbLcCiuNTvqHL5c9v2hOjdjpA==" crossorigin="anonymous" referrerpolicy="no-referrer" /> 802 <script src="https://cdnjs.cloudflare.com/ajax/libs/slim-select/2.6.0/slimselect.min.js" integrity="sha512-0E8oaoA2v32h26IycsmRDShtQ8kMgD91zWVBxdIvUCjU3xBw81PV61QBsBqNQpWkp/zYJZip8Ag3ifmzz1wCKQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>