nordic 2026
2-3 May, 2025

Days of Knowledge Nordic 2025

Join us in Odense, in the core of Denmark, for Days of Knowledge Nordic 2025! This local training event offers a unique opportunity for continuous learning in Business Central and related products, mastering cloud and AI technologies and accelerating technology adoption. Stay ahead by gaining the skills to implement modern customer solutions efficiently and connect with the Dynamics community to deliver more value to your clients.

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>