4-6 November 2025 in Poznan, Poland
Directions EMEA 2025
Join us for Directions EMEA 2025 - experience the latest updates from Microsoft and the ecosystem while connecting with the entire Business Central community, including resellers, add-on providers, Microsoft, CSPs, MVPs, developers, consultants, sales and marketing professionals, and business leaders. Fuel your motivation, inspiration, and success through sharing and collaboration.
Error executing template "Designs/Swift/Paragraph/COMM_Schedule.cshtml" System.NullReferenceException: Object reference not set to an instance of an object. at CompiledRazorTemplates.Dynamic.RazorEngine_f3a882deba8a4cff91acb2820129d595.<>c__DisplayClass16_5.<Execute>b__11(Item room) in C:\inetpub\wwwroot\directions2023\Files\Templates\Designs\Swift\Paragraph\COMM_Schedule.cshtml:line 308 at System.Linq.Enumerable.WhereListIterator`1.MoveNext() at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source) at CompiledRazorTemplates.Dynamic.RazorEngine_f3a882deba8a4cff91acb2820129d595.Execute() in C:\inetpub\wwwroot\directions2023\Files\Templates\Designs\Swift\Paragraph\COMM_Schedule.cshtml:line 308 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> @using Dynamicweb.Frontend.Navigation @using Dynamicweb.Content.Items @using Dynamicweb.Frontend @using System.Web.Helpers @using System.Web @using System.Text @using System.Net @using System.Linq @using System @using System.Globalization @using Newtonsoft.Json @using Newtonsoft.Json.Linq @functions{ public bool IsValidUrl(string url) { if (string.IsNullOrWhiteSpace(url)) return false; return Uri.TryCreate(url, UriKind.Absolute, out Uri uriResult) && (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps); } static string GetJson(string address) { using (var client = new WebClient()) { client.Headers.Add("Content-Type", "application/json; charset=utf-8"); try { return client.DownloadString(address); } catch (InvalidCastException e) { return ""; } } } string makeStringReadable(string data){ string response = ""; if(data != "") { string myStr = data; myStr = myStr.Replace('’', '\'').Replace('‘', '\'').Replace('–','-'); byte[] bytes = Encoding.UTF8.GetBytes(myStr); response = Encoding.UTF8.GetString(bytes); response = response.Replace("\r\n", "<br>"); response = response.Replace("’", "'"); response = response.Replace("–","-"); } return response; } public class Root { public List<Session> sessions {get; set;} public List<Speaker> speakers {get; set;} //public List<Question> questions {get; set;} public List<Category> categories {get; set;} public List<Item> rooms {get; set;} } public class Session { public string id {get; set;} public string title {get; set;} public string description {get; set;} public DateTime? startsAt {get; set;} public DateTime? endsAt {get; set;} public bool isServiceSession {get; set;} public bool isPlenumSession {get; set;} public List<string> speakers {get; set;} public List<int> categoryItems {get; set;} public List<QuestionAnswers> questionAnswers {get; set;} public int? roomId {get; set;} public string room {get; set;} public string liveUrl {get; set;} public string recordingUrl {get; set;} public string status {get; set;} } public class Speaker { public string id {get; set;} public string firstName {get; set;} public string lastName {get; set;} public string bio {get; set;} public string tagLine {get; set;} public string profilePicture {get; set;} public bool isTopSpeaker {get; set;} public List<Link> links {get; set;} public List<string> sessions {get; set;} public string fullName {get; set;} public List<int> categoryItems {get; set;} public List<QuestionAnswers> questionAnswers {get; set;} } public class Category { public int id {get; set;} public string title {get; set;} public List<Item> items {get; set;} public int sort {get; set;} public string type {get; set;} } public class Link { public string title {get; set;} public string url {get; set;} public string linType {get; set;} } public class Item { public int id {get; set;} public string name {get; set;} public int sort {get; set;} } public class Timeslot { public string Code {get; set;} public DateTime? DateAndStart {get; set;} public DateTime? SlotDate {get; set;} public DateTime SlotDuration {get; set;} public string SlotEnd {get; set;} public string SlotStart {get; set;} public string Status {get; set;} } public class Attribute { public string categoryTitle {get; set;} public int categoryId {get; set;} public int categorySort {get; set;} public int attributeId {get; set;} public string attributeName {get; set;} public int attributeSort {get; set;} } public string GetTimeslot(Session session) { string code = session.startsAt != null && session.endsAt != null ? session.startsAt.ToString().GetHashCode().ToString("x") + session.endsAt.ToString().GetHashCode().ToString("x") : "UNDEFINED"; return code; } public class QuestionAnswers { public string questionId {get; set;} public string answerValue {get; set;} } public class Test { public List<QuestionAnswers> questionAnswers { get; set; } } } @{ var parentPages = Dynamicweb.Content.Services.Pages.GetAncestors(Pageview.Page.ID, true); Dynamicweb.Content.Page rootPage = parentPages.Any() ? parentPages.Where(x => x.ItemType == "COMM_EventSection").FirstOrDefault() : new Dynamicweb.Content.Page(); var item = Dynamicweb.Content.Services.Items.GetItem(rootPage.ItemType, rootPage.ItemId); var sessionizeCode = item?["SessionizeCode"].ToString() ?? ""; var eventCode = !string.IsNullOrEmpty(Model.Item?.GetString("SessionizeCode")) ? Model.Item?.GetString("SessionizeCode") : sessionizeCode; var title = Model.Item?.GetString("Title"); string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("Theme")) && Model.Item.GetRawValueString("Theme") != "no-theme" ? " theme " + Model.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : ""; string detailTheme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("DetailTheme")) && Model.Item.GetRawValueString("DetailTheme") != "no-theme" ? " theme " + Model.Item.GetRawValueString("DetailTheme").Replace(" ", "").Trim().ToLower() : ""; detailTheme = detailTheme != "" ? detailTheme : theme; string parentContainerCss = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["session"]) ? "" : "shadow rounded-7"; string sessionQueryParameter = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["session"]) ? Dynamicweb.Context.Current.Request.QueryString["session"] : string.Empty; string sessionDetailCss = !string.IsNullOrEmpty(sessionQueryParameter) ? "p-4 rounded-7" : string.Empty; theme = sessionQueryParameter != "" ? detailTheme : theme; var dateTimeFormatField = !string.IsNullOrEmpty(Model.Item?.GetString("DateFormat")) ? Model.Item?.GetString("DateFormat") : ""; bool isUsDateTime = dateTimeFormatField == "us"; string dateTimeFormat = isUsDateTime ? "MM-dd-yyyy" : "dd-MM-yyyy"; string timeFormat = isUsDateTime ? "hh:mm tt" : "HH:mm"; } <div class="h-100 @parentContainerCss @(theme) @sessionDetailCss schedule-container item_@Model.Item.SystemName.ToLower()"> @if (!string.IsNullOrEmpty(eventCode)) { int dayCounter = 1; int dayCounterTab = 1; string sessionizeAll = "https://sessionize.com/api/v2/" + eventCode + "/view/All"; string responseSessionizeAll = GetJson(sessionizeAll).ToString(); //responseSessionizeAll = makeStringReadable(responseSessionizeAll); Root responseResult = Newtonsoft.Json.JsonConvert.DeserializeObject<Root>(responseSessionizeAll); var sessionizeSessions = responseResult.sessions; var sessionizeCategories = responseResult.categories; //filter categories sessionizeCategories = sessionizeCategories.Any() ? sessionizeCategories.Where(x => (x.id != 34553) && (x.id != 34539)).ToList() :sessionizeCategories; var sessionizeSpeakers = responseResult.speakers; var sessionizeRooms = responseResult.rooms; var sessionizeDays = sessionizeSessions.Where(x => x.startsAt != null).Select(x => x.startsAt?.Date).Distinct(); List<Timeslot> sessionizeTimeslots = new List<Timeslot>(); foreach(var session in sessionizeSessions) { Timeslot slot = new Timeslot(); slot.Code = GetTimeslot(session); slot.DateAndStart = session.startsAt; slot.SlotDate = session.startsAt?.Date; slot.SlotEnd = session.endsAt?.ToString(timeFormat); // take into consideration US & EU time slot.SlotStart = session.startsAt?.ToString(timeFormat); // take into consideration US & EU time slot.Status = session.isServiceSession ? "SERVICE" : "SESSION"; sessionizeTimeslots.Add(slot); } List<Attribute> sessionizeAttributes = new List<Attribute>(); var filteredAttributes = new string []{"Product Category"}; List<string> filteredAttributesId = new List<string>{"35602","186478","186480","186481"}; List<string> filteredAttributesNames = new List<string>{"No","Yes"}; foreach(var category in sessionizeCategories) { foreach(var i in category.items) { if(!filteredAttributesNames.Contains(i.name)) { Attribute attribute = new Attribute(); attribute.categoryTitle = category.title; attribute.categoryId = category.id; attribute.categorySort = category.sort; attribute.attributeId = i.id; attribute.attributeName = i.name; attribute.attributeSort = i.sort; sessionizeAttributes.Add(attribute); } } } string sessionDetailLink = Dynamicweb.Context.Current.Request.RawUrl; //var filtersList = new string []{"CONTENT OWNER","PRODUCT","LEVEL","SESSION TYPE","TARGET AUDIENCE","LEARNING PATH"}; var filtersList = new string []{"SESSION TYPE","TARGET AUDIENCE","PRODUCT"}; var sessionTimeslots = sessionizeTimeslots.GroupBy(x => x.Code) .Select(grp => grp.First()).OrderBy(x => x.SlotDate) .ToList(); string[] dayNames = {"Pre-day","Day 1","Day 2","Day 3"}; int tabHeadingCount = 1; int tabContentCount = 1; int accordionCount = 1; string categoriesQueryParameter = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["categories"]) ? Dynamicweb.Context.Current.Request.QueryString["categories"] : string.Empty; string dayQueryParameter = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["day"]) ? DateTime.ParseExact(Dynamicweb.Context.Current.Request.QueryString["day"], dateTimeFormat, CultureInfo.InvariantCulture).ToString(dateTimeFormat) : string.Empty; List<Session> sessions = new List<Session>(); for (int i = 0; i < sessionizeSessions.Count; i++) { if (!string.IsNullOrEmpty(categoriesQueryParameter)) { var categories = categoriesQueryParameter?.Split(',')?.Select(Int32.Parse)?.ToList(); var sessionDay = sessionizeSessions[i].startsAt.Value.ToString(dateTimeFormat); // take into consideration US & EU time if (sessionDay == dayQueryParameter) { @* Filter current selected day's sessions based on applied category filters *@ if (sessionizeSessions[i].categoryItems.Any(cat => categories.Contains(cat))) { sessions.Add(sessionizeSessions[i]); } else { sessions.Remove(sessionizeSessions[i]); } } else { @* Keep sessions for other days *@ sessions.Add(sessionizeSessions[i]); } } else { @* Keep all sessions if no category filter is applied *@ sessions.Add(sessionizeSessions[i]); } } @* Filter current selected day sessions based on categories *@ if (!string.IsNullOrEmpty(categoriesQueryParameter)) { @* Filter only current selected date sessions *@ if (!string.IsNullOrEmpty(dayQueryParameter)) { // sessionizeSessions = sessionizeSessions.Where(session => session.startsAt.ToString("dd-MM-yyyy") == DateTime.Parse(dayQueryParameter)).ToList(); } var categories = categoriesQueryParameter?.Split(',')?.Select(Int32.Parse)?.ToList(); sessionizeSessions = sessionizeSessions.Where(session => categories.Any(cat => session.categoryItems.Contains(cat))).ToList(); } @* Session details page logic *@ if (!string.IsNullOrEmpty(sessionQueryParameter)) { var session = sessionizeSessions.Where(session => session.id == sessionQueryParameter).FirstOrDefault(); var room = sessionizeRooms.Where(room => room.id == session.roomId).FirstOrDefault(); var speakers = sessionizeSpeakers.Where(speaker => session.speakers.Contains(speaker.id)).ToList(); var sessionDay = session.startsAt?.ToString(dateTimeFormat); // take into consideration US & EU time var startTime = session.startsAt?.ToString(timeFormat); // take into consideration US & EU time var endTime = session.endsAt?.ToString(timeFormat); // take into consideration US & EU time var sessionTitle = makeStringReadable(!string.IsNullOrEmpty(session.title) ? session.title : "TBD"); var sessionDescription = session.description != null ? makeStringReadable(session.description) : ""; var roomName = room.name != null ? makeStringReadable(room.name) : ""; var currentPageUrl = Dynamicweb.Context.Current.Request.RawUrl.Split('?')[0]; var clearFiltersUrl = currentPageUrl + "?" + "day=" + sessionDay + "&session=" + session.id; var seeScheduleUrl = currentPageUrl + "?" + "day=" + sessionDay; string requestTypeParam = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["RequestType"]) ? "&RequestType=" + Dynamicweb.Context.Current.Request.QueryString["RequestType"] : ""; string layoutTemplate = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["LayoutTemplate"]) ? "&LayoutTemplate=" + Dynamicweb.Context.Current.Request.QueryString["LayoutTemplate"] : ""; seeScheduleUrl = seeScheduleUrl + requestTypeParam; seeScheduleUrl = seeScheduleUrl + layoutTemplate; bool renderPresentationContainer = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["RequestType"]) && Dynamicweb.Context.Current.Request.QueryString["RequestType"] == "External"; string recordingUrl = session.recordingUrl; string liveUrl = session.liveUrl; <div class="grid w-100"> <div class="g-col-lg-6 g-col-12 mb-3"> <p class="mb-3 fw-bold">@sessionDay</p> <h1 class="mb-3">@sessionTitle</h1> <div class="d-flex align-items-center gap-lg-4 gap-2 flex-wrap"> <span> @RenderIcon("/Files/Templates/Designs/Swift/Assets/icons/clock.svg") @startTime - @endTime </span> <span> @RenderIcon("/Files/Templates/Designs/Swift/Assets/icons/map-pin.svg") @roomName </span> <span> <a class="btn btn-secondary" href="@seeScheduleUrl">@RenderIcon("/Files/Templates/Designs/Swift/Assets/icons/calendar.svg") @Translate("Back to event schedule")</a> </span> </div> @if (renderPresentationContainer) { string sessionsUrl = "https://sessionize.com/api/v2/"+ eventCode + "/view/Sessions"; string response = GetJson(sessionsUrl).ToString(); JArray data = JArray.Parse(response); JObject[] currentSession = data[0]["sessions"].Where(o => (string)o["id"] == session.id).Select(o => (JObject)o).ToArray(); JArray questionsAndAnswers = currentSession[0]["questionAnswers"] != null ? (JArray)currentSession[0]["questionAnswers"] : null; <div class="presentation-container mt-3"> @if (questionsAndAnswers != null) { foreach (var element in questionsAndAnswers) { bool renderDownloadLink = element["answer"] != null && !string.IsNullOrEmpty(element["answer"].ToString()) && IsValidUrl(element["answer"].ToString()); if (renderDownloadLink) { <a class="btn btn-primary" href="@element["answer"]">@Translate("Download presentation")</a> } } } </div> } </div> <div class="g-col-lg-6 g-col-12 mb-3 pt-5"> @if(liveUrl != "" && liveUrl != null) { <div><p>@Translate("MeetMicrosoft_Text")</p></div> <div><p><a class="btn btn-primary" href="@liveUrl">@Translate("Booth Schedule")</a></p></div> } @if (sessionDescription != null) { <div> <p>@sessionDescription</p> </div> } </div> @if (speakers.Any()) { int categoryParameter = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["Category"]) ? Convert.ToInt32(Dynamicweb.Context.Current.Request.QueryString["Category"]) : 0; var groupedAttributes = sessionizeAttributes.GroupBy( attr => attr.categoryTitle, (key, g) => new { Title = key, Items = g.ToList() }); speakers = categoryParameter != 0 ? speakers.Where(speaker => speaker.categoryItems.Contains(categoryParameter)).ToList() : speakers; string headerTitle = Translate("Speakers") + ":"; <div class="g-col-12"> <div class="w-100"> <h4 class="mb-4">@headerTitle</h4> </div> @* Speakers wall *@ <div class="grid"> @for (int i = 0; i < speakers.Count(); i++) { var columnSize = "grid g-col-12"; string viewSpeakerInfoTranslate = Translate("View") + " " + speakers[i].fullName + " " + Translate("info"); string speakerName = speakers[i].fullName != null ? speakers[i].fullName.ToString() : ""; string speakerBio = speakers[i].bio != null ? speakers[i].bio.ToString() : ""; string speakerTagLine = speakers[i].tagLine != null ? speakers[i].tagLine.ToString() : ""; string speakerProfilePicture = speakers[i].profilePicture != null ? speakers[i].profilePicture.ToString() : ""; string speakerCategories = speakers[i].categoryItems != null ? String.Join(",", speakers[i].categoryItems) : ""; var speakerSession = sessions.Where(session => speakers[i].sessions.Contains(session.id)).FirstOrDefault(); var speakerSessions = sessions.Where(session => speakers[i].sessions.Contains(session.id)).ToList(); var sessionsTranslate = speakerSessions.Count() > 1 ? Translate("Sessions") : Translate("Session"); <div class="speaker @theme @columnSize gap-0 position-relative rounded-7" data-categories="@speakerCategories"> <div class="h-100 g-col-lg-7 g-col-12 order-last order-md-first max-h-45-em"> <div class="h-100 py-4 max-h-30-em"> <div> <a href="#" class="btn btn-link p-0 text-decoration-none" title="@viewSpeakerInfoTranslate" onclick="event.preventDefault(); new bootstrap.Modal(document.getElementById('SpeakerModal_@i')).show()"> <h4 class="text-start">@makeStringReadable(speakerName)</h4> </a> <p>@speakerTagLine</p> </div> <div class="d-flex flex-column gap-3 justify-content-between max-h-15-em overflow-auto"> <p class="m-0 pb-4">@makeStringReadable(speakerBio)</p> </div> @if (speakers[i].links.Any()) { <div class="d-flex gap-3 align-items-end position-absolute top-100 mt-negative-3-em"> @foreach (var link in speakers[i].links) { string icon = "/Files/Templates/Designs/Swift/Assets/icons/"; if (link.url.Contains("twitter")) { icon += "twitter.svg"; } else if (link.url.Contains("linkedin")) { icon += "linkedin.svg"; } else { icon += "link.svg"; } <a href="@link.url" title="@link.title" target="_blank"> @RenderIcon(icon) </a> } </div> } </div> </div> <div class="h-100 ratio g-col-lg-5 g-col-12 rounded-7" style="--bs-aspect-ratio: 100%;"> <a class="btn btn-link p-4" title="@viewSpeakerInfoTranslate" onclick="new bootstrap.Modal(document.getElementById('SpeakerModal_@i')).show()"> <img src="@speakerProfilePicture" class="w-100 h-100 rounded-7"></img> </a> </div> <div class="h-100 w-100 position-absolute cursor-pointer d-none"> <a class="btn btn-link stretched-link" title="@viewSpeakerInfoTranslate" onclick="new bootstrap.Modal(document.getElementById('SpeakerModal_@i')).show()"></a> </div> </div> <div class="modal fade modal-xl" id="SpeakerModal_@i"> <div class="modal-dialog"> <div class="modal-content @theme rounded-7"> <div class="modal-body p-0" id="SpeakerModalBodyContainer_@i"> <div class="close-container position-absolute p-3 end-0 m-3 bg-white rounded-7 z-index-9"> <button type="button" class="btn-close bg-dark z-index-9" data-bs-dismiss="modal" aria-label="Close"></button> </div> <div class="grid @theme gap-0 rounded-7"> <div class="h-100 g-col-lg-7 g-col-12 order-last order-md-first"> <div class="h-100 p-4 overflow-auto max-h-30-em"> <div> <h4>@makeStringReadable(speakerName)</h4> <p>@speakerTagLine</p> </div> <div class="d-flex flex-column gap-3 justify-content-between"> <p class="m-0">@makeStringReadable(speakerBio)</p> </div> <div class="mt-4 d-grid"> <p class="m-0 fw-bold">@sessionsTranslate</p> @foreach (var _item in speakerSessions) { var sessionLink = currentPageUrl.IndexOf("?") > 0 ? currentPageUrl + "&session=" + _item.id : currentPageUrl + "?session=" + _item.id; <a class="btn btn-link text-start p-0 mb-2" title="@_item.title" href="@sessionLink"> @_item.title </a> } </div> @if (speakers[i].links.Any()) { <div class="d-flex gap-3 align-items-end"> @foreach (var link in speakers[i].links) { string icon = "/Files/Templates/Designs/Swift/Assets/icons/"; if (link.url.Contains("twitter")) { icon += "twitter.svg"; } else if (link.url.Contains("linkedin")) { icon += "linkedin.svg"; } else { icon += "link.svg"; } <a href="@link.url" title="@link.title" target="_blank"> @RenderIcon(icon) </a> } </div> } </div> </div> <div class="h-100 ratio g-col-lg-5 g-col-12" style="--bs-aspect-ratio: 100%"> <img src="@speakerProfilePicture" class="rounded-7"></img> </div> </div> </div> </div> </div> </div> } </div> </div> } </div> } else { if(sessionizeDays.Count() > 1) { <nav class="tabs rounded-7"> <ul class="nav nav-tabs days-tabs bg-light-grey rounded-7-top" role="tablist"> @foreach (var day in sessionizeDays) { string dayDate = day?.ToString(dateTimeFormat); // take into consideration US & EU time string dayName = dayNames[tabHeadingCount - 1]; bool showCounterWithTabName = dayName == "Training" ? true : false; string tabAnchorRaw = showCounterWithTabName ? dayName + tabHeadingCount : dayName; string tabAnchor = "tabname" + tabAnchorRaw + tabHeadingCount; bool hasDayParam = !string.IsNullOrEmpty(dayQueryParameter); string activeClass = hasDayParam && dayQueryParameter == dayDate ? "active" : tabHeadingCount == 1 && !hasDayParam ? "active" : ""; string firstTabCss = tabHeadingCount == 1 ? "rounded-7-top-left" : ""; <li class="flex-mobile-auto @(firstTabCss)" role="presentation"> <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"> <span class="fw-bold">@dayName</span> <span>@dayDate</span> </a> </li> tabHeadingCount += 1; } </ul> </nav> } <div class="tab-content days-tabs-container p-lg-4 p-2 rounded-7-bottom"> @foreach (var day in sessionizeDays) { string dayClass = tabContentCount == 1 ? "active" : ""; string timeslotsDay = day?.ToString(dateTimeFormat); // take into consideration US & EU time string dayName = dayNames[tabContentCount - 1]; bool showCounterWithTabName = dayName == "Training" ? true : false; string tabAnchorRaw = showCounterWithTabName ? dayName + tabContentCount : dayName; string tabAnchor = "tabname" + tabAnchorRaw + tabContentCount; string dayAnchor = showCounterWithTabName ? dayName + tabContentCount : dayName; string dayID = "day" + tabContentCount; var daySessionsList = sessionizeSessions.Where(x => x.startsAt?.Date == day); var dayAttributes = new List<int>(); foreach(var daySession in daySessionsList) { dayAttributes.AddRange(daySession.categoryItems); } var dayAttributesFiltered = sessionizeAttributes.Where(item => dayAttributes.Any(filter => filter.Equals(item.attributeId))); //remove attribute categories based on filtersList dayAttributesFiltered = dayAttributesFiltered.Where(item => filtersList.Contains(item.categoryTitle.ToUpper())).ToList(); var dayAttributesCategories = dayAttributesFiltered.Select(item => item.categoryTitle).Distinct(); bool hasDayParam = !string.IsNullOrEmpty(dayQueryParameter); bool matchingDate = hasDayParam && (dayQueryParameter == timeslotsDay); var activeTabClass = matchingDate ? "active" : tabContentCount == 1 && !hasDayParam ? "active" : ""; var activeTabContainerClass = matchingDate ? "show" : tabContentCount == 1 && !hasDayParam ? "show" : ""; <div id="@tabAnchor" role="tabpanel" class="tab-pane @activeTabClass"> @*<!--Filters--> @if (dayAttributesFiltered.Any()) { <div class="grid"> <div class="g-col-lg-4 g-col-12"> <label class="fw-bold" for="filter-sessions-1">@Translate("Filter Sessions")</label> <select id="filter-sessions-@tabContentCount" name="filter-sessions" class="form-control select2-multiple filter-session-ref filter-session-trigger" multiple="multiple" data-date="@timeslotsDay"> @foreach (var category in dayAttributesFiltered) { //Take into consideration the dayParam var categories = !string.IsNullOrEmpty(categoriesQueryParameter) ? categoriesQueryParameter?.Split(',')?.Select(Int32.Parse)?.ToList() : null; var selected = !string.IsNullOrEmpty(categoriesQueryParameter) && categories.Contains(category.attributeId) ? "selected" : ""; <option @selected value='@category.attributeId'>@category.attributeName @category.categoryTitle</option> } </select> @if (!string.IsNullOrEmpty(categoriesQueryParameter)) { var clearFiltersUrl = Dynamicweb.Context.Current.Request.RawUrl.Split('?')[0] + "?" + "day=" + timeslotsDay; //include RequestType & LayoutTemplate params if present (embedded page scenario) string requestTypeParam = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["RequestType"]) ? "&RequestType=" + Dynamicweb.Context.Current.Request.QueryString["RequestType"] : ""; string layoutTemplate = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["LayoutTemplate"]) ? "&LayoutTemplate=" + Dynamicweb.Context.Current.Request.QueryString["LayoutTemplate"] : ""; clearFiltersUrl = clearFiltersUrl + requestTypeParam; clearFiltersUrl = clearFiltersUrl + layoutTemplate; <a class="btn btn-link" href="@clearFiltersUrl" title="Clear filters"> @Translate("Clear filters") </a> } </div> </div> } <div class="hidden"> <div class="filterData"> @foreach (var filter in filtersList) { string filterName = filter; } </div> </div> <!--FiltersEnd-->*@ <!--Filters--> @if (dayAttributesFiltered.Any()) { <div class="grid"> @foreach(var filterCategory in dayAttributesCategories) { string filterCategoryName = filterCategory; string filterLabel = Translate("Filter " + filterCategoryName); filterCategoryName = filterCategoryName.Replace(" ","-").ToLower(); var dayAttributesList = dayAttributesFiltered.OrderBy(item=>item.attributeName).Where(item=>item.categoryTitle == filterCategory).ToList(); <div class="g-col-lg-4 g-col-12"> <label class="fw-bold" for="filter-@filterCategoryName-@tabContentCount">@filterLabel</label> <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"> @foreach (var category in dayAttributesList) { @* Take into consideration the dayParam *@ var categories = !string.IsNullOrEmpty(categoriesQueryParameter) ? categoriesQueryParameter?.Split(',')?.Select(Int32.Parse)?.ToList() : null; var selected = !string.IsNullOrEmpty(categoriesQueryParameter) && categories.Contains(category.attributeId) ? "selected" : ""; <option @selected value='@category.attributeId'>@category.attributeName @category.categoryTitle</option> } </select> @if (!string.IsNullOrEmpty(categoriesQueryParameter)) { var clearFiltersUrl = Dynamicweb.Context.Current.Request.RawUrl.Split('?')[0] + "?" + "day=" + timeslotsDay; @* include RequestType & LayoutTemplate params if present (embedded page scenario) *@ string requestTypeParam = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["RequestType"]) ? "&RequestType=" + Dynamicweb.Context.Current.Request.QueryString["RequestType"] : ""; string layoutTemplate = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["LayoutTemplate"]) ? "&LayoutTemplate=" + Dynamicweb.Context.Current.Request.QueryString["LayoutTemplate"] : ""; clearFiltersUrl = clearFiltersUrl + requestTypeParam; clearFiltersUrl = clearFiltersUrl + layoutTemplate; <a class="btn btn-link clear-filters" href="@clearFiltersUrl" title="Clear filters" data-target-dropdown="filter-@filterCategoryName-@tabContentCount"> @Translate("Clear filters") </a> } </div> } </div> } <div class="hidden"> <div class="filterData"> @foreach (var filter in filtersList) { string filterName = filter; } </div> </div> <!--FiltersEnd--> <!-- Search field --> <div class="mt-3"> <label class="fw-bold" for="schedule-search-@tabContentCount">@Translate("Search sessions")</label> <input type="text" id="schedule-search-@tabContentCount" class="form-control schedule-search-input bg-white text-dark border" placeholder="@Translate("Search by title, speaker, tags...")" autocomplete="off" style="color: #212529 !important; --swift-foreground-color: #6c757d;" /> </div> <!-- Second level content start --> <div class="tab-content2 tab-content-schedule"> <!-- All sessions start --> <div id='@(dayID + "_allsessions")' class="tab-pane fade in @activeTabContainerClass"> <div class="panel-group mt-4" id="@(dayID + "_allsessions_timeline")"> <p class="not-found mb-0 d-none">@Translate("No items found.")</p> @foreach (var timeslot in sessionTimeslots.Where(x => x.SlotDate == day).OrderBy(x => x.DateAndStart)) { string timeslotCode = timeslot.Code; var start = timeslot.SlotStart; // take into consideration US & EU time var end = timeslot.SlotEnd; // take into consideration US & EU time var currentSessions = sessions.Where(x => GetTimeslot(x) == timeslotCode && x.startsAt?.Date == day); // filtered sessions list by day & categories [based on sessionizeSessions] if (currentSessions.Any()) { string breakSessionTheme = currentSessions.Any(session => session.isServiceSession) ? "theme ice-blue" : ""; string isBreakSession = currentSessions.Any(session => session.isServiceSession) ? "is-break" : ""; <!-- Lecture start --> <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=""> <div class="g-col-12 time-wrapper position-absolute py-3 px-4 ms-4 rounded-7-bottom"> <strong class="time" data-debug="">@start - @end</strong> </div> @foreach (var session in currentSessions) { var sessionRoom = sessionizeRooms.Where(x => x.id == session.roomId).FirstOrDefault(); string sessionRoomName = sessionRoom != null ? makeStringReadable(sessionRoom.name) : "N/A"; var isBreak = session.isServiceSession ? "full" : ""; var test = session.isServiceSession ? "tested" : ""; // Check data structure here var publishingStatus = "FULL"; var approvalStatus = "approved"; var categoriesList = session.categoryItems; var _categories = String.Join(",", categoriesList.ToArray()); string categories = ""; var attributes = sessionizeAttributes.Where(item => categoriesList.Any(category => category == item.attributeId)); // Build session detail link using the session's own day so the link remains // correct even when the page was loaded for a different day (e.g. after // applying a filter on Day 1 and then switching to Day 2 client-side). var sessionDayForLink = session.startsAt?.ToString(dateTimeFormat); string sessionDetailBase = sessionDetailLink.Split('?')[0]; string categoriesParamForLink = !string.IsNullOrEmpty(categoriesQueryParameter) ? "&categories=" + categoriesQueryParameter : ""; string requestTypeForLink = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["RequestType"]) ? "&RequestType=" + Dynamicweb.Context.Current.Request.QueryString["RequestType"] : ""; string layoutTemplateForLink = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["LayoutTemplate"]) ? "&LayoutTemplate=" + Dynamicweb.Context.Current.Request.QueryString["LayoutTemplate"] : ""; string sessionDetailLinkAdjusted = sessionDetailBase + "?day=" + sessionDayForLink + categoriesParamForLink + requestTypeForLink + layoutTemplateForLink + "&session=" + session.id; string sessionTitle = makeStringReadable(!string.IsNullOrEmpty(session.title) ? session.title : "TBD"); string columnCss = currentSessions.Count() == 1 ? "g-col-12" : "g-col-lg-6 g-col-12"; var sessionSpeakerNames = sessionizeSpeakers.Where(sp => session.speakers.Contains(sp.id)).Select(sp => sp.fullName); var sessionTagNames = attributes.Select(a => a.attributeName); string searchData = string.Join(" ", new [] { sessionTitle, string.Join(" ", sessionSpeakerNames), string.Join(" ", sessionTagNames), sessionRoomName, session.description ?? "" }).ToLower(); <div class="d-grid gap-3 @columnCss title border-bottom my-3 pb-3 @test" data-search="@searchData"> <div class="session-name" data-publishing="@publishingStatus" data-categories="@_categories" data-approval="@approvalStatus" data-code="@session.id"> @if (publishingStatus == "FULL" && isBreak == "") { <a class="text-decoration-none fw-bold" href='@sessionDetailLinkAdjusted' data-id="@session.id"><h5 class="session-header">@sessionTitle</h5></a> } else { <h5 class="session-header fw-bold">@sessionTitle</h5> } </div> <div class="mb-2"> @RenderIcon("/Files/Templates/Designs/Swift/Assets/icons/map-pin.svg") <span class="speaker-name">@sessionRoomName</span> </div> @if (attributes.Any()) { <div> <p class="fw-bold mb-2 tags-text">@Translate("Tags")</p> <div class="d-flex flex-wrap gap-2"> @foreach (var attr in attributes) { <a class="session-tags text-decoration-underline fs-7" href="#" data-target="filter-sessions-@tabContentCount" id="@attr.attributeId">@attr.attributeName</a> } </div> </div> } </div> } </div> <!--Lecture end--> } } </div> </div> </div> </div> tabContentCount += 1; } </div> } } </div> @helper RenderIcon(string icon) { if (System.IO.Path.GetExtension(icon).ToLower() == ".svg") { if (!icon.ToLower().Contains("none") && icon != string.Empty) { <span class="icon-auto"> @ReadFile(icon) </span> } } } <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" /> <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> <script> document.addEventListener('DOMContentLoaded', function () { // Schedule search functionality document.querySelectorAll('.schedule-search-input').forEach(function(input) { input.addEventListener('input', function() { var query = this.value.toLowerCase().trim(); var tabPane = this.closest('.tab-pane'); var scheduleItems = tabPane ? tabPane.querySelectorAll('.schedule-item') : []; var notFound = tabPane ? tabPane.querySelector('.not-found') : null; var visibleCount = 0; scheduleItems.forEach(function(item) { var sessionCards = item.querySelectorAll('.title[data-search]'); var hasMatch = false; if (query === '') { sessionCards.forEach(function(card) { card.classList.remove('d-none'); }); item.classList.remove('d-none'); visibleCount++; } else { sessionCards.forEach(function(card) { var searchData = card.getAttribute('data-search') || ''; if (searchData.indexOf(query) !== -1) { card.classList.remove('d-none'); hasMatch = true; } else { card.classList.add('d-none'); } }); if (hasMatch) { item.classList.remove('d-none'); visibleCount++; } else { item.classList.add('d-none'); } } }); if (notFound) { if (visibleCount === 0 && query !== '') { notFound.classList.remove('d-none'); } else { notFound.classList.add('d-none'); } } }); }); }); </script>