irections ho chi minh asia 2026
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.

 

Error executing template "Designs/Swift/Paragraph/COMM_SpeakerWall.cshtml"
System.Net.WebException: The remote server returned an error: (404) Not Found.
   at System.Net.WebClient.DownloadDataInternal(Uri address, WebRequest& request)
   at System.Net.WebClient.DownloadString(Uri address)
   at CompiledRazorTemplates.Dynamic.RazorEngine_2dadb039c9d8481eae31b70d9a2fbf8c.GetJson(String address) in C:\inetpub\wwwroot\directions2023\Files\Templates\Designs\Swift\Paragraph\COMM_SpeakerWall.cshtml:line 145
   at CompiledRazorTemplates.Dynamic.RazorEngine_2dadb039c9d8481eae31b70d9a2fbf8c.Execute() in C:\inetpub\wwwroot\directions2023\Files\Templates\Designs\Swift\Paragraph\COMM_SpeakerWall.cshtml:line 260
   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 16 @functions{ 17 18 19 public class Root 20 { 21 public List<Session> sessions {get; set;} 22 public List<Speaker> speakers {get; set;} 23 public List<Category> categories {get; set;} 24 } 25 26 public class Session 27 { 28 public string id {get; set;} 29 public string title {get; set;} 30 public string description {get; set;} 31 public DateTime? startsAt {get; set;} 32 public DateTime? endsAt {get; set;} 33 public bool isServiceSession {get; set;} 34 public bool isPlenumSession {get; set;} 35 public List<string> speakers {get; set;} 36 public List<int> categoryItems {get; set;} 37 public List<QuestionAnswers> questionAnswers {get; set;} 38 public int? roomId {get; set;} 39 //liveUrl 40 //recordingUrl 41 } 42 43 public class categoryItems 44 { 45 public string name { get; set; } 46 } 47 // For Speaker class 48 public class sessions 49 { 50 public int id { get; set; } 51 public string name { get; set; } 52 } 53 // For Speaker class 54 public class categories 55 { 56 public int id { get; set; } 57 public string name { get; set; } 58 public List<Item> categoryItems {get; set;} 59 public int sort { get; set; } 60 } 61 62 public class Speaker 63 { 64 public string id {get; set;} 65 public string firstName {get; set;} 66 public string lastName {get; set;} 67 public string bio {get; set;} 68 public string tagLine {get; set;} 69 public string profilePicture {get; set;} 70 public bool isTopSpeaker {get; set;} 71 public List<Link> links {get; set;} 72 73 public List<sessions> sessions {get; set;} 74 public List<categories> categories { get; set; } 75 public string fullName {get; set;} 76 public List<int> categoryItems {get; set;} 77 public List<QuestionAnswers> questionAnswers {get; set;} 78 public int displayPriority {get; set;} 79 } 80 81 public class Category 82 { 83 public int id {get; set;} 84 public string title {get; set;} 85 public List<Item> items {get; set;} 86 public int sort {get; set;} 87 public string type {get; set;} 88 } 89 90 public class Link 91 { 92 public string title {get; set;} 93 public string url {get; set;} 94 public string linType {get; set;} 95 } 96 97 public class Item 98 { 99 public int id {get; set;} 100 public string name {get; set;} 101 public int sort {get; set;} 102 } 103 104 public class Timeslot 105 { 106 public string Code {get; set;} 107 public DateTime? DateAndStart {get; set;} 108 public DateTime? SlotDate {get; set;} 109 public DateTime SlotDuration {get; set;} 110 public string SlotEnd {get; set;} 111 public string SlotStart {get; set;} 112 public string Status {get; set;} 113 114 } 115 116 public class Attribute 117 { 118 public string categoryTitle {get; set;} 119 public int categoryId {get; set;} 120 public int categorySort {get; set;} 121 public int attributeId {get; set;} 122 public string attributeName {get; set;} 123 public int attributeSort {get; set;} 124 } 125 126 public string GetTimeslot(Session session) 127 { 128 string code = session.startsAt != null && session.endsAt != null ? session.startsAt.ToString().GetHashCode().ToString("x") + session.endsAt.ToString().GetHashCode().ToString("x") : "UNDEFINED"; 129 return code; 130 } 131 132 public class QuestionAnswers 133 { 134 public string questionId {get; set;} 135 public string answerValue {get; set;} 136 } 137 138 static string GetJson(string address) 139 { 140 using (var client = new WebClient()) 141 { 142 client.Headers.Add("Content-Type", "application/json"); 143 try 144 { 145 return client.DownloadString(address); 146 } 147 catch (InvalidCastException e) 148 { 149 return ""; 150 } 151 } 152 } 153 154 string makeStringReadable(string data){ 155 string myStr = data; 156 byte[] bytes = Encoding.Default.GetBytes(myStr); 157 return Encoding.UTF8.GetString(bytes); 158 } 159 //we define variables for acces in other helpers 160 string theme = ""; 161 bool showSummary = false; 162 string sessionDetailsPage = ""; 163 } 164 165 166 @{ 167 var parentPages = Dynamicweb.Content.Services.Pages.GetAncestors(Pageview.Page.ID, true); 168 Dynamicweb.Content.Page rootPage = parentPages.Any() ? parentPages.Where(x => x.ItemType == "COMM_EventSection").FirstOrDefault() : new Dynamicweb.Content.Page(); 169 theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("Theme")) && Model.Item.GetRawValueString("Theme") != "no-theme" ? " theme " + Model.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : ""; 170 171 var item = Dynamicweb.Content.Services.Items.GetItem(rootPage.ItemType, rootPage.ItemId); 172 var sessionizeCode = item?["SessionizeCode"].ToString() ?? ""; 173 var parentTheme = !string.IsNullOrEmpty(item?["Theme"].ToString()) ? "theme " + item?["Theme"].ToString() : ""; 174 var eventCode = !string.IsNullOrEmpty(Model.Item?.GetString("SessionizeCode")) ? Model.Item?.GetString("SessionizeCode") : sessionizeCode; 175 sessionDetailsPage = !string.IsNullOrEmpty(Model.Item?.GetString("SessionDetailPage")) ? Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl(Model.Item?.GetString("SessionDetailPage")) : ""; 176 177 theme = theme != "" ? theme : parentTheme; 178 179 showSummary = Model.Item.GetBoolean("ShowSummaryOnly"); 180 181 string eyebrow = Model.Item.GetString("Eyebrow", string.Empty).Replace(System.Environment.NewLine, "<br>"); 182 string eyebrowHeadingLevel = Model.Item.GetString("EyebrowHeadingLevel", "h3"); 183 string eyebrowFontSize = Model.Item.GetRawValueString("EyebrowFontSize", "h5"); 184 string eyebrowColor = Model.Item.GetString("EyebrowColor", "text-inherit"); 185 string eyebrowTextOpacity = Model.Item.GetString("EyebrowTextOpacity", "opacity-100"); 186 string eyebrowCssClass = Model.Item.GetString("EyebrowCssClass", string.Empty); 187 string eyebrowSpacingBottomDesktop = Model.Item.GetRawValueString("EyebrowSpacingBottomDesktop", "default"); 188 eyebrowSpacingBottomDesktop = eyebrowSpacingBottomDesktop != "default" ? eyebrowSpacingBottomDesktop : string.Empty; 189 string eyebrowSpacingBottomMobile = Model.Item.GetRawValueString("EyebrowSpacingBottomMobile", "default"); 190 eyebrowSpacingBottomMobile = eyebrowSpacingBottomMobile != "default" ? eyebrowSpacingBottomMobile : string.Empty; 191 192 string title = Model.Item.GetString("Title", string.Empty).Replace(System.Environment.NewLine, "<br>"); 193 string titleHeadingLevel = Model.Item.GetString("TitleHeadingLevel", "h2"); 194 string titleFontSize = Model.Item.GetRawValueString("TitleFontSize", "h2"); 195 string titleColor = Model.Item.GetString("TitleColor", "text-inherit"); 196 string titleTextOpacity = Model.Item.GetString("TitleTextOpacity", "opacity-100"); 197 string titleCssClass = Model.Item.GetString("TitleCssClass", string.Empty); 198 string titleSpacingBottomDesktop = Model.Item.GetRawValueString("TitleSpacingBottomDesktop", "default"); 199 titleSpacingBottomDesktop = titleSpacingBottomDesktop != "default" ? titleSpacingBottomDesktop : string.Empty; 200 string titleSpacingBottomMobile = Model.Item.GetRawValueString("TitleSpacingBottomMobile", "default"); 201 titleSpacingBottomMobile = titleSpacingBottomMobile != "default" ? titleSpacingBottomMobile : string.Empty; 202 203 string subtitle = Model.Item.GetString("Subtitle", string.Empty).Replace(System.Environment.NewLine, "<br>"); 204 string subtitleHeadingLevel = Model.Item.GetString("SubtitleHeadingLevel", "p"); 205 string subtitleFontSize = Model.Item.GetRawValueString("SubtitleFontSize", "fs-5"); 206 string subtitleColor = Model.Item.GetString("SubtitleColor", "text-inherit"); 207 string subtitleTextOpacity = Model.Item.GetString("SubtitleTextOpacity", "opacity-100"); 208 string subtitleCssClass = Model.Item.GetString("SubtitleCssClass", string.Empty); 209 string subtitleSpacingBottomDesktop = Model.Item.GetRawValueString("SubtitleSpacingBottomDesktop", "default"); 210 subtitleSpacingBottomDesktop = subtitleSpacingBottomDesktop != "default" ? subtitleSpacingBottomDesktop : string.Empty; 211 string subtitleSpacingBottomMobile = Model.Item.GetRawValueString("SubtitleSpacingBottomMobile", "default"); 212 subtitleSpacingBottomMobile = subtitleSpacingBottomMobile != "default" ? subtitleSpacingBottomMobile : string.Empty; 213 214 //Button 1 215 var button1Link = Model.Item.GetLink("Button1Link"); 216 var button1Label = Model.Item.GetString("Button1Label", string.Empty); 217 var button1Icon = Model.Item.GetRawValueString("Button1Icon"); 218 var button1IconPosition = Model.Item.GetRawValueString("Button1IconPosition", "right"); 219 var button1Style = Model.Item.GetRawValueString("Button1Style", "btn-primary"); 220 221 //Button 2 222 var button2Link = Model.Item.GetLink("Button2Link"); 223 var button2Label = Model.Item.GetString("Button2Label", string.Empty); 224 var button2Icon = Model.Item.GetRawValueString("Button2Icon"); 225 var button2IconPosition = Model.Item.GetRawValueString("Button2IconPosition", "right"); 226 var button2Style = Model.Item.GetRawValueString("Button2Style", "btn-primary"); 227 228 string contentAlignment = "align-items-center justify-content-center"; 229 string contentTextAlignment = "text-start"; 230 231 string renderTextCss = showSummary ? "d-none" : ""; 232 233 string layout = Model.Item.GetRawValueString("DisplayMode"); 234 string gridLayout = Model.Item.GetRawValueString("GridLayout"); 235 236 } 237 238 <div class="h-100 item_@Model.Item.SystemName.ToLower()"> 239 <div class="@renderTextCss"> 240 @if (!string.IsNullOrEmpty(eyebrow)) 241 { 242 @RenderContent(eyebrow, eyebrowHeadingLevel, eyebrowFontSize, eyebrowColor, eyebrowTextOpacity, eyebrowSpacingBottomDesktop, eyebrowSpacingBottomMobile, eyebrowCssClass) 243 } 244 245 @if (!string.IsNullOrEmpty(title)) 246 { 247 @RenderContent(title, titleHeadingLevel, titleFontSize, titleColor, titleTextOpacity, titleSpacingBottomDesktop, titleSpacingBottomMobile, titleCssClass) 248 } 249 250 @if (!string.IsNullOrEmpty(subtitle)) 251 { 252 @RenderContent(subtitle, subtitleHeadingLevel, subtitleFontSize, subtitleColor, subtitleTextOpacity, subtitleSpacingBottomDesktop, subtitleSpacingBottomMobile, subtitleCssClass) 253 } 254 </div> 255 256 @if (!string.IsNullOrEmpty(eventCode)) 257 { 258 259 string sessionizeSpeakers = "https://sessionize.com/api/v2/"+ sessionizeCode + "/view/Speakers"; 260 string response = GetJson(sessionizeSpeakers).ToString(); 261 var speakers = JsonConvert.DeserializeObject<List<Speaker>>(response); 262 263 //extend speakers with DisplayPriority property 264 List<Speaker> updatedSpeakers = new List<Speaker>(); 265 foreach(var speaker in speakers) 266 { 267 var speakerCategories = speaker.categories; 268 var speakerDisplayPriorities = speakerCategories != null ? speakerCategories.Where(c => c.name =="DisplayPriority")?.FirstOrDefault() : new categories(); 269 var categoryItems = speakerDisplayPriorities != null ? speakerDisplayPriorities.categoryItems : new List<Item>(); 270 Item priority = categoryItems.Any() ? categoryItems.FirstOrDefault() : new Item();//speaker.categories != null ? speaker.categories.Where(c => c.name =="DisplayPriority")?.FirstOrDefault().categoryItems?.FirstOrDefault() : new Item(); 271 //var priority = speaker.categories.Where(c => c.name =="DisplayPriority")?.FirstOrDefault().categoryItems?.FirstOrDefault();// : new Item(); 272 273 274 Speaker updatedSpeaker = new Speaker(); 275 updatedSpeaker = speaker; 276 updatedSpeaker.displayPriority = priority.name != null ? Dynamicweb.Core.Converter.ToInt32(priority.name) : 99; 277 updatedSpeakers.Add(updatedSpeaker); 278 } 279 280 //sort speakers by display priority 281 speakers = updatedSpeakers.OrderBy(x=>x.displayPriority).ThenBy(x=>x.lastName).ToList(); 282 if(speakers.Any()) 283 { 284 @RenderSpeakers(speakers , showSummary , theme , sessionDetailsPage, layout, gridLayout) 285 } 286 287 } 288 else 289 { 290 <div class="alert alert-info" role="alert"> 291 <span>@Translate("Missing sessionize Id")</span> 292 </div> 293 } 294 </div> 295 296 @helper RenderSpeakers(System.Collections.Generic.List<Speaker> speakers, bool showSummary , string theme , string sessionDetailsPage, string layout, string gridLayout) 297 { 298 string iconBadgeWidth = Model.Item.GetString("IconBadgeWidth"); 299 string iconBadgeHeight = Model.Item.GetString("IconBadgeHeight"); 300 301 var summaryCss = showSummary ? "grid-auto-rows-1-fr" : ""; 302 var gridCss = !showSummary ? "grid" : "container-lg p-0"; 303 int categoryParameter = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["Category"]) ? 304 Convert.ToInt32(Dynamicweb.Context.Current.Request.QueryString["Category"]) : 0; 305 306 bool isSlider = layout == "carousel"; 307 308 var filtersList = new string []{"SpeakerType"}; 309 310 bool hideSpeakerCategory = Model.Item.GetBoolean("HideSpeakerCategory"); 311 312 List<Attribute> sessionizeAttributes = new List<Attribute>(); 313 314 foreach (var speaker in speakers) 315 { 316 foreach(var category in speaker.categories) 317 { 318 foreach(var element in category.categoryItems) 319 { 320 if(category.name == "SpeakerType") 321 { 322 Attribute attribute = new Attribute(); 323 attribute.categoryTitle = category.name; 324 attribute.categoryId = category.id; 325 attribute.categorySort = category.sort; 326 attribute.attributeId = element.id; 327 attribute.attributeName = element.name; 328 // attribute.attributeSort = element.sort; 329 sessionizeAttributes.Add(attribute); 330 } 331 } 332 } 333 } 334 335 //Remove grouping 336 var groupedAttributes = sessionizeAttributes.GroupBy( 337 attr => attr.categoryTitle, 338 (key, g) => new { Title = key, Items = g.GroupBy(x => x.attributeId).Select(x => x.First()).ToList() }); 339 340 341 string categoryId = Model.Item.GetRawValueString("CategoryId"); 342 343 if (!showSummary && string.IsNullOrEmpty(categoryId)) 344 { 345 <div class="grid mb-3"> 346 @{ 347 Uri url = Dynamicweb.Context.Current.Request.Url; 348 var query = System.Web.HttpUtility.ParseQueryString(url.Query); 349 query.Remove("Category"); 350 var link = new UriBuilder( url ) { Query = query.ToString() }.Uri; 351 } 352 @foreach (var attrCollection in groupedAttributes) 353 { 354 foreach (var attr in attrCollection.Items.Where(item => item.attributeId == categoryParameter)) 355 { 356 <a href="@link" class="px-0 g-col-lg-3 g-col-12 btn btn-link btn-sm d-flex justify-content-between align-items-center"> 357 <span>@attrCollection.Title : @attr.attributeName</span> 358 <span class="btn-close btn-sm" aria-label="Close"></span> 359 </a> 360 } 361 } 362 </div> 363 <div class="grid mb-4"> 364 <div class="g-col-lg-3 g-col-12"> 365 <div class="form-group"> 366 <label class="fw-bold mb-2" for="searchSpeaker">@Translate("Search")</label> 367 <input type="search" class="form-control" id="searchSpeaker" placeholder="@Translate("Enter speaker name...")"></input> 368 </div> 369 </div> 370 371 <div class="g-col-lg-3 g-col-12"> 372 <label class="fw-bold mb-2" for="Category">@Translate("Category")</label> 373 <select class="form-control filter-session-ref filter-session-trigger speaker-category-dropdown-filter" id="Category" name="Category"> 374 <option value="">@Translate("Choose category")</option> 375 @foreach (var attrCollection in groupedAttributes) 376 { 377 @*<optgroup label="@attrCollection.Title">*@ 378 foreach (var attr in attrCollection.Items) 379 { 380 var selectedAttr = attr.attributeId == categoryParameter ? "selected" : ""; 381 <option value="@attr.attributeId" @selectedAttr>@attr.attributeName</option> 382 } 383 @*</optgroup>*@ 384 } 385 </select> 386 </div> 387 388 389 <div class="g-col-lg-3 g-col-12 d-flex justify-content-start align-items-end"> 390 <a class="btn btn-link p-0 clear-all-speaker-filters" data-params-to-remove="Category">@Translate("Clear all")</a> 391 </div> 392 </div> 393 } 394 395 396 if (speakers.Any()) 397 { 398 speakers = !string.IsNullOrEmpty(categoryId) ? speakers.Where(speaker => speaker.categories.Any(i => i.categoryItems.Any(cat => cat.id.ToString().Equals(categoryId)))).ToList() : speakers; 399 int summaryItemsCount = Model.Item.GetInt32("SummaryItemsCount"); 400 summaryItemsCount = summaryItemsCount > speakers.Count() ? speakers.Count() : summaryItemsCount; 401 int displayCount = showSummary ? summaryItemsCount : speakers.Count(); 402 403 404 if (showSummary) 405 { 406 string eyebrow = Model.Item.GetString("Eyebrow", string.Empty).Replace(System.Environment.NewLine, "<br>"); 407 string eyebrowHeadingLevel = Model.Item.GetString("EyebrowHeadingLevel", "h3"); 408 string eyebrowFontSize = Model.Item.GetRawValueString("EyebrowFontSize", "h5"); 409 string eyebrowColor = Model.Item.GetString("EyebrowColor", "text-inherit"); 410 string eyebrowTextOpacity = Model.Item.GetString("EyebrowTextOpacity", "opacity-100"); 411 string eyebrowCssClass = Model.Item.GetString("EyebrowCssClass", string.Empty); 412 string eyebrowSpacingBottomDesktop = Model.Item.GetRawValueString("EyebrowSpacingBottomDesktop", "default"); 413 eyebrowSpacingBottomDesktop = eyebrowSpacingBottomDesktop != "default" ? eyebrowSpacingBottomDesktop : string.Empty; 414 string eyebrowSpacingBottomMobile = Model.Item.GetRawValueString("EyebrowSpacingBottomMobile", "default"); 415 eyebrowSpacingBottomMobile = eyebrowSpacingBottomMobile != "default" ? eyebrowSpacingBottomMobile : string.Empty; 416 417 string title = Model.Item.GetString("Title", string.Empty).Replace(System.Environment.NewLine, "<br>"); 418 string titleHeadingLevel = Model.Item.GetString("TitleHeadingLevel", "h2"); 419 string titleFontSize = Model.Item.GetRawValueString("TitleFontSize", "h2"); 420 string titleColor = Model.Item.GetString("TitleColor", "text-inherit"); 421 string titleTextOpacity = Model.Item.GetString("TitleTextOpacity", "opacity-100"); 422 string titleCssClass = Model.Item.GetString("TitleCssClass", string.Empty); 423 string titleSpacingBottomDesktop = Model.Item.GetRawValueString("TitleSpacingBottomDesktop", "default"); 424 titleSpacingBottomDesktop = titleSpacingBottomDesktop != "default" ? titleSpacingBottomDesktop : string.Empty; 425 string titleSpacingBottomMobile = Model.Item.GetRawValueString("TitleSpacingBottomMobile", "default"); 426 titleSpacingBottomMobile = titleSpacingBottomMobile != "default" ? titleSpacingBottomMobile : string.Empty; 427 428 string subtitle = Model.Item.GetString("Subtitle", string.Empty).Replace(System.Environment.NewLine, "<br>"); 429 string subtitleHeadingLevel = Model.Item.GetString("SubtitleHeadingLevel", "p"); 430 string subtitleFontSize = Model.Item.GetRawValueString("SubtitleFontSize", "fs-5"); 431 string subtitleColor = Model.Item.GetString("SubtitleColor", "text-inherit"); 432 string subtitleTextOpacity = Model.Item.GetString("SubtitleTextOpacity", "opacity-100"); 433 string subtitleCssClass = Model.Item.GetString("SubtitleCssClass", string.Empty); 434 string subtitleSpacingBottomDesktop = Model.Item.GetRawValueString("SubtitleSpacingBottomDesktop", "default"); 435 subtitleSpacingBottomDesktop = subtitleSpacingBottomDesktop != "default" ? subtitleSpacingBottomDesktop : string.Empty; 436 string subtitleSpacingBottomMobile = Model.Item.GetRawValueString("SubtitleSpacingBottomMobile", "default"); 437 subtitleSpacingBottomMobile = subtitleSpacingBottomMobile != "default" ? subtitleSpacingBottomMobile : string.Empty; 438 439 440 //Button 1 441 var button1Link = Model.Item.GetLink("Button1Link"); 442 var button1Label = Model.Item.GetString("Button1Label", string.Empty); 443 var button1Icon = Model.Item.GetRawValueString("Button1Icon"); 444 var button1IconPosition = Model.Item.GetRawValueString("Button1IconPosition", "right"); 445 var button1Style = Model.Item.GetRawValueString("Button1Style", "btn-primary"); 446 447 //Button 2 448 var button2Link = Model.Item.GetLink("Button2Link"); 449 var button2Label = Model.Item.GetString("Button2Label", string.Empty); 450 var button2Icon = Model.Item.GetRawValueString("Button2Icon"); 451 var button2IconPosition = Model.Item.GetRawValueString("Button2IconPosition", "right"); 452 var button2Style = Model.Item.GetRawValueString("Button2Style", "btn-primary"); 453 454 string contentAlignment = "align-items-center justify-content-center"; 455 string contentTextAlignment = "text-start"; 456 457 458 var count = 0; 459 speakers = speakers.Where((speaker, index) => index < displayCount).ToList(); 460 461 var summarySpeakers = speakers.Select((speaker, index) => new {speaker, index}) 462 .GroupBy(g => g.index <= 5, 463 (key, g) => new { Title = key, Items = g.ToList() }); 464 string sliderCss = isSlider ? "swiffy-slider slider-nav-visible slider-nav-round" : ""; 465 string sliderListCss = isSlider ? "slider-container" : "container"; 466 467 <div class="@gridCss"> 468 <div id="Slider_@Model.ID" class="@sliderCss speaker-wall-preview"> 469 <div class="g-col-12 w-100 d-flex align-items-end justify-content-between gap-3 flex-wrap mb-4"> 470 <div> 471 @if (!string.IsNullOrEmpty(eyebrow)) 472 { 473 @RenderContent(eyebrow, eyebrowHeadingLevel, eyebrowFontSize, eyebrowColor, eyebrowTextOpacity, eyebrowSpacingBottomDesktop, eyebrowSpacingBottomMobile, eyebrowCssClass) 474 } 475 476 @if (!string.IsNullOrEmpty(title)) 477 { 478 @RenderContent(title, titleHeadingLevel, titleFontSize, titleColor, titleTextOpacity, titleSpacingBottomDesktop, titleSpacingBottomMobile, titleCssClass) 479 } 480 481 @if (!string.IsNullOrEmpty(subtitle)) 482 { 483 @RenderContent(subtitle, subtitleHeadingLevel, subtitleFontSize, subtitleColor, subtitleTextOpacity, subtitleSpacingBottomDesktop, subtitleSpacingBottomMobile, subtitleCssClass) 484 } 485 </div> 486 <div class="d-flex gap-3 align-items-stretch"> 487 <div> 488 @if (button1Link is object || button2Link is object) 489 { 490 if (contentTextAlignment == "text-start") 491 { 492 contentAlignment = "justify-content-start"; 493 } 494 if (contentTextAlignment == "text-center") 495 { 496 contentAlignment = "justify-content-center"; 497 } 498 if (contentTextAlignment == "text-end") 499 { 500 contentAlignment = "justify-content-end"; 501 } 502 503 <div class="d-flex flex-wrap @(contentAlignment) gap-3"> 504 @if (button1Link is object && !string.IsNullOrEmpty(button1Label)) 505 { 506 button1Style = button1Style + " rounded-7 btn-sm"; 507 @RenderButton(button1Link, button1Label, button1Style, button1Icon, button1IconPosition) 508 } 509 510 @if (button2Link is object && !string.IsNullOrEmpty(button1Label)) 511 { 512 @RenderButton(button2Link, button2Label, button2Style, button2Icon, button2IconPosition) 513 } 514 </div> 515 } 516 </div> 517 <div class="d-flex"> 518 <button type="button" title="@Translate("Previous slide")" class="btn btn-primary slider-nav position-relative p-lg-3 rounded-7-start bg-black text-white" style="z-index:1;max-height: 2.75em;min-height: 2.75em"> 519 <span class="icon-auto"> 520 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="feather feather-arrow-left"><line x1="19" y1="12" x2="5" y2="12"></line><polyline points="12 19 5 12 12 5"></polyline></svg> 521 </span> 522 <span class="visually-hidden">@Translate("Previous slide")</span> 523 </button> 524 <button type="button" title="@Translate("Next slide")" class="btn btn-primary slider-nav slider-nav-next position-relative p-lg-3 rounded-7-end bg-black text-white" style="z-index:1;max-height: 2.75em;min-height: 2.75em"> 525 <span class="icon-auto"> 526 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="feather feather-arrow-right"><line x1="5" y1="12" x2="19" y2="12"></line><polyline points="12 5 19 12 12 19"></polyline></svg> 527 </span> 528 <span class="visually-hidden">@Translate("Next slide")</span> 529 </button> 530 </div> 531 </div> 532 </div> 533 534 535 <ul class="@sliderListCss"> 536 @foreach (var _i in summarySpeakers) 537 { 538 <li class="grid speaker-slider"> 539 @foreach (var _item in _i.Items.Take(6)) 540 { 541 count++; 542 string viewSpeakerInfoTranslate = Translate("View") + " " + _item.speaker.fullName + " " + Translate("info"); 543 string speakerName = _item.speaker.fullName != null ? _item.speaker.fullName.ToString() : ""; 544 string speakerBio = _item.speaker.bio != null ? _item.speaker.bio.ToString() : ""; 545 string speakerTagLine = _item.speaker.tagLine != null ? _item.speaker.tagLine.ToString() : ""; 546 string speakerProfilePicture = _item.speaker.profilePicture != null ? _item.speaker.profilePicture.ToString() : ""; 547 var sessionsTranslate = _item.speaker.sessions.Count() > 1 ? Translate("Sessions") : Translate("Session"); 548 var speakerTypeList = _item.speaker.categories.Where(cat => cat.name == "SpeakerType") ?? null; 549 550 <div class="speaker h-100 grid grid-12 gap-lg-4 @theme gap-2 position-relative rounded-7"> 551 <div class="h-100 p-4 g-col-md-6 g-col-12 order-last order-md-first d-flex flex-column gap-1 max-h-15-em"> 552 <a href="#" class="btn btn-link p-0 text-decoration-none" title="@viewSpeakerInfoTranslate" onclick="event.preventDefault(); new bootstrap.Modal(document.getElementById('SpeakerModal_@(count - 1)')).show()"> 553 <h5 class="text-start">@makeStringReadable(speakerName)</h5> 554 </a> 555 <p class="fs-7 m-0">@speakerTagLine</p> 556 @if (speakerTypeList != null) 557 { 558 <div class="d-flex gap-2 mt-2"> 559 @foreach (var cat in speakerTypeList) 560 { 561 foreach (var c in cat.categoryItems) 562 { 563 string badgePath = "/Files/Images/"; 564 565 if (c.name.Equals("Microsoft")) 566 { 567 badgePath += "microsoftIconBadge.png"; 568 } 569 else if (c.name.Equals("Sponsor")) 570 { 571 badgePath += "sponsorIconBadge.png"; 572 } 573 else if (c.name.Equals("MVP")) 574 { 575 badgePath += "mvpIconBadge.png"; 576 } 577 else if (c.name.Equals("Directions")) 578 { 579 badgePath += "directionsIconBadge.png"; 580 } 581 else 582 { 583 badgePath = badgePath; 584 } 585 586 <img height="@iconBadgeHeight" width="@iconBadgeWidth" src="@badgePath" class="rounded-0"></img> 587 } 588 } 589 </div> 590 } 591 </div> 592 <div class="h-100 g-col-md-6 g-col-12 overflow-hidden rounded-7"> 593 <a class="btn btn-link p-0" title="@viewSpeakerInfoTranslate" onclick="new bootstrap.Modal(document.getElementById('SpeakerModal_@(count - 1)')).show()"> 594 <img src="@speakerProfilePicture" class="w-100 img-fluid rounded-7"></img> 595 </a> 596 </div> 597 </div> 598 } 599 </li> 600 } 601 </ul> 602 603 @for (int x = 0; x < displayCount; x++) 604 { 605 string viewSpeakerInfoTranslate = Translate("View") + " " + speakers[x].fullName + " " + Translate("info"); 606 string speakerName = speakers[x].fullName != null ? speakers[x].fullName.ToString() : ""; 607 string speakerBio = speakers[x].bio != null ? speakers[x].bio.ToString() : ""; 608 string speakerTagLine = speakers[x].tagLine != null ? speakers[x].tagLine.ToString() : ""; 609 string speakerProfilePicture = speakers[x].profilePicture != null ? speakers[x].profilePicture.ToString() : ""; 610 string speakerCategories = speakers[x].categoryItems != null ? String.Join(",", speakers[x].categoryItems) : ""; 611 var sessionsTranslate = speakers[x].sessions.Count() > 1 ? Translate("Sessions") : Translate("Session"); 612 var speakerTypeList = speakers[x].categories.Where(cat => cat.name == "SpeakerType") ?? null; 613 614 <div class="modal fade modal-xl" id="SpeakerModal_@x"> 615 <div class="modal-dialog"> 616 <div class="modal-content @theme rounded-7"> 617 <div class="modal-body p-0" id="SpeakerModalBodyContainer_@x"> 618 <div class="close-container position-absolute p-3 end-0 m-3 bg-white rounded-7 z-index-9"> 619 <button type="button" class="btn-close bg-dark z-index-9" data-bs-dismiss="modal" aria-label="Close"></button> 620 </div> 621 <div class="grid @theme gap-0 rounded-7"> 622 <div class="h-100 g-col-lg-7 g-col-12 order-last order-md-first"> 623 <div class="h-100 p-4 overflow-auto max-h-30-em"> 624 <div> 625 <h5>@makeStringReadable(speakerName)</h5> 626 <p>@speakerTagLine</p> 627 </div> 628 <div class="d-flex flex-column gap-3 justify-content-between overflow-auto max-h-15-em"> 629 <p class="m-0">@makeStringReadable(speakerBio)</p> 630 </div> 631 <div class="mt-4 d-grid"> 632 <p class="m-0 fw-bold">@sessionsTranslate</p> 633 @foreach (var session in speakers[x].sessions) 634 { 635 if (!string.IsNullOrEmpty(sessionDetailsPage)) 636 { 637 var sessionLink = sessionDetailsPage.IndexOf("?") > 0 ? sessionDetailsPage + "&session=" + session.id : sessionDetailsPage + "?session=" + session.id; 638 <a class="btn btn-link text-start p-0 mb-2" title="@session.name" href="@sessionLink"> 639 @session.name 640 </a> 641 } 642 else 643 { 644 <p class="mb-2">@session.name</p> 645 } 646 } 647 </div> 648 @if (speakerTypeList != null) 649 { 650 <div class="d-flex gap-2"> 651 @foreach (var cat in speakerTypeList) 652 { 653 foreach (var c in cat.categoryItems) 654 { 655 string badgePath = "/Files/Images/"; 656 657 if (c.name.Equals("Microsoft")) 658 { 659 badgePath += "microsoftIconBadge.png"; 660 } 661 else if (c.name.Equals("Sponsor")) 662 { 663 badgePath += "sponsorIconBadge.png"; 664 } 665 else if (c.name.Equals("MVP")) 666 { 667 badgePath += "mvpIconBadge.png"; 668 } 669 else if (c.name.Equals("Directions")) 670 { 671 badgePath += "directionsIconBadge.png"; 672 } 673 else 674 { 675 badgePath = badgePath; 676 } 677 678 <img height="@iconBadgeHeight" width="@iconBadgeWidth" src="@badgePath" class="rounded-0"></img> 679 } 680 } 681 </div> 682 } 683 </div> 684 </div> 685 <div class="h-100 g-col-lg-5 g-col-12"> 686 <img src="@speakerProfilePicture" class="h-100 w-100 img-fluid rounded-7"></img> 687 </div> 688 </div> 689 </div> 690 </div> 691 </div> 692 </div> 693 } 694 </div> 695 </div> 696 } 697 else 698 { 699 var level1Speakers = speakers.Where(s => s.displayPriority == 1).ToList(); 700 var level2Speakers = speakers.Where(s => s.displayPriority == 2); 701 var level3Speakers = speakers.Where(s => s.displayPriority > 2); 702 703 if (categoryParameter != 0) 704 { 705 level1Speakers = level1Speakers.Where(speaker => speaker.categories.Any(i => i.categoryItems.Any(cat => cat.id.Equals(categoryParameter)))).ToList(); 706 level2Speakers = level2Speakers.Where(speaker => speaker.categories.Any(i => i.categoryItems.Any(cat => cat.id.Equals(categoryParameter)))).ToList(); 707 level3Speakers = level3Speakers.Where(speaker => speaker.categories.Any(i => i.categoryItems.Any(cat => cat.id.Equals(categoryParameter)))).ToList(); 708 } 709 710 string topSpeakersCarouselWidth = Model.Item.GetRawValueString("TopSpeakersCarouselWidth", "w-100"); 711 712 <div class="d-grid mb-3"> 713 @if (level1Speakers.Any() && !hideSpeakerCategory) 714 { 715 <h4 class="mb-4">@Translate("SpeakerWall_DisplayOrder_1")</h4> 716 } 717 718 <div id="Slider_@Model.ID" class="@(topSpeakersCarouselWidth) m-auto d-grid swiffy-slider slider-nav-visible slider-nav-round slider-nav-autoplay slider-nav-autopause speaker-wall-preview"> 719 @RenderSpeakerSlider(level1Speakers, 6) 720 </div> 721 @*foreach(var speaker in level1Speakers) 722 { 723 @RenderSpeaker(speaker) 724 725 } *@ 726 </div> 727 728 if (level1Speakers.Any() && !hideSpeakerCategory) 729 { 730 <hr class="my-5"> 731 } 732 733 <div class="@gridCss mb-3"> 734 @if (level2Speakers.Any() && !hideSpeakerCategory) 735 { 736 <h4 class="mb-4 g-col-12">@Translate("SpeakerWall_DisplayOrder_2")</h4> 737 } 738 739 @foreach (var speaker in level2Speakers) 740 { 741 @RenderSpeaker(speaker) 742 } 743 </div> 744 745 if (level2Speakers.Any() && !hideSpeakerCategory) 746 { 747 <hr class="my-5"> 748 } 749 750 <div class="@gridCss mb-3"> 751 @if (level3Speakers.Any() && !hideSpeakerCategory) 752 { 753 <h4 class="mb-4 g-col-12">@Translate("SpeakerWall_DisplayOrder_3")</h4> 754 } 755 756 @foreach(var speaker in level3Speakers) 757 { 758 @RenderSpeaker(speaker) 759 } 760 </div> 761 } 762 } 763 764 } 765 766 @helper RenderContent(string content, string heading, string fontSize, string color, string opacity, string margin, string marginMobile, string cssClass) 767 { 768 var classes = new List<string> { }; 769 if (!string.IsNullOrEmpty(fontSize)) { classes.Add(fontSize); } 770 if (!string.IsNullOrEmpty(color)) { classes.Add(color); } 771 if (!string.IsNullOrEmpty(opacity)) { classes.Add(opacity); } 772 if (!string.IsNullOrEmpty(margin)) { classes.Add(margin); } 773 if (!string.IsNullOrEmpty(marginMobile)) { classes.Add(marginMobile); } 774 if (!string.IsNullOrEmpty(cssClass)) { classes.Add(cssClass); } 775 776 var tagStart = $"<{heading} class=\"{string.Join(" ", classes)}\">"; 777 var tagEnd = $"</{heading}>"; 778 779 @tagStart 780 @content 781 @tagEnd 782 } 783 784 @helper RenderButton(Dynamicweb.Frontend.LinkViewModel link, string label, string style, string icon, string iconPosition) 785 { 786 string target = Pageview.AreaSettings.GetBoolean("OpenLinksInNewTab") && link.IsExternal ? "target=\"_blank\"" : string.Empty; 787 string rel = Pageview.AreaSettings.GetBoolean("OpenLinksInNewTab") && link.IsExternal ? "rel=\"noopener\"" : string.Empty; 788 789 <a href="@link.Url" @target @rel class="btn @(style)"> 790 @if (icon is object) 791 { 792 <span class="d-flex align-items-center gap-1 @(iconPosition)"> 793 @label 794 @RenderIcon(icon) 795 </span> 796 } 797 else 798 { 799 @label 800 } 801 </a> 802 } 803 804 @helper RenderIcon(string icon) 805 { 806 if (System.IO.Path.GetExtension(icon).ToLower() == ".svg") 807 { 808 if (!icon.ToLower().Contains("none") && icon != string.Empty) 809 { 810 <span class="icon-auto"> 811 @ReadFile(icon) 812 </span> 813 } 814 } 815 } 816 @helper RenderSpeaker (Speaker speaker) 817 { 818 string iconBadgeWidth = Model.Item.GetString("IconBadgeWidth"); 819 string iconBadgeHeight = Model.Item.GetString("IconBadgeHeight"); 820 821 var columnSize = "grid g-col-xl-4 g-col-lg-6 g-col-md-6 g-col-12"; 822 columnSize = speaker.displayPriority == 1 ? "grid g-col-lg-12 g-col-12" : columnSize; 823 columnSize = speaker.displayPriority == 2 ? "grid g-col-lg-6 g-col-12" : columnSize; 824 825 string viewSpeakerInfoTranslate = Translate("View") + " " + speaker.fullName + " " + Translate("info"); 826 string speakerId = speaker.id; 827 string speakerName = speaker.fullName != null ? speaker.fullName.ToString() : ""; 828 string speakerBio = speaker.bio != null ? speaker.bio.ToString() : ""; 829 string speakerTagLine = speaker.tagLine != null ? speaker.tagLine.ToString() : ""; 830 string speakerProfilePicture = speaker.profilePicture != null ? speaker.profilePicture.ToString() : ""; 831 string speakerCategories = speaker.categoryItems != null ? String.Join(",", speaker.categoryItems) : ""; 832 string tagLineCssClass = "fs-7 m-0";//i == 0 ? string.Empty : "fs-7 m-0"; 833 var sessionsTranslate = speaker.sessions.Count() > 1 ? Translate("Sessions") : Translate("Session"); 834 var speakerTypeList = speaker.categories.Where(cat => cat.name == "SpeakerType") ?? null; 835 var speakerDisplayPriority = speaker.displayPriority.ToString(); 836 837 <div class="speaker @columnSize @theme gap-0 position-relative rounded-7 toggle-speaker" data-name="@makeStringReadable(speakerName)"> 838 <div class="h-100 g-col-lg-7 g-col-12 order-last order-lg-first"> 839 <div class="h-100 p-4 d-flex flex-column justify-content-between"> 840 <div class="d-flex flex-column"> 841 <a href="#" class="btn btn-link p-0 text-decoration-none" title="@viewSpeakerInfoTranslate" onclick="event.preventDefault(); new bootstrap.Modal(document.getElementById('SpeakerModal_@speakerId')).show()"> 842 <h5 class="text-start m-0">@makeStringReadable(speakerName)</h5> 843 </a> 844 <p class="@tagLineCssClass">@speakerTagLine</p> 845 </div> 846 <div class="d-flex flex-column gap-3 justify-content-between max-height-inherit overflow-auto"> 847 @*if (i == 0 && !showSummary) 848 { 849 <p class="m-0">@makeStringReadable(speakerBio)</p> 850 }*@ 851 </div> 852 @if (speakerTypeList != null) 853 { 854 <div class="d-flex gap-2"> 855 @foreach (var cat in speakerTypeList) 856 { 857 foreach (var c in cat.categoryItems) 858 { 859 string badgePath = "/Files/Images/"; 860 861 if (c.name.Equals("Microsoft")) 862 { 863 badgePath += "microsoftIconBadge.png"; 864 } 865 else if (c.name.Equals("Sponsor")) 866 { 867 badgePath += "sponsorIconBadge.png"; 868 } 869 else if (c.name.Equals("MVP")) 870 { 871 badgePath += "mvpIconBadge.png"; 872 } 873 else if (c.name.Equals("Directions")) 874 { 875 badgePath += "directionsIconBadge.png"; 876 } 877 else 878 { 879 badgePath = badgePath; 880 } 881 882 <img height="@iconBadgeHeight" width="@iconBadgeWidth" src="@badgePath" class="rounded-0"></img> 883 } 884 } 885 </div> 886 } 887 </div> 888 </div> 889 <div class="h-100 g-col-lg-5 g-col-12 rounded-7"> 890 <a class="btn btn-link p-0 d-flex" title="@viewSpeakerInfoTranslate" onclick="new bootstrap.Modal(document.getElementById('SpeakerModal_@speakerId')).show()"> 891 <img src="@speakerProfilePicture" class="w-100 img-fluid rounded-7"></img> 892 </a> 893 </div> 894 <div class="h-100 w-100 position-absolute cursor-pointer d-none"> 895 <a class="btn btn-link stretched-link" title="@viewSpeakerInfoTranslate" onclick="new bootstrap.Modal(document.getElementById('SpeakerModal_@speakerId')).show()"></a> 896 </div> 897 </div> 898 899 900 <div class="modal fade modal-xl" id="SpeakerModal_@speakerId"> 901 <div class="modal-dialog"> 902 <div class="modal-content @theme rounded-7"> 903 <div class="modal-body p-0" id="SpeakerModalBodyContainer_@speakerId"> 904 <div class="close-container position-absolute p-3 end-0 m-3 bg-white rounded-7 z-index-9"> 905 <button type="button" class="btn-close bg-dark z-index-9" data-bs-dismiss="modal" aria-label="Close"></button> 906 </div> 907 <div class="grid @theme gap-0 rounded-7"> 908 <div class="h-100 g-col-lg-7 g-col-12 order-last order-md-first"> 909 <div class="h-100 p-4 overflow-auto max-h-30-em"> 910 <div> 911 <h5>@makeStringReadable(speakerName)</h5> 912 <p>@speakerTagLine</p> 913 </div> 914 <div class="d-flex flex-column gap-3 justify-content-between overflow-auto max-h-15-em"> 915 <p class="m-0">@makeStringReadable(speakerBio)</p> 916 </div> 917 @if (speakerTypeList != null) 918 { 919 <div class="d-flex gap-2 mt-4"> 920 @foreach (var cat in speakerTypeList) 921 { 922 foreach (var c in cat.categoryItems) 923 { 924 string badgePath = "/Files/Images/"; 925 926 if (c.name.Equals("Microsoft")) 927 { 928 badgePath += "microsoftIconBadge.png"; 929 } 930 else if (c.name.Equals("Sponsor")) 931 { 932 badgePath += "sponsorIconBadge.png"; 933 } 934 else if (c.name.Equals("MVP")) 935 { 936 badgePath += "mvpIconBadge.png"; 937 } 938 else if (c.name.Equals("Directions")) 939 { 940 badgePath += "directionsIconBadge.png"; 941 } 942 else 943 { 944 badgePath = badgePath; 945 } 946 947 <img height="@iconBadgeHeight" width="@iconBadgeWidth" src="@badgePath" class="rounded-0"></img> 948 } 949 } 950 </div> 951 } 952 <div class="mt-4 d-grid"> 953 <p class="m-0 fw-bold">@sessionsTranslate</p> 954 @foreach (var session in speaker.sessions) 955 { 956 if (!string.IsNullOrEmpty(sessionDetailsPage)) 957 { 958 var sessionLink = sessionDetailsPage.IndexOf("?") > 0 ? sessionDetailsPage + "&session=" + session.id : sessionDetailsPage + "?session=" + session.id; 959 <a class="btn btn-link text-start p-0 mb-2" title="@session.name" href="@sessionLink"> 960 @session.name 961 </a> 962 } 963 else 964 { 965 <p class="mb-2">@session.name</p> 966 } 967 } 968 </div> 969 @if (speaker.links.Any()) 970 { 971 <div class="d-flex gap-3 align-items-end"> 972 @foreach (var link in speaker.links) 973 { 974 string icon = "/Files/Templates/Designs/Swift/Assets/icons/"; 975 976 if (link.url.Contains("twitter")) 977 { 978 icon += "twitter.svg"; 979 } 980 else if (link.url.Contains("linkedin")) 981 { 982 icon += "linkedin.svg"; 983 } 984 else 985 { 986 icon += "link.svg"; 987 } 988 989 <a href="@link.url" title="@link.title" target="_blank"> 990 @RenderIcon(icon) 991 </a> 992 } 993 </div> 994 } 995 </div> 996 </div> 997 <div class="h-100 g-col-lg-5 g-col-12"> 998 <img src="@speakerProfilePicture" class="h-100 w-100 img-fluid rounded-7"></img> 999 </div> 1000 </div> 1001 </div> 1002 </div> 1003 </div> 1004 </div> 1005 } 1006 1007 @helper RenderSpeakerSlider(List<Speaker> speakers, int pageSize) 1008 { 1009 string iconBadgeWidth = Model.Item.GetString("IconBadgeWidth"); 1010 string iconBadgeHeight = Model.Item.GetString("IconBadgeHeight"); 1011 var summarySpeakers = speakers.Select((speaker, index) => new {speaker, index}) 1012 .GroupBy(g => g.index < 3, 1013 (key, g) => new { Title = key, Items = g.ToList() }); 1014 if(speakers.Any()) 1015 { 1016 <div class="d-flex"> 1017 <button type="button" title="@Translate("Previous slide")" class="btn btn-primary slider-nav position-relative p-lg-3 rounded-7-start bg-black text-white" style="z-index:1;max-height: 2.75em;min-height: 2.75em"> 1018 <span class="icon-auto"> 1019 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="feather feather-arrow-left"><line x1="19" y1="12" x2="5" y2="12"></line><polyline points="12 19 5 12 12 5"></polyline></svg> 1020 </span> 1021 <span class="visually-hidden">@Translate("Previous slide")</span> 1022 </button> 1023 <button type="button" title="@Translate("Next slide")" class="btn btn-primary slider-nav slider-nav-next position-relative p-lg-3 rounded-7-end bg-black text-white" style="z-index:1;max-height: 2.75em;min-height: 2.75em"> 1024 <span class="icon-auto"> 1025 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="feather feather-arrow-right"><line x1="5" y1="12" x2="19" y2="12"></line><polyline points="12 5 19 12 12 19"></polyline></svg> 1026 </span> 1027 <span class="visually-hidden">@Translate("Next slide")</span> 1028 </button> 1029 </div> 1030 1031 <ul class="slider-container"> 1032 @foreach (var _speaker in speakers.Take(pageSize)) 1033 { 1034 string viewSpeakerInfoTranslate = Translate("View") + " " + _speaker.fullName + " " + Translate("info"); 1035 string speakerId = _speaker.id; 1036 string speakerName = _speaker.fullName != null ? _speaker.fullName.ToString() : ""; 1037 string speakerBio = _speaker.bio != null ? _speaker.bio.ToString() : ""; 1038 string speakerTagLine = _speaker.tagLine != null ? _speaker.tagLine.ToString() : ""; 1039 string speakerProfilePicture = _speaker.profilePicture != null ? _speaker.profilePicture.ToString() : ""; 1040 var sessionsTranslate = _speaker.sessions.Count() > 1 ? Translate("Sessions") : Translate("Session"); 1041 var speakerTypeList = _speaker.categories.Where(cat => cat.name == "SpeakerType") ?? null; 1042 string bioText = speakerBio.Count() > 700 ? speakerBio.Substring(0, 700) + "..." : speakerBio; 1043 1044 <li class="toggle-speaker" data-name="@makeStringReadable(speakerName)"> 1045 <div class="speaker grid @theme position-relative rounded-7"> 1046 <div class="h-100 p-4 g-col-lg-7 g-col-12 order-last order-lg-first d-flex flex-column gap-1"> 1047 <a href="#" class="btn btn-link p-0 text-decoration-none" title="@viewSpeakerInfoTranslate" onclick="event.preventDefault(); new bootstrap.Modal(document.getElementById('SpeakerModal_@speakerId')).show()"> 1048 <h5 class="text-start">@makeStringReadable(speakerName)</h5> 1049 </a> 1050 <h5>@speakerTagLine</h5> 1051 <div class="h-100 d-flex flex-column justify-content-between"> 1052 <div class="d-flex flex-column gap-3 justify-content-between overflow-hidden speaker-bio-container"> 1053 <p class="m-0 bio-text fs-lg-7">@makeStringReadable(bioText)</p> 1054 </div> 1055 <div class="d-flex justify-content-between align-items-center"> 1056 @if (speakerTypeList != null) 1057 { 1058 <div class="d-flex gap-2 mt-2"> 1059 @foreach (var cat in speakerTypeList) 1060 { 1061 foreach (var c in cat.categoryItems) 1062 { 1063 string badgePath = "/Files/Images/"; 1064 1065 if (c.name.Equals("Microsoft")) 1066 { 1067 badgePath += "microsoftIconBadge.png"; 1068 } 1069 else if (c.name.Equals("Sponsor")) 1070 { 1071 badgePath += "sponsorIconBadge.png"; 1072 } 1073 else if (c.name.Equals("MVP")) 1074 { 1075 badgePath += "mvpIconBadge.png"; 1076 } 1077 else if (c.name.Equals("Directions")) 1078 { 1079 badgePath += "directionsIconBadge.png"; 1080 } 1081 else 1082 { 1083 badgePath = badgePath; 1084 } 1085 1086 <img height="@iconBadgeHeight" width="@iconBadgeWidth" src="@badgePath" class="rounded-0"></img> 1087 } 1088 } 1089 </div> 1090 } 1091 <div class="mt-2"> 1092 <button class="btn btn-primary btn-sm" onclick="event.preventDefault(); new bootstrap.Modal(document.getElementById('SpeakerModal_@speakerId')).show()">@Translate("Read more")</button> 1093 </div> 1094 </div> 1095 </div> 1096 </div> 1097 <div class="h-100 g-col-lg-5 g-col-12 overflow-hidden rounded-7"> 1098 <a class="btn btn-link p-0 w-100" title="@viewSpeakerInfoTranslate" onclick="new bootstrap.Modal(document.getElementById('SpeakerModal_@speakerId')).show()"> 1099 <img src="@speakerProfilePicture" class="w-100 img-fluid rounded-7"></img> 1100 </a> 1101 </div> 1102 </div> 1103 </li> 1104 } 1105 </ul> 1106 1107 foreach (var speaker in speakers) 1108 { 1109 string speakerId = speaker.id; 1110 string viewSpeakerInfoTranslate = Translate("View") + " " + speaker.fullName + " " + Translate("info"); 1111 string speakerName = speaker.fullName != null ? speaker.fullName.ToString() : ""; 1112 string speakerBio = speaker.bio != null ? speaker.bio.ToString() : ""; 1113 string speakerTagLine = speaker.tagLine != null ? speaker.tagLine.ToString() : ""; 1114 string speakerProfilePicture = speaker.profilePicture != null ? speaker.profilePicture.ToString() : ""; 1115 string speakerCategories = speaker.categoryItems != null ? String.Join(",", speaker.categoryItems) : ""; 1116 var sessionsTranslate = speaker.sessions.Count() > 1 ? Translate("Sessions") : Translate("Session"); 1117 var speakerTypeList = speaker.categories.Where(cat => cat.name == "SpeakerType") ?? null; 1118 1119 <div class="modal fade modal-xl" id="SpeakerModal_@speakerId"> 1120 <div class="modal-dialog"> 1121 <div class="modal-content @theme rounded-7"> 1122 <div class="modal-body p-0" id="SpeakerModalBodyContainer_@speakerId"> 1123 <div class="close-container position-absolute p-3 end-0 m-3 bg-white rounded-7 z-index-9"> 1124 <button type="button" class="btn-close bg-dark z-index-9" data-bs-dismiss="modal" aria-label="Close"></button> 1125 </div> 1126 <div class="grid @theme gap-0 rounded-7"> 1127 <div class="h-100 g-col-lg-7 g-col-12 order-last order-md-first"> 1128 <div class="h-100 p-4 overflow-auto max-h-30-em"> 1129 <div> 1130 <h5>@makeStringReadable(speakerName)</h5> 1131 <p>@speakerTagLine</p> 1132 </div> 1133 <div class="d-flex flex-column gap-3 justify-content-between overflow-auto max-h-15-em"> 1134 <p class="m-0">@makeStringReadable(speakerBio)</p> 1135 </div> 1136 <div class="mt-4 d-grid"> 1137 <p class="m-0 fw-bold">@sessionsTranslate</p> 1138 @foreach (var session in speaker.sessions) 1139 { 1140 if (!string.IsNullOrEmpty(sessionDetailsPage)) 1141 { 1142 var sessionLink = sessionDetailsPage.IndexOf("?") > 0 ? sessionDetailsPage + "&session=" + session.id : sessionDetailsPage + "?session=" + session.id; 1143 <a class="btn btn-link text-start p-0 mb-2" title="@session.name" href="@sessionLink"> 1144 @session.name 1145 </a> 1146 } 1147 else 1148 { 1149 <p class="mb-2">@session.name</p> 1150 } 1151 } 1152 </div> 1153 @if (speakerTypeList != null) 1154 { 1155 <div class="d-flex gap-2"> 1156 @foreach (var cat in speakerTypeList) 1157 { 1158 foreach (var c in cat.categoryItems) 1159 { 1160 string badgePath = "/Files/Images/"; 1161 1162 if (c.name.Equals("Microsoft")) 1163 { 1164 badgePath += "microsoftIconBadge.png"; 1165 } 1166 else if (c.name.Equals("Sponsor")) 1167 { 1168 badgePath += "sponsorIconBadge.png"; 1169 } 1170 else if (c.name.Equals("MVP")) 1171 { 1172 badgePath += "mvpIconBadge.png"; 1173 } 1174 else if (c.name.Equals("Directions")) 1175 { 1176 badgePath += "directionsIconBadge.png"; 1177 } 1178 else 1179 { 1180 badgePath = badgePath; 1181 } 1182 1183 <img height="@iconBadgeHeight" width="@iconBadgeWidth" src="@badgePath" class="rounded-0"></img> 1184 } 1185 } 1186 </div> 1187 } 1188 </div> 1189 </div> 1190 <div class="h-100 g-col-lg-5 g-col-12"> 1191 <img src="@speakerProfilePicture" class="h-100 w-100 img-fluid rounded-7"></img> 1192 </div> 1193 </div> 1194 </div> 1195 </div> 1196 </div> 1197 </div> 1198 } 1199 } 1200 } 1201 <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" /> 1202 <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> 1203 <script type="module" src="/Files/Templates/Designs/Swift/Assets/js/swiffy-slider.js"></script> 1204 <link rel="stylesheet" type="text/css" href="/Files/Templates/Designs/Swift/Assets/css/swiffy-slider.min.css"></link>