4 uk
21-22 March, 2024

Days of Knowledge UK 2024

Days of Knowledge is a Directions for Partners event focused on educating consultants and developers, sharing knowledge and upgrading Business Central professionals to enable quality customer solutions. Training and acquiring knowledge are the magic words at Days of Knowledge.

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