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