16-17 May 2024

Directions ASIA 2024

Directions ASIA is focusing on bringing state-of-the-art keynotes and sessions about how the SMB market can unlock their full technological potential with ERP, CRM and Cloud solutions in the form of the Microsoft Power Platform, Microsoft Dynamics 365 Business Central, and Azure.

 

 

Home video

NUEVA EDICION 8 Abril 2025

Business Central en Español 2025

BC Day ES 2025, es un evento para usuarios y profesionales de Dynamics 365 Business Central que se celebra en España. Aquí podrás aprender y compartir, tanto en la parte técnica como en la parte funcional, en Español. La participación es gratuita pero es necesario registrase ya que las plazas son limitadas.

 

Home video

7-9 May 2025

Directions ASIA 2025

Directions ASIA is expanding to a 3-day conference in 2025, with an even greater focus on learning and growth. Join us again in Bangkok, where you’ll enjoy exceptional hospitality and a culinary experience like no other, for the latest updates from Microsoft and the ecosystem. Connect with the entire Dynamics 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.

Interested in sponsoring? Click here to contact our sponsor team.

The Directions EMEA 2023 calendar

Check the program

The session schedule is live! Dive into three exciting conference days packed with 3 keynotes, 200+ sessions, 15 workshops, and 20 roundtables. To make the most of your conference experience, start personalizing your schedule in the app. 

This year, we're optimizing session rooms based on your preferences from the app, so be sure to add the sessions you'd like to attend in advance. Check the app to ensure you're heading to the correct room for each session. 

Collect your badge at the registration area
18:00 - 20:00
Welcome Reception
18:00 - 20:00
Collect your badge at the registration area
07:00 - 09:00
Keynote day 1
09:00 - 10:45
Coffee break in the expo area
10:45 - 11:15
Sessions
11:15 - 13:00
Lunch in the expo area
13:00 - 14:00
Sessions
14:00 - 18:00
Coffee break in the expo area
15:45 - 16:15
Evening reception in the expo area
18:00 - 20:00
Keynote day 2
09:00 - 10:45
Coffee break in expo area
10:45 - 11:15
Sessions
11:15 - 13:00
Lunch in the expo area
13:00 - 14:00
Sessions
14:00 - 18:00
Coffee break in the expo area
15:45 - 16:15
Expo
18:00 - 19:00
Community Party
19:00 - 00:00
Keynote day 3
09:00 - 10:00
Coffee break in expo area
10:00 - 10:30
Sessions
10:30 - 14:30
Coffee break with snacks
12:15 - 12:45
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_73a9861be881419e970c6b31b245998b.Execute() in C:\inetpub\wwwroot\directions2023_uat\Files\Templates\Designs\Swift\Paragraph\COMM_Schedule.cshtml:line 164
   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--> <!-- 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"; <div class="d-grid gap-3 @columnCss title border-bottom my-3 pb-3 @test"> <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>