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_9af85c414f574319b5a0a45b141ad935.<>c__DisplayClass15_5.<Execute>b__11(Item room) in C:\inetpub\wwwroot\directions2023\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_9af85c414f574319b5a0a45b141ad935.Execute() in C:\inetpub\wwwroot\directions2023\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 item_@Model.Item.SystemName.ToLower()"> 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 if(sessionizeDays.Count() > 1) 542 { 543 <nav class="tabs rounded-7"> 544 <ul class="nav nav-tabs days-tabs bg-light-grey rounded-7-top" role="tablist"> 545 @foreach (var day in sessionizeDays) 546 { 547 string dayDate = day?.ToString(dateTimeFormat); // take into consideration US & EU time 548 string dayName = dayNames[tabHeadingCount - 1]; 549 bool showCounterWithTabName = dayName == "Training" ? true : false; 550 string tabAnchorRaw = showCounterWithTabName ? dayName + tabHeadingCount : dayName; 551 string tabAnchor = "tabname" + tabAnchorRaw + tabHeadingCount; 552 bool hasDayParam = !string.IsNullOrEmpty(dayQueryParameter); 553 string activeClass = hasDayParam && dayQueryParameter == dayDate ? 554 "active" : tabHeadingCount == 1 && !hasDayParam ? "active" : ""; 555 556 string firstTabCss = tabHeadingCount == 1 ? "rounded-7-top-left" : ""; 557 558 <li class="flex-mobile-auto @(firstTabCss)" role="presentation"> 559 <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"> 560 <span class="fw-bold">@dayName</span> <span>@dayDate</span> 561 </a> 562 </li> 563 tabHeadingCount += 1; 564 } 565 </ul> 566 </nav> 567 } 568 <div class="tab-content days-tabs-container p-lg-4 p-2 rounded-7-bottom"> 569 @foreach (var day in sessionizeDays) 570 { 571 string dayClass = tabContentCount == 1 ? "active" : ""; 572 string timeslotsDay = day?.ToString(dateTimeFormat); // take into consideration US & EU time 573 string dayName = dayNames[tabContentCount - 1]; 574 bool showCounterWithTabName = dayName == "Training" ? true : false; 575 string tabAnchorRaw = showCounterWithTabName ? dayName + tabContentCount : dayName; 576 string tabAnchor = "tabname" + tabAnchorRaw + tabContentCount; 577 string dayAnchor = showCounterWithTabName ? dayName + tabContentCount : dayName; 578 string dayID = "day" + tabContentCount; 579 580 var daySessionsList = sessionizeSessions.Where(x => x.startsAt?.Date == day); 581 var dayAttributes = new List<int>(); 582 foreach(var daySession in daySessionsList) 583 { 584 dayAttributes.AddRange(daySession.categoryItems); 585 } 586 587 var dayAttributesFiltered = sessionizeAttributes.Where(item => dayAttributes.Any(filter => filter.Equals(item.attributeId))); 588 //remove attribute categories based on filtersList 589 dayAttributesFiltered = dayAttributesFiltered.Where(item => filtersList.Contains(item.categoryTitle.ToUpper())).ToList(); 590 var dayAttributesCategories = dayAttributesFiltered.Select(item => item.categoryTitle).Distinct(); 591 592 bool hasDayParam = !string.IsNullOrEmpty(dayQueryParameter); 593 bool matchingDate = hasDayParam && (dayQueryParameter == timeslotsDay); 594 var activeTabClass = matchingDate ? 595 "active" : tabContentCount == 1 && !hasDayParam ? "active" : ""; 596 597 var activeTabContainerClass = matchingDate ? 598 "show" : tabContentCount == 1 && !hasDayParam ? "show" : ""; 599 600 <div id="@tabAnchor" role="tabpanel" class="tab-pane @activeTabClass"> 601 602 @*<!--Filters--> 603 @if (dayAttributesFiltered.Any()) 604 { 605 <div class="grid"> 606 <div class="g-col-lg-4 g-col-12"> 607 <label class="fw-bold" for="filter-sessions-1">@Translate("Filter Sessions")</label> 608 <select id="filter-sessions-@tabContentCount" name="filter-sessions" class="form-control select2-multiple filter-session-ref filter-session-trigger" multiple="multiple" data-date="@timeslotsDay"> 609 @foreach (var category in dayAttributesFiltered) 610 { 611 //Take into consideration the dayParam 612 var categories = !string.IsNullOrEmpty(categoriesQueryParameter) ? categoriesQueryParameter?.Split(',')?.Select(Int32.Parse)?.ToList() : null; 613 var selected = !string.IsNullOrEmpty(categoriesQueryParameter) && categories.Contains(category.attributeId) ? "selected" : ""; 614 <option @selected value='@category.attributeId'>@category.attributeName @category.categoryTitle</option> 615 } 616 </select> 617 @if (!string.IsNullOrEmpty(categoriesQueryParameter)) 618 { 619 var clearFiltersUrl = Dynamicweb.Context.Current.Request.RawUrl.Split('?')[0] + "?" + "day=" + timeslotsDay; 620 //include RequestType & LayoutTemplate params if present (embedded page scenario) 621 string requestTypeParam = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["RequestType"]) ? 622 "&RequestType=" + Dynamicweb.Context.Current.Request.QueryString["RequestType"] : ""; 623 string layoutTemplate = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["LayoutTemplate"]) ? 624 "&LayoutTemplate=" + Dynamicweb.Context.Current.Request.QueryString["LayoutTemplate"] : ""; 625 626 clearFiltersUrl = clearFiltersUrl + requestTypeParam; 627 clearFiltersUrl = clearFiltersUrl + layoutTemplate; 628 <a class="btn btn-link" href="@clearFiltersUrl" title="Clear filters"> 629 @Translate("Clear filters") 630 </a> 631 } 632 </div> 633 </div> 634 } 635 636 <div class="hidden"> 637 <div class="filterData"> 638 @foreach (var filter in filtersList) 639 { 640 string filterName = filter; 641 } 642 </div> 643 </div> 644 645 <!--FiltersEnd-->*@ 646 647 <!--Filters--> 648 @if (dayAttributesFiltered.Any()) 649 { 650 <div class="grid"> 651 @foreach(var filterCategory in dayAttributesCategories) 652 { 653 string filterCategoryName = filterCategory; 654 string filterLabel = Translate("Filter " + filterCategoryName); 655 filterCategoryName = filterCategoryName.Replace(" ","-").ToLower(); 656 var dayAttributesList = dayAttributesFiltered.OrderBy(item=>item.attributeName).Where(item=>item.categoryTitle == filterCategory).ToList(); 657 658 <div class="g-col-lg-4 g-col-12"> 659 <label class="fw-bold" for="filter-@filterCategoryName-@tabContentCount">@filterLabel</label> 660 <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"> 661 @foreach (var category in dayAttributesList) 662 { 663 @* Take into consideration the dayParam *@ 664 var categories = !string.IsNullOrEmpty(categoriesQueryParameter) ? categoriesQueryParameter?.Split(',')?.Select(Int32.Parse)?.ToList() : null; 665 var selected = !string.IsNullOrEmpty(categoriesQueryParameter) && categories.Contains(category.attributeId) ? "selected" : ""; 666 <option @selected value='@category.attributeId'>@category.attributeName @category.categoryTitle</option> 667 } 668 </select> 669 @if (!string.IsNullOrEmpty(categoriesQueryParameter)) 670 { 671 var clearFiltersUrl = Dynamicweb.Context.Current.Request.RawUrl.Split('?')[0] + "?" + "day=" + timeslotsDay; 672 @* include RequestType & LayoutTemplate params if present (embedded page scenario) *@ 673 string requestTypeParam = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["RequestType"]) ? 674 "&RequestType=" + Dynamicweb.Context.Current.Request.QueryString["RequestType"] : ""; 675 string layoutTemplate = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["LayoutTemplate"]) ? 676 "&LayoutTemplate=" + Dynamicweb.Context.Current.Request.QueryString["LayoutTemplate"] : ""; 677 678 clearFiltersUrl = clearFiltersUrl + requestTypeParam; 679 clearFiltersUrl = clearFiltersUrl + layoutTemplate; 680 <a class="btn btn-link clear-filters" href="@clearFiltersUrl" title="Clear filters" data-target-dropdown="filter-@filterCategoryName-@tabContentCount"> 681 @Translate("Clear filters") 682 </a> 683 } 684 </div> 685 686 } 687 </div> 688 } 689 690 <div class="hidden"> 691 <div class="filterData"> 692 @foreach (var filter in filtersList) 693 { 694 string filterName = filter; 695 } 696 </div> 697 </div> 698 699 <!--FiltersEnd--> 700 701 702 <!-- Second level content start --> 703 <div class="tab-content2 tab-content-schedule"> 704 <!-- All sessions start --> 705 <div id='@(dayID + "_allsessions")' class="tab-pane fade in @activeTabContainerClass"> 706 <div class="panel-group mt-4" id="@(dayID + "_allsessions_timeline")"> 707 <p class="not-found mb-0 d-none">@Translate("No items found.")</p> 708 @foreach (var timeslot in sessionTimeslots.Where(x => x.SlotDate == day).OrderBy(x => x.DateAndStart)) 709 { 710 string timeslotCode = timeslot.Code; 711 var start = timeslot.SlotStart; // take into consideration US & EU time 712 var end = timeslot.SlotEnd; // take into consideration US & EU time 713 var currentSessions = sessions.Where(x => GetTimeslot(x) == timeslotCode); // filtered sessions list by day & categories [based on sessionizeSessions] 714 715 if (currentSessions.Any()) 716 { 717 string breakSessionTheme = currentSessions.Any(session => session.isServiceSession) ? "theme ice-blue" : ""; 718 string isBreakSession = currentSessions.Any(session => session.isServiceSession) ? "is-break" : ""; 719 <!-- Lecture start --> 720 <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=""> 721 <div class="g-col-12 time-wrapper position-absolute py-3 px-4 ms-4 rounded-7-bottom"> 722 <strong class="time" data-debug="">@start - @end</strong> 723 </div> 724 @foreach (var session in currentSessions) 725 { 726 727 var sessionRoom = sessionizeRooms.Where(x => x.id == session.roomId).FirstOrDefault(); 728 string sessionRoomName = sessionRoom != null ? makeStringReadable(sessionRoom.name) : "N/A"; 729 var isBreak = session.isServiceSession ? "full" : ""; 730 var test = session.isServiceSession ? "tested" : ""; // Check data structure here 731 var publishingStatus = "FULL"; 732 var approvalStatus = "approved"; 733 var categoriesList = session.categoryItems; 734 var _categories = String.Join(",", categoriesList.ToArray()); 735 string categories = ""; 736 737 var attributes = sessionizeAttributes.Where(item => categoriesList.Any(category => category == item.attributeId)); 738 string sessionDetailLinkAdjusted = sessionDetailLink.IndexOf("?") > 0 ? sessionDetailLink + "&session=" + session.id : sessionDetailLink + "?session=" + session.id; 739 string sessionTitle = makeStringReadable(!string.IsNullOrEmpty(session.title) ? session.title : "TBD"); 740 string columnCss = currentSessions.Count() == 1 ? "g-col-12" : "g-col-lg-6 g-col-12"; 741 <div class="d-grid gap-3 @columnCss title border-bottom my-3 pb-3 @test"> 742 <div class="session-name" data-publishing="@publishingStatus" data-categories="@_categories" data-approval="@approvalStatus" data-code="@session.id"> 743 @if (publishingStatus == "FULL" && isBreak == "") 744 { 745 <a class="text-decoration-none fw-bold" href='@sessionDetailLinkAdjusted' data-id="@session.id"><h5 class="session-header">@sessionTitle</h5></a> 746 } 747 else 748 { 749 <h5 class="session-header fw-bold">@sessionTitle</h5> 750 } 751 </div> 752 753 <div class="mb-2"> 754 @RenderIcon("/Files/Templates/Designs/Swift/Assets/icons/map-pin.svg") 755 <span class="speaker-name">@sessionRoomName</span> 756 </div> 757 758 @if (attributes.Any()) 759 { 760 <div> 761 <p class="fw-bold mb-2 tags-text">@Translate("Tags")</p> 762 <div class="d-flex flex-wrap gap-2"> 763 @foreach (var attr in attributes) 764 { 765 <a class="session-tags text-decoration-underline fs-7" href="#" data-target="filter-sessions-@tabContentCount" id="@attr.attributeId">@attr.attributeName</a> 766 } 767 </div> 768 </div> 769 } 770 771 </div> 772 } 773 </div> 774 <!--Lecture end--> 775 } 776 } 777 </div> 778 </div> 779 </div> 780 </div> 781 782 tabContentCount += 1; 783 } 784 </div> 785 } 786 } 787 788 </div> 789 790 791 @helper RenderIcon(string icon) 792 { 793 if (System.IO.Path.GetExtension(icon).ToLower() == ".svg") 794 { 795 if (!icon.ToLower().Contains("none") && icon != string.Empty) 796 { 797 <span class="icon-auto"> 798 @ReadFile(icon) 799 </span> 800 } 801 } 802 } 803 <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" /> 804 <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>