Fra kaos til klarhed: hvordan struktureret produktdata skaber værdi for produktionsvirksomheder
Vi gør dig klogere på, hvordan du kan håndtere de stigende informationsstrømme på en intelligent og strategisk måde.
Mængden af produktdata i produktionsvirksomheder vokser støt. Fra specifikationer og styklister (BOM'er), til kvalitetscertifikater og vedligeholdelsesdokumenter genererer hver procestrin ny information. Selvom disse data er essentielle, kan mangel på organisering føre til ineffektivitet, fejl og tabte muligheder. Håndtering af denne informationsstrøm kræver en intelligent og strategisk tilgang.
Risici ved ustrukturerede produktdata
Ustrukturerede data skaber ofte kaos. Det gør det svært for teams hurtigt at finde de rette oplysninger, hvilket drastisk reducerer effektiviteten. Forestil dig en medarbejder i forsyningskæden, der kæmper med at finde kritisk leverandørinformation, eller en ingeniør, der uforvarende arbejder med forældede tekniske specifikationer. Disse situationer forsinker ikke blot processerne, men kan også føre til dyre fejl.
En anden udfordring er, at ineffektiv datastyring ofte resulterer i tabte oplysninger eller dobbelt dataregistrering. Når data er spredt på tværs af forskellige systemer eller eksisterer i siloer, hindrer det optimalt samarbejde. Denne mangel på tværfaglig kommunikation påvirker både produktkvalitet og projektbudgetter negativt.
Produktinformation og designoplysninger opbevares ofte i formater som PDF'er, hvilket skaber det, der kaldes "døde data." Disse statiske dokumenter er svære at opdatere eller integrere i moderne arbejdsgange.
En anden væsentlig risiko er tabet af kritisk viden. Mange virksomheder er stadig afhængige af medarbejderes ekspertise uden at dokumentere deres processer eller indsigter ordentligt. Når en medarbejder forlader virksomheden, forsvinder deres værdifulde viden ofte med dem, hvilket medfører forsinkelser og øgede omkostninger i fremtidige projekter.
En vej ud af kaos
For at imødekomme disse udfordringer, skal virksomheder prioritere at strukturere og centralisere deres data. Det kræver investering i processer, metoder og teknologier, der gør datastyring enklere. Fokus på klar kommunikation, effektiv versionskontrol og central adgang til data kan gøre en betydelig forskel.
Forestil dig for eksempel at implementere et system, der organiserer al produktinformation på en klar og tilgængelig måde. Ved at kategorisere nøgledata og gøre dem let tilgængelige, kan virksomheder spare tid og undgå dyre fejl. Men hvordan sikrer man, at denne tilgang forbliver effektiv på lang sigt? Her kommer en holistisk løsning i spil.
PLM som svar på data-overload
Når man ser på det store potentiale i centraliseret datahåndtering, tilbyder PLM mere end bare klarhed - det giver et fundament for strategisk vækst. PLM-systemer erstatter fragmenteret datalagring og dobbelte processer med en sammenhængende platform, hvor alt samles. Med PLM kan virksomheder:
- Undgå dataduplikering ved at sikre, at design, dokumenter og specifikationer kun gemmes og bruges én gang.
- Forbedre versionsstyringen og sikre, at teams altid arbejder med de senest opdaterede oplysninger.
- Bevare viden ved at digitalisere beregninger, designretningslinjer og dokumentation for at sikre, at det forbliver tilgængeligt, selv hvis kritiske medarbejdere forlader virksomheden.
Kvalitets- og certificeringsdata kan f.eks. nemt gemmes og spores i et PLM-system. Det sikrer, at disse oplysninger er let tilgængelige ved revisioner, eller når nye lovkrav skal opfyldes.
Risikostyring og bæredygtighed med PLM
Et PLM-system giver også stærke værktøjer til risikostyring. Ved at tilbyde dataindsigt i realtid hjælper PLM med hurtigt at identificere problemer - uanset om det er defekte komponenter, compliance-risici eller pludselige ændringer i materialeomkostninger. Virksomheder kan f.eks. simulere scenarier, hvor miljøreglerne ændres. Hvad sker der med omkostninger og produktionsplanlægning, hvis det viser sig, at et kritisk råmateriale har et højere CO2-aftryk? Med PLM kan disse usikkerheder bedre imødegås, så virksomhederne kan forberede sig på fremtidige udfordringer.
En anden vigtig fordel er dens understøttelse af bæredygtighedsindsatsen. PLM-systemer giver indsigt, der hjælper med at gøre produkter mere miljøvenlige, f.eks. gennem brug af genanvendelige materialer eller energieffektive produktionsmetoder. De giver virksomhederne mulighed for at overvåge og rapportere om disse parametre via værktøjer som Digital Product Passports, hvilket fremmer gennemsigtighed og sporbarhed. Dette er endnu en grund til, at klare og strukturerede data er nødvendige.
Data som drivkraft for beslutningstagning
Centraliserede, velorganiserede data giver mulighed for stærkere og mere præcis beslutningstagning. Forestil dig ledere, der stiller spørgsmål til deres produktdatabase, understøttet af AI-systemer som Copilot. Spørgsmål som »Hvilke komponenter i vores produkter understøttes ikke længere?« eller »Hvad er leveringstiden for designændringer?« kan besvares med det samme. Dette niveau af indsigt er kun muligt med et velforbundet PLM-system, der integreres problemfrit med ERP og anden organisations-software.
Gør data-kaos til en strategisk fordel
Håndtering af produktdata i produktionsvirksomheder handler om mere end blot at reducere kompleksiteten - det handler om at udnytte data som et strategisk aktiv. Ved at implementere en PLM-løsning som PTC Windchill kan virksomheder strukturere deres information, minimere risici og drive innovation. Uanset om det er gennem bedre versionskontrol, fastholdelse af viden, risikostyring eller bæredygtighed, er fordelene ved PLM ubestridelige.
Overvej, hvordan din virksomhed i øjeblikket håndterer produktdata. Er der behov for større klarhed og struktur? Kontakt os for at få skræddersyet rådgivning om, hvordan PLM kan optimere dine processer. Sammen forvandler vi data-kaos til en strategisk kraft, der løfter din virksomhed til næste niveau.
Error compiling template "Designs/Swift/Paragraph/9a_Content_RelatedContentBanner.cshtml" Line 9: The type or namespace name 'NineAltitudes' could not be found (are you missing a using directive or an assembly reference?) Line 16: The type or namespace name 'NineAltitudes' could not be found (are you missing a using directive or an assembly reference?) Line 35: The name 'NineAStaticContent' does not exist in the current context Line 206: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. Auto-generated code requires an explicit '#nullable' directive in source. Line 207: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. Auto-generated code requires an explicit '#nullable' directive in source. Line 210: 'FileViewModel.FocalX' is obsolete: 'Use Dynamicweb.Frontend.ImageViewModel.FocalX' Line 211: 'FileViewModel.FocalY' is obsolete: 'Use Dynamicweb.Frontend.ImageViewModel.FocalY' Line 219: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. Auto-generated code requires an explicit '#nullable' directive in source. Line 266: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. Auto-generated code requires an explicit '#nullable' directive in source. Line 479: 'User.GetUserByID(int)' is obsolete: 'Use UserManagementServices.Users.GetUserById instead.' Line 618: The type or namespace name 'INineAContentQueryService' could not be found (are you missing a using directive or an assembly reference?)
1 // <auto-generated/> 2 #pragma warning disable 1591 3 namespace CompiledRazorTemplates.Dynamic 4 { 5 #line hidden 6 using System.Threading.Tasks; 7 using System; 8 using System.Collections.Generic; 9 using NineAltitudes.CustomCode.NineAContent; 10 using Dynamicweb.Rendering; 11 using Dynamicweb.Core; 12 using Dynamicweb.Extensibility; 13 using Dynamicweb.Frontend; 14 using System.Linq; 15 using System.IO; 16 using NineAltitudes.CustomCode.NineAContent.ContentClient; 17 internal class RazorEngine_42b8d3d3be9d4bcda0b78b5cfbc2e94b : Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.ParagraphViewModel> 18 { 19 #pragma warning disable 1998 20 public async override global::System.Threading.Tasks.Task ExecuteAsync() 21 { 22 WriteLiteral("\r\n"); 23 24 int maxItemsInList = Model.Item.GetInt32("MaxItemsInList"); 25 if (maxItemsInList == 0) 26 { 27 maxItemsInList = 10; 28 } 29 30 var pageView = Dynamicweb.Frontend.PageView.Current(); 31 int currentPageId = pageView.ID; 32 int currentPageAreaId = pageView.AreaID; 33 34 string filteringType = Model.Item.GetString("FilteringType") ?? "tags"; 35 var content = filteringType == "static" ? NineAStaticContent.GetStaticContent(Model, currentPageAreaId) : GetFacetedContent(Model, maxItemsInList, currentPageAreaId, currentPageId); 36 WriteLiteral("\r\n"); 37 WriteLiteral("\r\n\r\n"); 38 39 //Not a parameter anymore 40 string listBehaviour = Model.Item.GetRawValueString("ListBehaviour", "articles"); 41 42 //Not a parameter anymore 43 string articleListLayout = Model.Item.GetRawValueString("ArticleListLayout", "carousel"); 44 string articleItemLayout = Model.Item.GetRawValueString("ArticleItemLayout", string.Empty); 45 46 string columnTheme = Model.Item.GetRawValueString("ColumnTheme", string.Empty).ToString().Replace(" ", "").Trim().ToLower(); 47 48 string columnThemeClass = columnTheme != string.Empty ? " theme " + columnTheme + " p-3" + (articleListLayout == "carousel" ? " px-lg-4" : string.Empty) : string.Empty; 49 50 var carouselSettings = Model.Item.GetRawValueString("CarouselSettings", "4"); 51 52 string slidesPerPage = $"slider-item-show{carouselSettings}"; 53 string navigationStyle = $"{Model.Item.GetRawValueString("NavigationStyle", "slider-nav-round")}"; 54 string navigationPlacement = $"{Model.Item.GetRawValueString("NavigationPlacement", "slider-nav-on-slides")}"; 55 string indicatorStyle = $"{Model.Item.GetRawValueString("IndicatorStyle", string.Empty)}"; 56 string revealSlides = Model.Item.GetRawValueString("RevealSlides", "reveal") == "reveal" ? "slider-item-reveal" : string.Empty; 57 string sliderItemsGap = Model.Item.GetRawValueString("SliderItemsGap", "slider-item-gap") == "slider-item-nogap" ? "slider-item-nogap" : string.Empty; 58 string navigationAlwaysVisible = (Model.Item.GetBoolean("NavigationAlwaysVisible")) ? "slider-nav-visible" : string.Empty; 59 string navigationVisibleOnTouch = (Model.Item.GetBoolean("NavigationVisibleOnTouch")) ? "slider-nav-touch" : string.Empty; 60 string navigationShowScrollbar = (Model.Item.GetBoolean("NavigationShowScrollbar")) ? "slider-nav-scrollbar" : string.Empty; 61 string scrollBarForceMobile = (Model.Item.GetBoolean("NavigationShowScrollbar")) ? "--swiffy-slider-track-height:0.5rem !important;" : string.Empty; 62 string navigationSmall = (Model.Item.GetBoolean("NavigationSmall")) ? "slider-nav-sm" : string.Empty; 63 string navigationInvertColors = (Model.Item.GetBoolean("NavigationInvertColors")) ? "slider-nav-dark" : string.Empty; 64 string navigationSlideEntirePage = (Model.Item.GetBoolean("NavigationSlideEntirePage")) ? "slider-nav-page" : string.Empty; 65 string navigationNoLoop = (Model.Item.GetBoolean("NavigationNoLoop")) ? "slider-nav-noloop" : string.Empty; 66 string indicatorsOutsideSlider = (Model.Item.GetBoolean("IndicatorsOutsideSlider") && indicatorStyle != string.Empty) ? "slider-indicators-outside" : string.Empty; 67 string indicatorsHighlightActive = (Model.Item.GetBoolean("IndicatorsHighlightActive")) ? "slider-indicators-highlight" : string.Empty; 68 string indicatorsInvertColors = (Model.Item.GetBoolean("IndicatorsInvertedColors")) ? "slider-indicators-dark" : string.Empty; 69 string indicatorsVisibleOnSmallDevices = (Model.Item.GetBoolean("IndicatorsVisibleOnSmallDevices")) ? "slider-indicators-sm" : string.Empty; 70 string animation = Model.Item.GetRawValueString("Animation", string.Empty) != string.Empty ? $"slider-nav-animation {Model.Item.GetRawValueString("Animation")}" : string.Empty; 71 string autoplay = (Model.Item.GetBoolean("Autoplay")) ? "slider-nav-autoplay" : string.Empty; 72 string autoplayInterval = Model.Item.GetRawValueString("AutoplayInterval", string.Empty); 73 bool hideSliderNavigation = false; 74 75 var totalItems = content.Count(); 76 var count = content.Count(); 77 var hasItems = content.Any(); 78 79 var percent = count > 0 ? Convert.ToInt32(Math.Round(((double)count / totalItems) * 100, 0)) : 0; 80 var disableLoadMoreButton = count == totalItems ? true : false; 81 82 var loadMore = !disableLoadMoreButton ? $"onclick=\"document.querySelector('#PageSize_{Pageview.CurrentParagraph.ID}').value='{count + maxItemsInList}'; this.dispatchEvent(new window.Event('change', {{ bubbles: true }}))\"" : null; 83 var disabled = disableLoadMoreButton ? "disabled" : null; 84 85 bool showLoadMore = Model.Item.GetBoolean("ShowLoadMore"); 86 87 string titleFontSize = Model.Item.GetString("TitleFontSize", string.Empty); 88 string gridSettings = Model.Item.GetString("GridSettings", "4"); 89 90 bool showButton = Model.Item.GetBoolean("ShowButton"); 91 bool showDates = Model.Item.GetBoolean("ShowDates"); 92 string ratio = Model.Item.GetString("ImageAspectRatio", string.Empty); 93 ratio = ratio != "0" ? ratio : string.Empty; 94 95 string articleItemTheme = Model.Item.GetString("ArticleItemTheme", string.Empty).Replace(" ", "").Trim().ToLower(); 96 string articleItemShape = Model.Item.GetString("ArticleItemShape", "boxed"); 97 98 99 if (navigationStyle == "slider-nav-none") 100 { 101 hideSliderNavigation = true; 102 } 103 104 WriteLiteral(" <div"); 105 BeginWriteAttribute("class", " class=\"", 9664, "\"", 9734, 4); 106 WriteAttributeValue("", 9672, "h-100", 9672, 5, true); 107 WriteAttributeValue("", 9677, columnThemeClass, 9677, 19, false); 108 WriteAttributeValue(" ", 9696, "item_", 9697, 6, true); 109 WriteAttributeValue("", 9702, Model.Item.SystemName.ToLower(), 9702, 32, false); 110 EndWriteAttribute(); 111 WriteLiteral(">\r\n <div"); 112 BeginWriteAttribute("id", " id=\"", 9750, "\"", 9764, 1); 113 WriteAttributeValue("", 9755, Model.ID, 9755, 9, false); 114 EndWriteAttribute(); 115 WriteLiteral(" class=\"user-select-none\" style=\"scroll-margin-top:var(--header-height,150px)\"></div>\r\n"); 116 117 if (!Model.Item.GetBoolean("HideTitle")) 118 { 119 120 string headingLevel = "h2"; 121 string headingLevelStart = $"<{headingLevel} class=\" mb-4\">"; 122 string headingLevelStop = $"</{headingLevel}>"; 123 Write(headingLevelStart); 124 Write(Model.Item.GetString("Title")); 125 Write(headingLevelStop); 126 127 } 128 WriteLiteral(" <div"); 129 BeginWriteAttribute("id", " id=\"", 10283, "\"", 10304, 2); 130 WriteAttributeValue("", 10288, "Slider_", 10288, 7, true); 131 WriteAttributeValue("", 10295, Model.ID, 10295, 9, false); 132 EndWriteAttribute(); 133 BeginWriteAttribute("class", " class=\"", 10305, "\"", 10793, 22); 134 WriteAttributeValue("", 10313, "swiffy-slider", 10313, 13, true); 135 WriteAttributeValue(" ", 10326, slidesPerPage, 10327, 16, false); 136 WriteAttributeValue(" ", 10343, navigationStyle, 10344, 18, false); 137 WriteAttributeValue(" ", 10362, revealSlides, 10363, 15, false); 138 WriteAttributeValue(" ", 10378, navigationPlacement, 10379, 22, false); 139 WriteAttributeValue(" ", 10401, navigationAlwaysVisible, 10402, 26, false); 140 WriteAttributeValue(" ", 10428, navigationVisibleOnTouch, 10429, 27, false); 141 WriteAttributeValue(" ", 10456, sliderItemsGap, 10457, 17, false); 142 WriteAttributeValue(" ", 10474, indicatorStyle, 10475, 17, false); 143 WriteAttributeValue(" ", 10492, navigationShowScrollbar, 10493, 26, false); 144 WriteAttributeValue(" ", 10519, navigationSmall, 10520, 18, false); 145 WriteAttributeValue(" ", 10538, navigationInvertColors, 10539, 25, false); 146 WriteAttributeValue(" ", 10564, indicatorsOutsideSlider, 10565, 26, false); 147 WriteAttributeValue(" ", 10591, navigationNoLoop, 10592, 19, false); 148 WriteAttributeValue(" ", 10611, indicatorsHighlightActive, 10612, 28, false); 149 WriteAttributeValue(" ", 10640, indicatorsInvertColors, 10641, 25, false); 150 WriteAttributeValue(" ", 10666, indicatorsVisibleOnSmallDevices, 10667, 34, false); 151 WriteAttributeValue(" ", 10701, navigationSlideEntirePage, 10702, 28, false); 152 WriteAttributeValue(" ", 10730, animation, 10731, 12, false); 153 WriteAttributeValue(" ", 10743, autoplay, 10744, 11, false); 154 WriteAttributeValue(" ", 10755, "item_", 10756, 6, true); 155 WriteAttributeValue("", 10761, Model.Item.SystemName.ToLower(), 10761, 32, false); 156 EndWriteAttribute(); 157 BeginWriteAttribute("style", " style=\"", 10794, "\"", 10964, 2); 158 WriteAttributeValue("", 10802, "--swiffy-slider-nav-light:var(--swift-foreground-color);--swiffy-slider-nav-dark:var(--swift-background-color);visibility:hidden;opacity:0;", 10802, 139, true); 159 WriteAttributeValue("", 10941, scrollBarForceMobile, 10941, 23, false); 160 EndWriteAttribute(); 161 WriteLiteral(" data-slider-nav-autoplay-interval=\""); 162 Write(autoplayInterval); 163 WriteLiteral("\">\r\n <div class=\"slider-container pb-3 py-lg-3 px-lg-3 mt-lg-n3 mx-lg-n3\">\r\n\r\n"); 164 165 166 // CARD SPECIFIC SETTINGS 167 168 string orderReverseClass = articleItemLayout == "image-right" ? " order-first order-lg-last" : string.Empty; 169 string articleItemLayoutClass = string.Empty; 170 171 string ratioCssClass = ratio != string.Empty ? " ratio" : string.Empty; 172 string ratioVariable = ratio != string.Empty ? "style=\"--bs-aspect-ratio: " + ratio + "\"" : string.Empty; 173 174 string shapeClass = " rounded-0"; 175 if (articleItemShape == "rounded") 176 { 177 shapeClass = " rounded-4"; 178 } 179 180 string settingsClassGrid = string.Empty; 181 switch (gridSettings) 182 { 183 case "2": 184 settingsClassGrid = " grid-md-2"; 185 break; 186 case "3": 187 settingsClassGrid = " grid-md-3"; 188 break; 189 case "4": 190 settingsClassGrid = " grid-md-2 grid-lg-3 grid-xl-4"; 191 break; 192 case "5": 193 settingsClassGrid = " grid-md-2 grid-lg-3 grid-xl-5"; 194 break; 195 } 196 string gridWrapperStart = articleListLayout == "grid" ? $"<div class=\"article-list grid gap-4 grid-1{settingsClassGrid}\">" : null; 197 string gridWrapperEnd = articleListLayout == "grid" ? "</div>" : null; 198 199 bool hasListContext = Pageview.CurrentParagraph.Item["ListContext"] is object; 200 WriteLiteral("\r\n <!--CARDS BEGIN HERE -->\r\n"); 201 foreach (var item in content) 202 { 203 string title = !string.IsNullOrEmpty(item.GetString("Title")) && !item.GetBoolean("HideTitle") ? item.GetString("Title") : string.Empty; 204 string coverTitle = title; 205 206 List<FileViewModel> imageList = (List<FileViewModel>?)item.Fields?.FirstOrDefault(o => o.SystemName == "Image")?.Value ?? new List<FileViewModel>(); 207 FileViewModel? imageObject = imageList.FirstOrDefault(); 208 string coverImagePath = imageObject?.Path ?? ""; 209 210 int focalX = (int?)imageObject?.FocalX ?? 0; 211 int focalY = (int?)imageObject?.FocalY ?? 0; 212 213 int xPos = 100 - ((100 - focalX) / 2); 214 int yPos = ((100 - focalY) / 2); 215 string cssPosition = $"{xPos}% {yPos}%"; 216 217 string summary = !string.IsNullOrEmpty(item.GetString("Summary")) ? item.GetString("Summary") : string.Empty; 218 219 string? publishedDate = item.GetString("PublishedDate"); 220 bool hidePublishedDate = item.GetBoolean("HidePublishedDate"); 221 222 if (hidePublishedDate) 223 { 224 publishedDate = null; 225 } 226 else 227 { 228 publishedDate = ToDateTime(publishedDate)?.ToShortDateString(); 229 if (publishedDate == "01/01/1900" || (publishedDate is not null && (publishedDate.Contains("1900") || publishedDate.Contains("0001")))) 230 { 231 publishedDate = null; 232 } 233 } 234 235 string link = item.Link; 236 string buttonLabel = item.GetString("ButtonLabel", string.Empty); 237 238 239 string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/"; 240 241 int? author = ToInt(item.GetString("Author")); 242 243 bool renderContentWrapper = true; 244 bool renderArticleInfoWrapper = true; 245 246 if (string.IsNullOrEmpty(title) && string.IsNullOrEmpty(summary) && string.IsNullOrEmpty(publishedDate) && !showButton) 247 { 248 renderContentWrapper = false; 249 } 250 251 if (string.IsNullOrEmpty(publishedDate) || !showDates) 252 { 253 renderArticleInfoWrapper = false; 254 } 255 256 switch (articleItemLayout) 257 { 258 case "image-left": 259 case "image-right": 260 articleItemLayoutClass = !string.IsNullOrEmpty(coverImagePath) && renderContentWrapper ? "flex-lg-row" : articleItemLayoutClass; 261 break; 262 } 263 264 string imageObjectFit = ratio != string.Empty ? "object-fit: cover;" : "object-fit: contain;"; 265 266 string? coverTheme = item.GetString("CoverTheme")?.Replace(" ", "").Trim().ToLower() ?? string.Empty; 267 268 string themeClass = string.Empty; 269 string coverImageWrapperClass = string.Empty; 270 271 if (!string.IsNullOrEmpty(coverTheme)) 272 { 273 articleItemTheme = coverTheme; 274 } 275 276 if (articleItemTheme != string.Empty) 277 { 278 themeClass = " theme " + articleItemTheme; 279 } 280 281 // Exclude self from list - if list has context (Tags) and if is on same page 282 bool excludeSelf = false; 283 bool renderItem = true; 284 285 renderItem = hasListContext && excludeSelf ? renderItem = false : !hasListContext && !excludeSelf ? renderItem : renderItem; 286 287 if (renderItem) 288 { 289 WriteLiteral(" <article"); 290 BeginWriteAttribute("class", " class=\"", 17079, "\"", 17251, 9); 291 WriteAttributeValue("", 17087, "card", 17087, 4, true); 292 WriteAttributeValue(" ", 17091, "border-0", 17092, 9, true); 293 WriteAttributeValue(" ", 17100, string.IsNullOrEmpty(themeClass) ? "gap-3" : null, 17101, 52, false); 294 WriteAttributeValue(" ", 17153, articleItemLayoutClass, 17154, 23, false); 295 WriteAttributeValue("", 17177, themeClass, 17177, 13, false); 296 WriteAttributeValue("", 17190, shapeClass, 17190, 13, false); 297 WriteAttributeValue(" ", 17203, "overflow-hidden", 17204, 16, true); 298 WriteAttributeValue(" ", 17219, LiftOnHover(), 17220, 14, false); 299 WriteAttributeValue(" ", 17234, ShadowOnHover(), 17235, 16, false); 300 EndWriteAttribute(); 301 WriteLiteral(" itemscope itemtype=\"https://schema.org/CreativeWork\" style=\"background-color: var(--swift-background-color)\">\r\n\r\n"); 302 if (!string.IsNullOrEmpty(coverImagePath)) 303 { 304 if (Path.GetExtension(coverImagePath).ToLower() == ".svg") 305 { 306 coverImageWrapperClass = !renderContentWrapper ? "d-flex justify-content-center align-items-center h-100 w-100 " : "w-100 "; 307 308 WriteLiteral(" <a"); 309 BeginWriteAttribute("class", " class=\"", 17799, "\"", 17852, 2); 310 WriteAttributeValue("", 17807, coverImageWrapperClass, 17807, 25, false); 311 WriteAttributeValue("", 17832, orderReverseClass, 17832, 20, false); 312 EndWriteAttribute(); 313 BeginWriteAttribute("title", " title=\"", 17853, "\"", 17867, 1); 314 WriteAttributeValue("", 17861, title, 17861, 6, false); 315 EndWriteAttribute(); 316 BeginWriteAttribute("href", " href=\"", 17868, "\"", 17880, 1); 317 WriteAttributeValue("", 17875, link, 17875, 5, false); 318 EndWriteAttribute(); 319 WriteLiteral(" tabindex=\"-1\">\r\n <div"); 320 BeginWriteAttribute("class", " class=\"", 17942, "\"", 18030, 5); 321 WriteAttributeValue("", 17950, "d-flex", 17950, 6, true); 322 WriteAttributeValue(" ", 17956, "justify-content-center", 17957, 23, true); 323 WriteAttributeValue(" ", 17979, "align-items-center", 17980, 19, true); 324 WriteAttributeValue(" ", 17998, "overflow-hidden", 17999, 16, true); 325 WriteAttributeValue("", 18014, ratioCssClass, 18014, 16, false); 326 EndWriteAttribute(); 327 WriteLiteral(" "); 328 Write(ratioVariable); 329 WriteLiteral(">\r\n "); 330 Write(ReadFile(coverImagePath)); 331 WriteLiteral("\r\n </div>\r\n </a>\r\n"); 332 } 333 else 334 { 335 coverImageWrapperClass = articleItemLayout == "image-top" ? "position-relative" : $"col {orderReverseClass}"; 336 coverImageWrapperClass += renderContentWrapper && articleItemLayout != "image-top" ? " col-lg-5" : string.Empty; 337 338 string figureClass = articleItemLayout == "image-top" ? ratioCssClass : "h-lg-100 ratio ratio-16x9"; 339 ratioVariable = articleItemLayout == "image-top" ? ratioVariable : string.Empty; 340 341 WriteLiteral(" <a"); 342 BeginWriteAttribute("class", " class=\"", 18913, "\"", 18944, 1); 343 WriteAttributeValue("", 18921, coverImageWrapperClass, 18921, 23, false); 344 EndWriteAttribute(); 345 BeginWriteAttribute("title", " title=\"", 18945, "\"", 18959, 1); 346 WriteAttributeValue("", 18953, title, 18953, 6, false); 347 EndWriteAttribute(); 348 BeginWriteAttribute("href", " href=\"", 18960, "\"", 18972, 1); 349 WriteAttributeValue("", 18967, link, 18967, 5, false); 350 EndWriteAttribute(); 351 WriteLiteral(" tabindex=\"-1\">\r\n <figure"); 352 BeginWriteAttribute("class", " class=\"", 19037, "\"", 19087, 4); 353 WriteAttributeValue("", 19045, "overflow-hidden", 19045, 15, true); 354 WriteAttributeValue(" ", 19060, "m-0", 19061, 4, true); 355 WriteAttributeValue(" ", 19064, "mx-auto", 19065, 8, true); 356 WriteAttributeValue(" ", 19072, figureClass, 19073, 14, false); 357 EndWriteAttribute(); 358 WriteLiteral(" "); 359 Write(ratioVariable); 360 WriteLiteral(">\r\n"); 361 362 coverImagePath = Dynamicweb.Context.Current.Server.UrlEncode(coverImagePath); 363 imageObjectFit = articleItemLayout != "image-top" ? "object-fit: cover" : imageObjectFit; 364 365 string imgSizeSelector = "50vw"; 366 imgSizeSelector = gridSettings == "1" || carouselSettings == "1" ? "100vw" : imgSizeSelector; 367 imgSizeSelector = gridSettings == "2" || carouselSettings == "2" ? "50vw" : imgSizeSelector; 368 imgSizeSelector = gridSettings == "3" || carouselSettings == "3" ? "33vw" : imgSizeSelector; 369 imgSizeSelector = gridSettings == "4" || carouselSettings == "4" ? "25vw" : imgSizeSelector; 370 imgSizeSelector = gridSettings == "5" || carouselSettings == "5" ? "17vw" : imgSizeSelector; 371 372 string coverImagePathM = $"/Admin/Public/GetImage.ashx?image={coverImagePath}&width=640&format=webp"; 373 string coverImagePathL = $"/Admin/Public/GetImage.ashx?image={coverImagePath}&width=960&format=webp"; 374 string imagePathFallBack = coverImagePathM; 375 376 WriteLiteral(" <img"); 377 BeginWriteAttribute("srcset", " srcset=\"", 20666, "\"", 20862, 4); 378 WriteAttributeValue("\r\n ", 20675, coverImagePathM, 20745, 16, false); 379 WriteAttributeValue(" ", 20761, "640w,", 20764, 8, true); 380 WriteAttributeValue("\r\n ", 20769, coverImagePathL, 20839, 16, false); 381 WriteAttributeValue(" ", 20855, "960w", 20858, 7, true); 382 EndWriteAttribute(); 383 BeginWriteAttribute("src", "\r\n src=\"", 20863, "\"", 20941, 1); 384 WriteAttributeValue("", 20923, imagePathFallBack, 20923, 18, false); 385 EndWriteAttribute(); 386 BeginWriteAttribute("sizes", "\r\n sizes=\"", 20942, "\"", 21046, 5); 387 WriteAttributeValue("", 21004, "(min-width:", 21004, 11, true); 388 WriteAttributeValue(" ", 21015, "992px)", 21016, 7, true); 389 WriteAttributeValue(" ", 21022, imgSizeSelector, 21023, 16, false); 390 WriteAttributeValue("", 21039, ",", 21039, 1, true); 391 WriteAttributeValue(" ", 21040, "100vw", 21041, 6, true); 392 EndWriteAttribute(); 393 WriteLiteral("\r\n loading=\"lazy\"\r\n decoding=\"async\"\r\n class=\"img-fluid image-zoom-lg-1-hover\""); 394 BeginWriteAttribute("style", "\r\n style=\"", 21281, "\"", 21390, 5); 395 WriteAttributeValue("", 21343, imageObjectFit, 21343, 15, false); 396 WriteAttributeValue("", 21358, ";", 21358, 1, true); 397 WriteAttributeValue(" ", 21359, "object-position:", 21360, 17, true); 398 WriteAttributeValue(" ", 21376, cssPosition, 21377, 12, false); 399 WriteAttributeValue("", 21389, ";", 21389, 1, true); 400 EndWriteAttribute(); 401 BeginWriteAttribute("alt", "\r\n alt=\"", 21391, "\"", 21457, 1); 402 WriteAttributeValue("", 21451, title, 21451, 6, false); 403 EndWriteAttribute(); 404 WriteLiteral(">\r\n"); 405 WriteLiteral(" </figure>\r\n </a>\r\n"); 406 } 407 } 408 WriteLiteral("\r\n"); 409 if (renderContentWrapper) 410 { 411 WriteLiteral(" <div"); 412 BeginWriteAttribute("class", " class=\"", 21792, "\"", 21846, 4); 413 WriteAttributeValue("", 21800, "col", 21800, 3, true); 414 WriteAttributeValue(" ", 21803, "d-flex", 21804, 7, true); 415 WriteAttributeValue(" ", 21810, "flex-column", 21811, 12, true); 416 WriteAttributeValue(" ", 21822, GetPadding(themeClass), 21823, 23, false); 417 EndWriteAttribute(); 418 WriteLiteral(">\r\n <div class=\"card-body p-0 d-flex flex-column gap-2\">\r\n"); 419 WriteLiteral("\r\n"); 420 if (!string.IsNullOrEmpty(title)) 421 { 422 WriteLiteral(" <a class=\"text-decoration-none text-decoration-underline-hover\""); 423 BeginWriteAttribute("href", " href=\"", 22231, "\"", 22243, 1); 424 WriteAttributeValue("", 22238, link, 22238, 5, false); 425 EndWriteAttribute(); 426 WriteLiteral(">\r\n <h3"); 427 BeginWriteAttribute("class", " class=\"", 22298, "\"", 22325, 2); 428 WriteAttributeValue("", 22306, titleFontSize, 22306, 14, false); 429 WriteAttributeValue(" ", 22320, "mb-0", 22321, 5, true); 430 EndWriteAttribute(); 431 WriteLiteral(" itemprop=\"headline\">"); 432 Write(title); 433 WriteLiteral("</h3>\r\n </a>\r\n"); 434 } 435 if (!string.IsNullOrEmpty(summary)) 436 { 437 WriteLiteral(" <p class=\"m-0 opacity-75\">"); 438 Write(summary); 439 WriteLiteral("</p>\r\n"); 440 } 441 442 WriteLiteral(" "); 443 Write(GetTagStickers(item)); 444 WriteLiteral("\r\n\r\n"); 445 if (showButton) 446 { 447 WriteLiteral(" <div class=\"mt-auto\">\r\n\r\n"); 448 if (!string.IsNullOrEmpty(buttonLabel)) 449 { 450 WriteLiteral(" <a"); 451 BeginWriteAttribute("href", " href=\"", 23196, "\"", 23208, 1); 452 WriteAttributeValue("", 23203, link, 23203, 5, false); 453 EndWriteAttribute(); 454 WriteLiteral(" class=\"text-start btn btn-link p-0\">\r\n "); 455 Write(buttonLabel); 456 WriteLiteral("\r\n <span class=\"icon-auto\">\r\n "); 457 Write(ReadFile(iconPath + "arrow-right.svg")); 458 WriteLiteral("\r\n </span>\r\n </a>\r\n"); 459 } 460 else 461 { 462 WriteLiteral(" <a"); 463 BeginWriteAttribute("href", " href=\"", 23834, "\"", 23846, 1); 464 WriteAttributeValue("", 23841, link, 23841, 5, false); 465 EndWriteAttribute(); 466 WriteLiteral(" class=\"btn btn-link p-0 lh-1 text-start\">\r\n <span class=\"icon-auto\">\r\n "); 467 Write(ReadFile(iconPath + "arrow-right.svg")); 468 WriteLiteral("\r\n </span>\r\n </a>\r\n"); 469 } 470 WriteLiteral(" </div>\r\n"); 471 } 472 WriteLiteral("\r\n </div>\r\n\r\n"); 473 if (renderArticleInfoWrapper) 474 { 475 WriteLiteral(" <div class=\"card-footer p-0 pt-3 border-top-0\">\r\n <div class=\"d-flex align-items-center justify-content-between gap-3\">\r\n"); 476 if (author != null && author != 0) 477 { 478 int authorID = author.Value; 479 var authorUser = Dynamicweb.Security.UserManagement.User.GetUserByID(authorID); 480 string authorImage = !string.IsNullOrEmpty(authorUser?.Image) ? authorUser.Image : string.Empty; 481 string authorImagePath = !string.IsNullOrEmpty(authorUser?.Image) ? $"/Admin/Public/GetImage.ashx?image={authorUser.Image}&width=24&height=24&Crop=0&format=webp" : string.Empty; 482 string authorName = !string.IsNullOrEmpty(authorUser?.Name) ? authorName = authorUser.Name : string.Empty; 483 string authorJobTitle = !string.IsNullOrEmpty(authorUser?.JobTitle) ? authorJobTitle = authorUser.JobTitle : string.Empty; 484 485 WriteLiteral(" <div class=\"d-flex align-items-center gap-2 fs-8 opacity-75\">\r\n\r\n"); 486 if (!string.IsNullOrEmpty(authorImage)) 487 { 488 WriteLiteral(" <img class=\"img-fluid rounded-circle\""); 489 BeginWriteAttribute("src", " src=\"", 26143, "\"", 26165, 1); 490 WriteAttributeValue("", 26149, authorImagePath, 26149, 16, false); 491 EndWriteAttribute(); 492 WriteLiteral(" loading=\"lazy\""); 493 BeginWriteAttribute("alt", " alt=\"", 26181, "\"", 26198, 1); 494 WriteAttributeValue("", 26187, authorName, 26187, 11, false); 495 EndWriteAttribute(); 496 WriteLiteral(" width=\"24\" height=\"24\">\r\n"); 497 } 498 else 499 { 500 WriteLiteral(@" <div class=""d-flex align-items-center justify-content-center rounded-circle"" style=""background-color: rgba(var(--swift-foreground-color-rgb),.25)""> 501 <div class=""icon-2 p-1""> 502 "); 503 Write(ReadFile(iconPath + "user.svg")); 504 WriteLiteral("\r\n </div>\r\n </div>\r\n"); 505 } 506 WriteLiteral("\r\n <div class=\"d-flex flex-column lh-1\">\r\n"); 507 if (!string.IsNullOrEmpty(authorName)) 508 { 509 WriteLiteral(" <span itemprop=\"author\">"); 510 Write(authorName); 511 WriteLiteral("</span>\r\n"); 512 } 513 if (!string.IsNullOrEmpty(authorJobTitle)) 514 { 515 WriteLiteral(" <span class=\"opacity-75\">"); 516 Write(authorJobTitle); 517 WriteLiteral("</span>\r\n"); 518 } 519 WriteLiteral(" </div>\r\n </div>\r\n"); 520 } 521 WriteLiteral("\r\n"); 522 if (!string.IsNullOrEmpty(publishedDate)) 523 { 524 525 string articleDateTime = publishedDate; 526 527 WriteLiteral(" <div class=\"d-flex align-items-center gap-1 fs-8 opacity-75\">\r\n <div class=\"icon-1\">\r\n "); 528 Write(ReadFile(iconPath + "calendar.svg")); 529 WriteLiteral("\r\n </div>\r\n <time"); 530 BeginWriteAttribute("datetime", " datetime=\"", 28614, "\"", 28641, 1); 531 WriteAttributeValue("", 28625, articleDateTime, 28625, 16, false); 532 EndWriteAttribute(); 533 WriteLiteral(" itemprop=\"datePublished\">"); 534 Write(publishedDate); 535 WriteLiteral("</time>\r\n </div>\r\n"); 536 } 537 WriteLiteral(" </div>\r\n </div>\r\n"); 538 } 539 WriteLiteral(" </div>\r\n"); 540 } 541 WriteLiteral(" </article>\r\n"); 542 } 543 544 545 } 546 WriteLiteral("\r\n <!-- CARDS END HERE -->\r\n </div>\r\n\r\n"); 547 if (!hideSliderNavigation) 548 { 549 WriteLiteral(" <button type=\"button\""); 550 BeginWriteAttribute("title", " title=\"", 29252, "\"", 29288, 1); 551 WriteAttributeValue("", 29260, Translate("Previous slide"), 29260, 28, false); 552 EndWriteAttribute(); 553 WriteLiteral(" class=\"slider-nav\" style=\"z-index:1;\">\r\n <span class=\"visually-hidden\">"); 554 Write(Translate("Previous slide")); 555 WriteLiteral("</span>\r\n </button>\r\n <button type=\"button\""); 556 BeginWriteAttribute("title", " title=\"", 29481, "\"", 29513, 1); 557 WriteAttributeValue("", 29489, Translate("Next slide"), 29489, 24, false); 558 EndWriteAttribute(); 559 WriteLiteral(" class=\"slider-nav slider-nav-next\" style=\"z-index:1;\">\r\n <span class=\"visually-hidden\">"); 560 Write(Translate("Next slide")); 561 WriteLiteral("</span>\r\n </button>\r\n"); 562 } 563 if (indicatorStyle != "slider-indicators-hidden") 564 { 565 WriteLiteral(" <div class=\"slider-indicators\" style=\"z-index:1;\"></div>\r\n"); 566 } 567 WriteLiteral("\r\n <script type=\"module\" src=\"/Files/Templates/Designs/Swift/Assets/js/swiffy-slider.js\"></script>\r\n <script>\r\n window.addEventListener(\"load\", () => {\r\n initSlider_"); 568 Write(Model.ID); 569 WriteLiteral("();\r\n });\r\n\r\n document.addEventListener(\"updated.swift.pageupdater\", function (data) {\r\n initSlider_"); 570 Write(Model.ID); 571 WriteLiteral("();\r\n });\r\n\r\n function initSlider_"); 572 Write(Model.ID); 573 WriteLiteral("() {\r\n swift.AssetLoader.Load(\'/Files/Templates/Designs/Swift/Assets/css/swiffy-slider.min.css\', \'css\');\r\n window.swiffyslider.initSlider(document.querySelector(\'#Slider_"); 574 Write(Model.ID); 575 WriteLiteral("\'));\r\n document.querySelector(\'#Slider_"); 576 Write(Model.ID); 577 WriteLiteral("\').style.opacity = 1;\r\n document.querySelector(\'#Slider_"); 578 Write(Model.ID); 579 WriteLiteral("\').style.visibility = \"visible\";\r\n }\r\n </script>\r\n\r\n"); 580 if (indicatorStyle != "slider-indicators-hidden") 581 { 582 WriteLiteral(" <script type=\"module\">\r\n const slider = document.querySelector(\'#Slider_"); 583 Write(Model.ID); 584 WriteLiteral(@"'); 585 const sliderContainer = slider.querySelector('.slider-container'); 586 let slides = sliderContainer.querySelectorAll('article'); 587 const sliderIndicators = slider.querySelector('.slider-indicators'); 588 589 slides.forEach((slide, index) => { 590 const indicator = document.createElement('template'); 591 indicator.innerHTML = ` 592 <button type=""button"" class=""${index == 0 ? ""active"" : """"}"" title='"); 593 Write(Translate("Go to slide")); 594 WriteLiteral(" ${index + 1}\'>\r\n <span class=\"visually-hidden\">"); 595 Write(Translate("Go to slide")); 596 WriteLiteral(@" ${index + 1}</span> 597 </button> 598 `; 599 sliderIndicators.appendChild(indicator.content); 600 }); 601 </script> 602 "); 603 } 604 WriteLiteral(" </div>\r\n\r\n\r\n </div>\r\n"); 605 WriteLiteral("\r\n"); 606 } 607 #pragma warning restore 1998 608 609 610 private List<Dynamicweb.Frontend.ItemViewModel> GetFacetedContent(ParagraphViewModel model, int maxItems, int pageAreaId, int currentPageId) 611 { 612 var selectedTags = GetSelectedTags(model); 613 614 var contentTypes = model.Item?.GetList("ContentTypes")?.GetRawValue().OfType<string>() ?? Enumerable.Empty<string>(); 615 616 string ordering = model.Item?.GetString("Ordering") ?? "none"; 617 618 var service = ServiceLocator.Current.GetInstance<INineAContentQueryService>(); 619 620 var contentWithTags = service.GetContentByTagFilters(pageAreaId, currentPageId, contentTypes, selectedTags, maxItems, ordering); 621 622 var localizedTagPageIds = contentWithTags.Select(tag => tag.PageId).Take(maxItems); 623 var content = GetPagesByPageId(localizedTagPageIds); 624 625 return content; 626 } 627 628 private string[] GetSelectedTags(ParagraphViewModel model) 629 { 630 var industry_filters = model.Item?.GetList("Filters_Tags_Industries")?.GetRawValue().OfType<string>(); 631 var vendor_filters = model.Item?.GetList("Filters_Tags_Vendors")?.GetRawValue().OfType<string>(); 632 var domain_filters = model.Item?.GetList("Filters_Tags_Domains")?.GetRawValue().OfType<string>(); 633 var solution_filters = model.Item?.GetList("Filters_Tags_Solutions")?.GetRawValue().OfType<string>(); 634 var product_filters = model.Item?.GetList("Filters_Tags_Products")?.GetRawValue().OfType<string>(); 635 var country_filters = model.Item?.GetList("Filters_Tags_Countries")?.GetRawValue().OfType<string>(); 636 var service_filters = model.Item?.GetList("Filters_Tags_Services")?.GetRawValue().OfType<string>(); 637 var topic_filters = model.Item?.GetList("Filters_Tags_Topics")?.GetRawValue().OfType<string>(); 638 var hr_filters = model.Item?.GetList("Filters_Tags_HR")?.GetRawValue().OfType<string>(); 639 640 List<string> allTagsList = (industry_filters ?? []) 641 .Concat(vendor_filters ?? []) 642 .Concat(domain_filters ?? []) 643 .Concat(solution_filters ?? []) 644 .Concat(product_filters ?? []) 645 .Concat(country_filters ?? []) 646 .Concat(service_filters ?? []) 647 .Concat(topic_filters ?? []) 648 .Concat(hr_filters ?? []).ToList(); 649 650 //Possible DW10 bug that forces the default value of "Checkbox List" to be System.Collections.Generic.List\u00601[System.String]. 651 //Then if there is 0 options in "Checkbox List", it inserts this value in the database, and then the module shows no content, as there is no content 652 //with the tag "System.Collections.Generic.List\u00601[System.String]" 653 //so the following line is to remove that. If it is fixed in newer DW10, this can be removed. 654 allTagsList.RemoveAll(tag => tag == "System.Collections.Generic.List\u00601[System.String]"); 655 656 var allTags = allTagsList.ToArray(); 657 658 return allTags; 659 } 660 661 private List<Dynamicweb.Frontend.ItemViewModel> GetPagesByPageId(IEnumerable<int> pageIds) 662 { 663 var lists = new List<Dynamicweb.Frontend.ItemViewModel>(); 664 665 if (pageIds.Any()) 666 { 667 foreach (var tagPageID in pageIds) 668 { 669 var page = Dynamicweb.Content.Services.Pages?.GetPage(Dynamicweb.Core.Converter.ToInt32(tagPageID)) ?? null; 670 var viewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(page)?.Item ?? null; 671 672 if (viewModel != null) 673 { 674 lists.Add(viewModel); 675 } 676 } 677 } 678 return lists; 679 680 } 681 682 683 private int? ToInt(string value) 684 { 685 return Converter.ToInt32(value); 686 } 687 688 private DateTime? ToDateTime(string value) 689 { 690 return Converter.ToDateTime(value); 691 } 692 693 694 695 696 private string GetTagStickers(ItemViewModel item) 697 { 698 var stickers = string.Empty; 699 700 if (item.GetString("ItemPublisher:Item.SystemName") == "Swift_Article") 701 { 702 var showTags = Pageview.CurrentParagraph.Item["ShowTags"] != null ? (Boolean)Pageview.CurrentParagraph.Item["ShowTags"] : false; 703 704 if (showTags && GetTags(item).Count >= 1) 705 { 706 stickers += "<div class=\"d-inline-flex flex-wrap gap-1\">"; 707 foreach (var tag in GetTags(item)) 708 { 709 stickers += CreateSticker(tag); 710 } 711 stickers += "</div>"; 712 } 713 } 714 715 716 /* CUSTOM 9a Content type */ 717 if (item.GetString("ItemPublisher:Item.SystemName") == "9a_Content") 718 { 719 720 } 721 /* CUSTOM END */ 722 723 return stickers; 724 } 725 726 727 728 private List<string> GetTags(ItemViewModel item) 729 { 730 var tags = new List<string>(); 731 732 //foreach (var tag in item.GetLoop("ItemPublisher:Item.Tags.Options")) 733 //{ 734 // if (tag.GetBoolean("ItemPublisher:Item.Tags.Option.IsSelected")) 735 // { 736 // tags.Add(tag.GetString("ItemPublisher:Item.Tags.Option.Label")); 737 // } 738 //} 739 740 return tags; 741 } 742 743 744 private string CreateSticker(string label) 745 { 746 string shape = Pageview.CurrentParagraph.Item["ArticleItemShape"] != null ? Pageview.CurrentParagraph.Item["ArticleItemShape"].ToString() : "boxed"; 747 var sticker = $"<span class=\"badge fw-normal shadow-none\" style=\"border: 1px solid rgba(var(--swift-foreground-color-rgb), 0.2);\">{label}</span>"; 748 return sticker; 749 } 750 751 752 private string LiftOnHover() 753 { 754 bool liftOnHover = Pageview.CurrentParagraph.Item["LiftOnHover"] != null ? (Boolean)Pageview.CurrentParagraph.Item["LiftOnHover"] : false; 755 var lift = liftOnHover ? "lift" : null; 756 return lift; 757 } 758 759 private string ShadowOnHover() 760 { 761 bool shadowOnHover = Pageview.CurrentParagraph.Item["ShadowOnHover"] != null ? (Boolean)Pageview.CurrentParagraph.Item["ShadowOnHover"] : false; 762 var shadow = shadowOnHover ? "shadow-hover" : null; 763 return shadow; 764 } 765 766 private string GetPadding(string theme) 767 { 768 var padding = !string.IsNullOrEmpty(theme) ? "p-3" : null; 769 return padding; 770 } 771 772 private string GetGap(string theme) 773 { 774 var padding = string.IsNullOrEmpty(theme) ? "gap-3" : null; 775 return padding; 776 } 777 } 778 } 779 #pragma warning restore 1591 780
1 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.ParagraphViewModel> 2 @using NineAltitudes.CustomCode.NineAContent; 3 @using Dynamicweb.Rendering; 4 @using Dynamicweb.Core; 5 @using Dynamicweb.Extensibility; 6 @using Dynamicweb.Frontend; 7 @using System.Linq; 8 @using System.IO; 9 @using NineAltitudes.CustomCode.NineAContent.ContentClient; 10 11 @{ 12 int maxItemsInList = Model.Item.GetInt32("MaxItemsInList"); 13 if (maxItemsInList == 0) 14 { 15 maxItemsInList = 10; 16 } 17 18 var pageView = Dynamicweb.Frontend.PageView.Current(); 19 int currentPageId = pageView.ID; 20 int currentPageAreaId = pageView.AreaID; 21 22 string filteringType = Model.Item.GetString("FilteringType") ?? "tags"; 23 var content = filteringType == "static" ? NineAStaticContent.GetStaticContent(Model, currentPageAreaId) : GetFacetedContent(Model, maxItemsInList, currentPageAreaId, currentPageId); 24 } 25 26 @functions { 27 28 private List<Dynamicweb.Frontend.ItemViewModel> GetFacetedContent(ParagraphViewModel model, int maxItems, int pageAreaId, int currentPageId) 29 { 30 var selectedTags = GetSelectedTags(model); 31 32 var contentTypes = model.Item?.GetList("ContentTypes")?.GetRawValue().OfType<string>() ?? Enumerable.Empty<string>(); 33 34 string ordering = model.Item?.GetString("Ordering") ?? "none"; 35 36 var service = ServiceLocator.Current.GetInstance<INineAContentQueryService>(); 37 38 var contentWithTags = service.GetContentByTagFilters(pageAreaId, currentPageId, contentTypes, selectedTags, maxItems, ordering); 39 40 var localizedTagPageIds = contentWithTags.Select(tag => tag.PageId).Take(maxItems); 41 var content = GetPagesByPageId(localizedTagPageIds); 42 43 return content; 44 } 45 46 private string[] GetSelectedTags(ParagraphViewModel model) 47 { 48 var industry_filters = model.Item?.GetList("Filters_Tags_Industries")?.GetRawValue().OfType<string>(); 49 var vendor_filters = model.Item?.GetList("Filters_Tags_Vendors")?.GetRawValue().OfType<string>(); 50 var domain_filters = model.Item?.GetList("Filters_Tags_Domains")?.GetRawValue().OfType<string>(); 51 var solution_filters = model.Item?.GetList("Filters_Tags_Solutions")?.GetRawValue().OfType<string>(); 52 var product_filters = model.Item?.GetList("Filters_Tags_Products")?.GetRawValue().OfType<string>(); 53 var country_filters = model.Item?.GetList("Filters_Tags_Countries")?.GetRawValue().OfType<string>(); 54 var service_filters = model.Item?.GetList("Filters_Tags_Services")?.GetRawValue().OfType<string>(); 55 var topic_filters = model.Item?.GetList("Filters_Tags_Topics")?.GetRawValue().OfType<string>(); 56 var hr_filters = model.Item?.GetList("Filters_Tags_HR")?.GetRawValue().OfType<string>(); 57 58 List<string> allTagsList = (industry_filters ?? []) 59 .Concat(vendor_filters ?? []) 60 .Concat(domain_filters ?? []) 61 .Concat(solution_filters ?? []) 62 .Concat(product_filters ?? []) 63 .Concat(country_filters ?? []) 64 .Concat(service_filters ?? []) 65 .Concat(topic_filters ?? []) 66 .Concat(hr_filters ?? []).ToList(); 67 68 //Possible DW10 bug that forces the default value of "Checkbox List" to be System.Collections.Generic.List\u00601[System.String]. 69 //Then if there is 0 options in "Checkbox List", it inserts this value in the database, and then the module shows no content, as there is no content 70 //with the tag "System.Collections.Generic.List\u00601[System.String]" 71 //so the following line is to remove that. If it is fixed in newer DW10, this can be removed. 72 allTagsList.RemoveAll(tag => tag == "System.Collections.Generic.List\u00601[System.String]"); 73 74 var allTags = allTagsList.ToArray(); 75 76 return allTags; 77 } 78 79 private List<Dynamicweb.Frontend.ItemViewModel> GetPagesByPageId(IEnumerable<int> pageIds) 80 { 81 var lists = new List<Dynamicweb.Frontend.ItemViewModel>(); 82 83 if (pageIds.Any()) 84 { 85 foreach (var tagPageID in pageIds) 86 { 87 var page = Dynamicweb.Content.Services.Pages?.GetPage(Dynamicweb.Core.Converter.ToInt32(tagPageID)) ?? null; 88 var viewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(page)?.Item ?? null; 89 90 if (viewModel != null) 91 { 92 lists.Add(viewModel); 93 } 94 } 95 } 96 return lists; 97 98 } 99 100 101 private int? ToInt(string value) 102 { 103 return Converter.ToInt32(value); 104 } 105 106 private DateTime? ToDateTime(string value) 107 { 108 return Converter.ToDateTime(value); 109 } 110 } 111 112 113 @{ 114 //Not a parameter anymore 115 string listBehaviour = Model.Item.GetRawValueString("ListBehaviour", "articles"); 116 117 //Not a parameter anymore 118 string articleListLayout = Model.Item.GetRawValueString("ArticleListLayout", "carousel"); 119 string articleItemLayout = Model.Item.GetRawValueString("ArticleItemLayout", string.Empty); 120 121 string columnTheme = Model.Item.GetRawValueString("ColumnTheme", string.Empty).ToString().Replace(" ", "").Trim().ToLower(); 122 123 string columnThemeClass = columnTheme != string.Empty ? " theme " + columnTheme + " p-3" + (articleListLayout == "carousel" ? " px-lg-4" : string.Empty) : string.Empty; 124 125 var carouselSettings = Model.Item.GetRawValueString("CarouselSettings", "4"); 126 127 string slidesPerPage = $"slider-item-show{carouselSettings}"; 128 string navigationStyle = $"{Model.Item.GetRawValueString("NavigationStyle", "slider-nav-round")}"; 129 string navigationPlacement = $"{Model.Item.GetRawValueString("NavigationPlacement", "slider-nav-on-slides")}"; 130 string indicatorStyle = $"{Model.Item.GetRawValueString("IndicatorStyle", string.Empty)}"; 131 string revealSlides = Model.Item.GetRawValueString("RevealSlides", "reveal") == "reveal" ? "slider-item-reveal" : string.Empty; 132 string sliderItemsGap = Model.Item.GetRawValueString("SliderItemsGap", "slider-item-gap") == "slider-item-nogap" ? "slider-item-nogap" : string.Empty; 133 string navigationAlwaysVisible = (Model.Item.GetBoolean("NavigationAlwaysVisible")) ? "slider-nav-visible" : string.Empty; 134 string navigationVisibleOnTouch = (Model.Item.GetBoolean("NavigationVisibleOnTouch")) ? "slider-nav-touch" : string.Empty; 135 string navigationShowScrollbar = (Model.Item.GetBoolean("NavigationShowScrollbar")) ? "slider-nav-scrollbar" : string.Empty; 136 string scrollBarForceMobile = (Model.Item.GetBoolean("NavigationShowScrollbar")) ? "--swiffy-slider-track-height:0.5rem !important;" : string.Empty; 137 string navigationSmall = (Model.Item.GetBoolean("NavigationSmall")) ? "slider-nav-sm" : string.Empty; 138 string navigationInvertColors = (Model.Item.GetBoolean("NavigationInvertColors")) ? "slider-nav-dark" : string.Empty; 139 string navigationSlideEntirePage = (Model.Item.GetBoolean("NavigationSlideEntirePage")) ? "slider-nav-page" : string.Empty; 140 string navigationNoLoop = (Model.Item.GetBoolean("NavigationNoLoop")) ? "slider-nav-noloop" : string.Empty; 141 string indicatorsOutsideSlider = (Model.Item.GetBoolean("IndicatorsOutsideSlider") && indicatorStyle != string.Empty) ? "slider-indicators-outside" : string.Empty; 142 string indicatorsHighlightActive = (Model.Item.GetBoolean("IndicatorsHighlightActive")) ? "slider-indicators-highlight" : string.Empty; 143 string indicatorsInvertColors = (Model.Item.GetBoolean("IndicatorsInvertedColors")) ? "slider-indicators-dark" : string.Empty; 144 string indicatorsVisibleOnSmallDevices = (Model.Item.GetBoolean("IndicatorsVisibleOnSmallDevices")) ? "slider-indicators-sm" : string.Empty; 145 string animation = Model.Item.GetRawValueString("Animation", string.Empty) != string.Empty ? $"slider-nav-animation {Model.Item.GetRawValueString("Animation")}" : string.Empty; 146 string autoplay = (Model.Item.GetBoolean("Autoplay")) ? "slider-nav-autoplay" : string.Empty; 147 string autoplayInterval = Model.Item.GetRawValueString("AutoplayInterval", string.Empty); 148 bool hideSliderNavigation = false; 149 150 var totalItems = content.Count(); 151 var count = content.Count(); 152 var hasItems = content.Any(); 153 154 var percent = count > 0 ? Convert.ToInt32(Math.Round(((double)count / totalItems) * 100, 0)) : 0; 155 var disableLoadMoreButton = count == totalItems ? true : false; 156 157 var loadMore = !disableLoadMoreButton ? $"onclick=\"document.querySelector('#PageSize_{Pageview.CurrentParagraph.ID}').value='{count + maxItemsInList}'; this.dispatchEvent(new window.Event('change', {{ bubbles: true }}))\"" : null; 158 var disabled = disableLoadMoreButton ? "disabled" : null; 159 160 bool showLoadMore = Model.Item.GetBoolean("ShowLoadMore"); 161 162 string titleFontSize = Model.Item.GetString("TitleFontSize", string.Empty); 163 string gridSettings = Model.Item.GetString("GridSettings", "4"); 164 165 bool showButton = Model.Item.GetBoolean("ShowButton"); 166 bool showDates = Model.Item.GetBoolean("ShowDates"); 167 string ratio = Model.Item.GetString("ImageAspectRatio", string.Empty); 168 ratio = ratio != "0" ? ratio : string.Empty; 169 170 string articleItemTheme = Model.Item.GetString("ArticleItemTheme", string.Empty).Replace(" ", "").Trim().ToLower(); 171 string articleItemShape = Model.Item.GetString("ArticleItemShape", "boxed"); 172 173 174 if (navigationStyle == "slider-nav-none") 175 { 176 hideSliderNavigation = true; 177 } 178 179 <div class="h-100@(columnThemeClass) item_@Model.Item.SystemName.ToLower()"> 180 <div id="@Model.ID" class="user-select-none" style="scroll-margin-top:var(--header-height,150px)"></div> 181 @{ 182 if (!Model.Item.GetBoolean("HideTitle")) 183 { 184 185 string headingLevel = "h2"; 186 string headingLevelStart = $"<{headingLevel} class=\" mb-4\">"; 187 string headingLevelStop = $"</{headingLevel}>"; 188 @headingLevelStart 189 @Model.Item.GetString("Title") 190 @headingLevelStop 191 } 192 } 193 <div id="Slider_@Model.ID" class="swiffy-slider @(slidesPerPage) @(navigationStyle) @(revealSlides) @(navigationPlacement) @(navigationAlwaysVisible) @(navigationVisibleOnTouch) @(sliderItemsGap) @(indicatorStyle) @(navigationShowScrollbar) @(navigationSmall) @(navigationInvertColors) @(indicatorsOutsideSlider) @(navigationNoLoop) @(indicatorsHighlightActive) @(indicatorsInvertColors) @(indicatorsVisibleOnSmallDevices) @(navigationSlideEntirePage) @(animation) @(autoplay) item_@Model.Item.SystemName.ToLower()" style="--swiffy-slider-nav-light:var(--swift-foreground-color);--swiffy-slider-nav-dark:var(--swift-background-color);visibility:hidden;opacity:0;@(scrollBarForceMobile)" data-slider-nav-autoplay-interval="@(autoplayInterval)"> 194 <div class="slider-container pb-3 py-lg-3 px-lg-3 mt-lg-n3 mx-lg-n3"> 195 196 @{ 197 198 // CARD SPECIFIC SETTINGS 199 200 string orderReverseClass = articleItemLayout == "image-right" ? " order-first order-lg-last" : string.Empty; 201 string articleItemLayoutClass = string.Empty; 202 203 string ratioCssClass = ratio != string.Empty ? " ratio" : string.Empty; 204 string ratioVariable = ratio != string.Empty ? "style=\"--bs-aspect-ratio: " + ratio + "\"" : string.Empty; 205 206 string shapeClass = " rounded-0"; 207 if (articleItemShape == "rounded") 208 { 209 shapeClass = " rounded-4"; 210 } 211 212 string settingsClassGrid = string.Empty; 213 switch (gridSettings) 214 { 215 case "2": 216 settingsClassGrid = " grid-md-2"; 217 break; 218 case "3": 219 settingsClassGrid = " grid-md-3"; 220 break; 221 case "4": 222 settingsClassGrid = " grid-md-2 grid-lg-3 grid-xl-4"; 223 break; 224 case "5": 225 settingsClassGrid = " grid-md-2 grid-lg-3 grid-xl-5"; 226 break; 227 } 228 string gridWrapperStart = articleListLayout == "grid" ? $"<div class=\"article-list grid gap-4 grid-1{settingsClassGrid}\">" : null; 229 string gridWrapperEnd = articleListLayout == "grid" ? "</div>" : null; 230 231 bool hasListContext = Pageview.CurrentParagraph.Item["ListContext"] is object; 232 } 233 234 <!--CARDS BEGIN HERE --> 235 @foreach (var item in content) 236 { 237 string title = !string.IsNullOrEmpty(item.GetString("Title")) && !item.GetBoolean("HideTitle") ? item.GetString("Title") : string.Empty; 238 string coverTitle = title; 239 240 List<FileViewModel> imageList = (List<FileViewModel>?)item.Fields?.FirstOrDefault(o => o.SystemName == "Image")?.Value ?? new List<FileViewModel>(); 241 FileViewModel? imageObject = imageList.FirstOrDefault(); 242 string coverImagePath = imageObject?.Path ?? ""; 243 244 int focalX = (int?)imageObject?.FocalX ?? 0; 245 int focalY = (int?)imageObject?.FocalY ?? 0; 246 247 int xPos = 100 - ((100 - focalX) / 2); 248 int yPos = ((100 - focalY) / 2); 249 string cssPosition = $"{xPos}% {yPos}%"; 250 251 string summary = !string.IsNullOrEmpty(item.GetString("Summary")) ? item.GetString("Summary") : string.Empty; 252 253 string? publishedDate = item.GetString("PublishedDate"); 254 bool hidePublishedDate = item.GetBoolean("HidePublishedDate"); 255 256 if (hidePublishedDate) 257 { 258 publishedDate = null; 259 } 260 else 261 { 262 publishedDate = ToDateTime(publishedDate)?.ToShortDateString(); 263 if (publishedDate == "01/01/1900" || (publishedDate is not null && (publishedDate.Contains("1900") || publishedDate.Contains("0001")))) 264 { 265 publishedDate = null; 266 } 267 } 268 269 string link = item.Link; 270 string buttonLabel = item.GetString("ButtonLabel", string.Empty); 271 272 273 string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/"; 274 275 int? author = ToInt(item.GetString("Author")); 276 277 bool renderContentWrapper = true; 278 bool renderArticleInfoWrapper = true; 279 280 if (string.IsNullOrEmpty(title) && string.IsNullOrEmpty(summary) && string.IsNullOrEmpty(publishedDate) && !showButton) 281 { 282 renderContentWrapper = false; 283 } 284 285 if (string.IsNullOrEmpty(publishedDate) || !showDates) 286 { 287 renderArticleInfoWrapper = false; 288 } 289 290 switch (articleItemLayout) 291 { 292 case "image-left": 293 case "image-right": 294 articleItemLayoutClass = !string.IsNullOrEmpty(coverImagePath) && renderContentWrapper ? "flex-lg-row" : articleItemLayoutClass; 295 break; 296 } 297 298 string imageObjectFit = ratio != string.Empty ? "object-fit: cover;" : "object-fit: contain;"; 299 300 string? coverTheme = item.GetString("CoverTheme")?.Replace(" ", "").Trim().ToLower() ?? string.Empty; 301 302 string themeClass = string.Empty; 303 string coverImageWrapperClass = string.Empty; 304 305 if (!string.IsNullOrEmpty(coverTheme)) 306 { 307 articleItemTheme = coverTheme; 308 } 309 310 if (articleItemTheme != string.Empty) 311 { 312 themeClass = " theme " + articleItemTheme; 313 } 314 315 // Exclude self from list - if list has context (Tags) and if is on same page 316 bool excludeSelf = false; 317 bool renderItem = true; 318 319 renderItem = hasListContext && excludeSelf ? renderItem = false : !hasListContext && !excludeSelf ? renderItem : renderItem; 320 321 if (renderItem) 322 { 323 <article class="card border-0 @(string.IsNullOrEmpty(themeClass) ? "gap-3" : null) @articleItemLayoutClass@(themeClass)@(shapeClass) overflow-hidden @LiftOnHover() @ShadowOnHover()" itemscope itemtype="https://schema.org/CreativeWork" style="background-color: var(--swift-background-color)"> 324 325 @if (!string.IsNullOrEmpty(coverImagePath)) 326 { 327 if (Path.GetExtension(coverImagePath).ToLower() == ".svg") 328 { 329 coverImageWrapperClass = !renderContentWrapper ? "d-flex justify-content-center align-items-center h-100 w-100 " : "w-100 "; 330 331 <a class="@(coverImageWrapperClass)@(orderReverseClass)" title="@title" href="@link" tabindex="-1"> 332 <div class="d-flex justify-content-center align-items-center overflow-hidden@(ratioCssClass)" @ratioVariable> 333 @ReadFile(coverImagePath) 334 </div> 335 </a> 336 } 337 else 338 { 339 coverImageWrapperClass = articleItemLayout == "image-top" ? "position-relative" : $"col {orderReverseClass}"; 340 coverImageWrapperClass += renderContentWrapper && articleItemLayout != "image-top" ? " col-lg-5" : string.Empty; 341 342 string figureClass = articleItemLayout == "image-top" ? ratioCssClass : "h-lg-100 ratio ratio-16x9"; 343 ratioVariable = articleItemLayout == "image-top" ? ratioVariable : string.Empty; 344 345 <a class="@coverImageWrapperClass" title="@title" href="@link" tabindex="-1"> 346 <figure class="overflow-hidden m-0 mx-auto @(figureClass)" @ratioVariable> 347 @{ 348 coverImagePath = Dynamicweb.Context.Current.Server.UrlEncode(coverImagePath); 349 imageObjectFit = articleItemLayout != "image-top" ? "object-fit: cover" : imageObjectFit; 350 351 string imgSizeSelector = "50vw"; 352 imgSizeSelector = gridSettings == "1" || carouselSettings == "1" ? "100vw" : imgSizeSelector; 353 imgSizeSelector = gridSettings == "2" || carouselSettings == "2" ? "50vw" : imgSizeSelector; 354 imgSizeSelector = gridSettings == "3" || carouselSettings == "3" ? "33vw" : imgSizeSelector; 355 imgSizeSelector = gridSettings == "4" || carouselSettings == "4" ? "25vw" : imgSizeSelector; 356 imgSizeSelector = gridSettings == "5" || carouselSettings == "5" ? "17vw" : imgSizeSelector; 357 358 string coverImagePathM = $"/Admin/Public/GetImage.ashx?image={coverImagePath}&width=640&format=webp"; 359 string coverImagePathL = $"/Admin/Public/GetImage.ashx?image={coverImagePath}&width=960&format=webp"; 360 string imagePathFallBack = coverImagePathM; 361 362 <img srcset=" 363 @coverImagePathM 640w, 364 @coverImagePathL 960w" 365 src="@imagePathFallBack" 366 sizes="(min-width: 992px) @imgSizeSelector, 100vw" 367 loading="lazy" 368 decoding="async" 369 class="img-fluid image-zoom-lg-1-hover" 370 style="@imageObjectFit; object-position: @cssPosition;" 371 alt="@title"> 372 } 373 </figure> 374 </a> 375 } 376 } 377 378 @if (renderContentWrapper) 379 { 380 <div class="col d-flex flex-column @GetPadding(themeClass)"> 381 <div class="card-body p-0 d-flex flex-column gap-2"> 382 @*Show tag stickers*@ 383 384 @if (!string.IsNullOrEmpty(title)) 385 { 386 <a class="text-decoration-none text-decoration-underline-hover" href="@link"> 387 <h3 class="@titleFontSize mb-0" itemprop="headline">@title</h3> 388 </a> 389 } 390 @if (!string.IsNullOrEmpty(summary)) 391 { 392 <p class="m-0 opacity-75">@summary</p> 393 } 394 395 @*Show tag stickers*@ 396 @GetTagStickers(item) 397 398 @if (showButton) 399 { 400 <div class="mt-auto"> 401 402 @if (!string.IsNullOrEmpty(buttonLabel)) 403 { 404 <a href="@link" class="text-start btn btn-link p-0"> 405 @buttonLabel 406 <span class="icon-auto"> 407 @ReadFile(iconPath + "arrow-right.svg") 408 </span> 409 </a> 410 } 411 else 412 { 413 <a href="@link" class="btn btn-link p-0 lh-1 text-start"> 414 <span class="icon-auto"> 415 @ReadFile(iconPath + "arrow-right.svg") 416 </span> 417 </a> 418 } 419 </div> 420 } 421 422 </div> 423 424 @if (renderArticleInfoWrapper) 425 { 426 <div class="card-footer p-0 pt-3 border-top-0"> 427 <div class="d-flex align-items-center justify-content-between gap-3"> 428 @if (author != null && author != 0) 429 { 430 int authorID = author.Value; 431 var authorUser = Dynamicweb.Security.UserManagement.User.GetUserByID(authorID); 432 string authorImage = !string.IsNullOrEmpty(authorUser?.Image) ? authorUser.Image : string.Empty; 433 string authorImagePath = !string.IsNullOrEmpty(authorUser?.Image) ? $"/Admin/Public/GetImage.ashx?image={authorUser.Image}&width=24&height=24&Crop=0&format=webp" : string.Empty; 434 string authorName = !string.IsNullOrEmpty(authorUser?.Name) ? authorName = authorUser.Name : string.Empty; 435 string authorJobTitle = !string.IsNullOrEmpty(authorUser?.JobTitle) ? authorJobTitle = authorUser.JobTitle : string.Empty; 436 437 <div class="d-flex align-items-center gap-2 fs-8 opacity-75"> 438 439 @if (!string.IsNullOrEmpty(authorImage)) 440 { 441 <img class="img-fluid rounded-circle" src="@authorImagePath" loading="lazy" alt="@authorName" width="24" height="24"> 442 } 443 else 444 { 445 <div class="d-flex align-items-center justify-content-center rounded-circle" style="background-color: rgba(var(--swift-foreground-color-rgb),.25)"> 446 <div class="icon-2 p-1"> 447 @ReadFile(iconPath + "user.svg") 448 </div> 449 </div> 450 } 451 452 <div class="d-flex flex-column lh-1"> 453 @if (!string.IsNullOrEmpty(authorName)) 454 { 455 <span itemprop="author">@authorName</span> 456 } 457 @if (!string.IsNullOrEmpty(authorJobTitle)) 458 { 459 <span class="opacity-75">@authorJobTitle</span> 460 } 461 </div> 462 </div> 463 } 464 465 @if (!string.IsNullOrEmpty(publishedDate)) 466 { 467 468 string articleDateTime = publishedDate; 469 470 <div class="d-flex align-items-center gap-1 fs-8 opacity-75"> 471 <div class="icon-1"> 472 @ReadFile(iconPath + "calendar.svg") 473 </div> 474 <time datetime="@articleDateTime" itemprop="datePublished">@publishedDate</time> 475 </div> 476 } 477 </div> 478 </div> 479 } 480 </div> 481 } 482 </article> 483 } 484 485 486 } 487 488 <!-- CARDS END HERE --> 489 </div> 490 491 @if (!hideSliderNavigation) 492 { 493 <button type="button" title="@Translate("Previous slide")" class="slider-nav" style="z-index:1;"> 494 <span class="visually-hidden">@Translate("Previous slide")</span> 495 </button> 496 <button type="button" title="@Translate("Next slide")" class="slider-nav slider-nav-next" style="z-index:1;"> 497 <span class="visually-hidden">@Translate("Next slide")</span> 498 </button> 499 } 500 @if (indicatorStyle != "slider-indicators-hidden") 501 { 502 <div class="slider-indicators" style="z-index:1;"></div> 503 } 504 505 <script type="module" src="/Files/Templates/Designs/Swift/Assets/js/swiffy-slider.js"></script> 506 <script> 507 window.addEventListener("load", () => { 508 initSlider_@(Model.ID)(); 509 }); 510 511 document.addEventListener("updated.swift.pageupdater", function (data) { 512 initSlider_@(Model.ID)(); 513 }); 514 515 function initSlider_@(Model.ID)() { 516 swift.AssetLoader.Load('/Files/Templates/Designs/Swift/Assets/css/swiffy-slider.min.css', 'css'); 517 window.swiffyslider.initSlider(document.querySelector('#Slider_@Model.ID')); 518 document.querySelector('#Slider_@Model.ID').style.opacity = 1; 519 document.querySelector('#Slider_@Model.ID').style.visibility = "visible"; 520 } 521 </script> 522 523 @if (indicatorStyle != "slider-indicators-hidden") 524 { 525 <script type="module"> 526 const slider = document.querySelector('#Slider_@Model.ID'); 527 const sliderContainer = slider.querySelector('.slider-container'); 528 let slides = sliderContainer.querySelectorAll('article'); 529 const sliderIndicators = slider.querySelector('.slider-indicators'); 530 531 slides.forEach((slide, index) => { 532 const indicator = document.createElement('template'); 533 indicator.innerHTML = ` 534 <button type="button" class="${index == 0 ? "active" : ""}" title='@Translate("Go to slide") ${index + 1}'> 535 <span class="visually-hidden">@Translate("Go to slide") ${index + 1}</span> 536 </button> 537 `; 538 sliderIndicators.appendChild(indicator.content); 539 }); 540 </script> 541 } 542 </div> 543 544 545 </div> 546 } 547 548 @functions { 549 550 551 552 private string GetTagStickers(ItemViewModel item) 553 { 554 var stickers = string.Empty; 555 556 if (item.GetString("ItemPublisher:Item.SystemName") == "Swift_Article") 557 { 558 var showTags = Pageview.CurrentParagraph.Item["ShowTags"] != null ? (Boolean)Pageview.CurrentParagraph.Item["ShowTags"] : false; 559 560 if (showTags && GetTags(item).Count >= 1) 561 { 562 stickers += "<div class=\"d-inline-flex flex-wrap gap-1\">"; 563 foreach (var tag in GetTags(item)) 564 { 565 stickers += CreateSticker(tag); 566 } 567 stickers += "</div>"; 568 } 569 } 570 571 572 /* CUSTOM 9a Content type */ 573 if (item.GetString("ItemPublisher:Item.SystemName") == "9a_Content") 574 { 575 576 } 577 /* CUSTOM END */ 578 579 return stickers; 580 } 581 582 583 584 private List<string> GetTags(ItemViewModel item) 585 { 586 var tags = new List<string>(); 587 588 //foreach (var tag in item.GetLoop("ItemPublisher:Item.Tags.Options")) 589 //{ 590 // if (tag.GetBoolean("ItemPublisher:Item.Tags.Option.IsSelected")) 591 // { 592 // tags.Add(tag.GetString("ItemPublisher:Item.Tags.Option.Label")); 593 // } 594 //} 595 596 return tags; 597 } 598 599 600 private string CreateSticker(string label) 601 { 602 string shape = Pageview.CurrentParagraph.Item["ArticleItemShape"] != null ? Pageview.CurrentParagraph.Item["ArticleItemShape"].ToString() : "boxed"; 603 var sticker = $"<span class=\"badge fw-normal shadow-none\" style=\"border: 1px solid rgba(var(--swift-foreground-color-rgb), 0.2);\">{label}</span>"; 604 return sticker; 605 } 606 607 608 private string LiftOnHover() 609 { 610 bool liftOnHover = Pageview.CurrentParagraph.Item["LiftOnHover"] != null ? (Boolean)Pageview.CurrentParagraph.Item["LiftOnHover"] : false; 611 var lift = liftOnHover ? "lift" : null; 612 return lift; 613 } 614 615 private string ShadowOnHover() 616 { 617 bool shadowOnHover = Pageview.CurrentParagraph.Item["ShadowOnHover"] != null ? (Boolean)Pageview.CurrentParagraph.Item["ShadowOnHover"] : false; 618 var shadow = shadowOnHover ? "shadow-hover" : null; 619 return shadow; 620 } 621 622 private string GetPadding(string theme) 623 { 624 var padding = !string.IsNullOrEmpty(theme) ? "p-3" : null; 625 return padding; 626 } 627 628 private string GetGap(string theme) 629 { 630 var padding = string.IsNullOrEmpty(theme) ? "gap-3" : null; 631 return padding; 632 } 633 }
Lad os tage en snak
Digital forretningstransformation er, hvad vi gør. Vi sikrer, at organisationer er klar til at levere til dagens og morgendagens slutkunde. Takket være vores brancheekspertise kan vi kombinere hastighed og kvalitet i din digitale transformationsrejse.
Vi er klar til at vejlede dig og hjælpe dig med at realisere dine mål.