irections emea 2025 poznan
4-6 November 2025 in Poznan, Poland

Directions EMEA 2025

Join us for Directions EMEA 2025 - experience the latest updates from Microsoft and the ecosystem while connecting with the entire Business Central community, including resellers, add-on providers, Microsoft, CSPs, MVPs, developers, consultants, sales and marketing professionals, and business leaders.  Fuel your motivation, inspiration, and success through sharing and collaboration.

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