An error occurred while attaching module (Dynamicweb.Frontend.Content)
System.Data.SqlClient.SqlException (0x80131904): A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: Named Pipes Provider, error: 40 - Could not open a connection to SQL Server) ---> System.ComponentModel.Win32Exception (0x80004005): The system cannot find the file specified
at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection)
at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection)
at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection)
at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
at System.Data.SqlClient.SqlConnection.TryOpenInner(TaskCompletionSource`1 retry)
at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry)
at System.Data.SqlClient.SqlConnection.Open()
at Dynamicweb.Data.DatabaseConnectionProvider.CreateConnection(Boolean open)
at Dynamicweb.Data.Database.CreateConnection()
at Dynamicweb.Data.Database.CreateDataReader(CommandBuilder commandBuilder, IDbConnection connection, IDbTransaction transaction, Int32 commandTimeout)
at Dynamicweb.Ecommerce.Products.ProductRepository.GetProductsBySql(CommandBuilder query, Boolean doRefactoring, Boolean bulkFill, Boolean useAssortments)
at Dynamicweb.Ecommerce.Products.ProductRepository.GetAllVariantProducts(IEnumerable`1 productIds, String productLanguageId)
at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.GetBulkVariants(IEnumerable`1 productIds, String languageId)
at System.Lazy`1.CreateValue()
at System.Lazy`1.LazyInitValue()
at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.<>c__DisplayClass3_1.b__6()
at Dynamicweb.Ecommerce.ProductCatalog.ViewModelPropertyFiller`1.Fill[S](T model, String propertyName, Func`1 source)
at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.BulkCreateView(ProductViewModelSettings settings, Boolean isRecursive, IList`1 products)
at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.CreateView(ProductViewModelSettings settings, Product product)
at Dynamicweb.Ecommerce.ProductCatalog.ProductCatalogFrontend.RenderProduct(String productId, String variantId, String groupId, ProductCatalogSettings settings)
at Dynamicweb.Ecommerce.ProductCatalog.ProductCatalogFrontend.GetContent()
at Dynamicweb.Frontend.Content.GetModuleOutput(Paragraph paragraph, PageView pageview)
ClientConnectionId:00000000-0000-0000-0000-000000000000
Error Number:2,State:0,Class:20
System.Data.SqlClient.SqlException (0x80131904): A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: Named Pipes Provider, error: 40 - Could not open a connection to SQL Server) ---> System.ComponentModel.Win32Exception (0x80004005): The system cannot find the file specified at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection) at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection) at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection) at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions) at System.Data.SqlClient.SqlConnection.TryOpenInner(TaskCompletionSource`1 retry) at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry) at System.Data.SqlClient.SqlConnection.Open() at Dynamicweb.Data.DatabaseConnectionProvider.CreateConnection(Boolean open) at Dynamicweb.Data.Database.CreateConnection() at Dynamicweb.Data.Database.CreateDataReader(CommandBuilder commandBuilder, IDbConnection connection, IDbTransaction transaction, Int32 commandTimeout) at Dynamicweb.Ecommerce.Products.ProductRepository.GetProductsBySql(CommandBuilder query, Boolean doRefactoring, Boolean bulkFill, Boolean useAssortments) at Dynamicweb.Ecommerce.Products.ProductRepository.GetAllVariantProducts(IEnumerable`1 productIds, String productLanguageId) at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.GetBulkVariants(IEnumerable`1 productIds, String languageId) at System.Lazy`1.CreateValue() at System.Lazy`1.LazyInitValue() at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.<>c__DisplayClass3_1.b__6() at Dynamicweb.Ecommerce.ProductCatalog.ViewModelPropertyFiller`1.Fill[S](T model, String propertyName, Func`1 source) at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.BulkCreateView(ProductViewModelSettings settings, Boolean isRecursive, IList`1 products) at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.CreateView(ProductViewModelSettings settings, Product product) at Dynamicweb.Ecommerce.ProductCatalog.ProductCatalogFrontend.RenderProduct(String productId, String variantId, String groupId, ProductCatalogSettings settings) at Dynamicweb.Ecommerce.ProductCatalog.ProductCatalogFrontend.GetContent() at Dynamicweb.Frontend.Content.GetModuleOutput(Paragraph paragraph, PageView pageview) ClientConnectionId:00000000-0000-0000-0000-000000000000 Error Number:2,State:0,Class:20
Error executing template "/Designs/Swift/Paragraph/Swift_ProductDetailsImage_Mennt.cshtml" System.ArgumentNullException: Value cannot be null. Parameter name: source at System.Linq.Enumerable.Where[TSource](IEnumerable`1 source, Func`2 predicate) at CompiledRazorTemplates.Dynamic.RazorEngine_3b43772db7624900a4dda159a34280bc.Execute() in D:\dynamicweb.net\Solutions\Mennt\bekken3x.cloud.dynamicweb-cms.com\files\Templates\Designs\Swift\Paragraph\Swift_ProductDetailsImage_Mennt.cshtml:line 78 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.Ecommerce.ProductCatalog 3 @using Dynamicweb.Frontend 4 @using System.IO 5 6 @functions { 7 public ProductViewModel product { get; set; } = new ProductViewModel(); 8 public string galleryLayout { get; set; } 9 public string[] supportedImageFormats { get; set; } 10 public string[] supportedVideoFormats { get; set; } 11 public string[] supportedDocumentFormats { get; set; } 12 public string[] allSupportedFormats { get; set; } 13 14 public class RatioSettings { 15 public string Ratio { get; set; } 16 public string CssClass { get; set; } 17 public string CssVariable { get; set; } 18 public string Fill { get; set; } 19 } 20 21 public RatioSettings GetRatioSettings(string size = "desktop") { 22 var ratioSettings = new RatioSettings(); 23 24 string ratio = Model.Item.GetRawValueString("ImageAspectRatio", ""); 25 ratio = ratio != "0" ? ratio : ""; 26 string cssClass = ratio != "" && ratio != "fill" ? " ratio" : ""; 27 string cssVariable = ratio != "" && ratio != "fill" ? "--bs-aspect-ratio: " + ratio : ""; 28 cssClass = ratio == "fill" && size == "mobile" ? " ratio" : cssClass; 29 cssVariable = ratio == "fill" && size == "mobile" ? "--bs-aspect-ratio: 66%" : cssVariable; 30 31 ratioSettings.Ratio = ratio; 32 ratioSettings.CssClass = cssClass; 33 ratioSettings.CssVariable = cssVariable; 34 ratioSettings.Fill = ratio == "fill" ? " h-100" : ""; 35 36 return ratioSettings; 37 } 38 39 public string GetArrowsColor() 40 { 41 var invertColor = Model.Item.GetBoolean("InvertModalArrowsColor"); 42 var arrowsColor = invertColor ? " carousel-dark" : string.Empty; 43 return arrowsColor; 44 } 45 } 46 47 @{ 48 ProductViewModel product = null; 49 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails")) 50 { 51 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"]; 52 } 53 else if (Pageview.Page.Item["DummyProduct"] != null && Pageview.IsVisualEditorMode) 54 { 55 var pageViewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(Pageview.Page); 56 ProductListViewModel productList = pageViewModel.Item.GetValue("DummyProduct") != null ? pageViewModel.Item.GetValue("DummyProduct") as ProductListViewModel : new ProductListViewModel(); 57 58 if (productList?.Products is object) 59 { 60 product = productList.Products[0]; 61 } 62 } 63 } 64 65 @if (product is object) { 66 @* Supported formats *@ 67 supportedImageFormats = new string[] { ".jpg", ".jpeg", ".webp", ".png", ".gif", ".bmp", ".tiff" }; 68 supportedVideoFormats = new string[] { "youtu.be", "youtube", "vimeo", ".mp4", ".webm" }; 69 supportedDocumentFormats = new string[] { ".pdf", ".docx", ".xlsx", ".ppt", "pptx" }; 70 allSupportedFormats = supportedImageFormats.Concat(supportedVideoFormats).Concat(supportedDocumentFormats).ToArray(); 71 72 @* Collect the assets *@ 73 var selectedAssetCategories = Model.Item.GetRawValueString("ImageAssets").Split(',').ToList(); 74 bool includeImagePatternImages = Model.Item.GetBoolean("ImagePatternImages"); 75 76 @* Needed image data collection to support both DefaultImage, ImagePatterns and Image Assets *@ 77 string defaultImage = product.DefaultImage != null ? product.DefaultImage.Value : ""; 78 IEnumerable<MediaViewModel> assetsImages = product.AssetCategories.Where(x => selectedAssetCategories.Contains(x.SystemName)).SelectMany(x => x.Assets); 79 assetsImages = assetsImages.OrderByDescending(x => x.Value.Equals(defaultImage)); 80 IEnumerable<MediaViewModel> assetsList = new MediaViewModel[]{}; 81 assetsList = assetsList.Union(assetsImages); 82 assetsList = includeImagePatternImages ? assetsList.Union(product.ImagePatternImages) : assetsList; 83 assetsList = includeImagePatternImages && assetsList.Count() == 0 ? assetsList.Append(product.DefaultImage) : assetsList; 84 85 bool defaultImageFallback = Model.Item.GetBoolean("DefaultImageFallback"); 86 bool showOnlyPrimaryImage = Model.Item.GetBoolean("ShowOnlyPrimaryImage"); 87 88 int totalAssets = 0; 89 if (showOnlyPrimaryImage == false) { 90 foreach (MediaViewModel asset in assetsList) { 91 var assetValue = asset.Value; 92 foreach (string format in allSupportedFormats) { 93 if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) { 94 totalAssets++; 95 } 96 } 97 } 98 } 99 100 if((totalAssets == 0 && product.DefaultImage != null && selectedAssetCategories.Count() == 0) || (showOnlyPrimaryImage == true && product.DefaultImage != null) || totalAssets == 0 && defaultImageFallback) 101 { 102 assetsList = new List<MediaViewModel>(){ product.DefaultImage }; 103 totalAssets = 1; 104 } 105 106 107 @* Theme settings *@ 108 string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("Theme")) ? " theme " + Model.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : ""; 109 110 var badgeParms = new Dictionary<string, object>(); 111 badgeParms.Add("size", "h5"); 112 badgeParms.Add("saleBadgeType", Model.Item.GetRawValue("SaleBadgeType")); 113 badgeParms.Add("saleBadgeCssClassName", Model.Item.GetRawValue("SaleBadgeDesign")); 114 badgeParms.Add("newBadgeCssClassName", Model.Item.GetRawValue("NewBadgeDesign")); 115 badgeParms.Add("newPublicationDays", Model.Item.GetInt32("NewPublicationDays")); 116 badgeParms.Add("campaignBadgesValues", Model.Item.GetRawValueString("CampaignBadges")); 117 118 bool saleBadgeEnabled = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("SaleBadgeDesign")) && Model.Item.GetRawValueString("SaleBadgeDesign") != "none" ? true : false; 119 bool newBadgeEnabled = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("NewBadgeDesign")) && Model.Item.GetRawValueString("NewBadgeDesign") != "none" ? true : false; 120 DateTime createdDate = product.Created.Value; 121 bool showBadges = saleBadgeEnabled && product.Discount.Price != 0 ? true : false; 122 showBadges = (newBadgeEnabled && Model.Item.GetInt32("NewPublicationDays") == 0) || (newBadgeEnabled && (createdDate.AddDays(Model.Item.GetInt32("NewPublicationDays")) > DateTime.Now)) ? true : showBadges; 123 showBadges = !string.IsNullOrEmpty(Model.Item.GetRawValueString("CampaignBadges")) ? true : showBadges; 124 125 @* Get assets from selected categories or get all assets *@ 126 if (totalAssets != 0) { 127 int assetNumber = 0; 128 int thumbnailNumber = 0; 129 int modalAssetNumber = 0; 130 131 <div class="h-100@(theme) position-relative item_@Model.Item.SystemName.ToLower()"> 132 <div id="SmallScreenImages_@Model.ID" class="carousel@(GetArrowsColor())" data-bs-ride="carousel"> 133 <div class="carousel-inner h-100"> 134 @foreach (MediaViewModel asset in assetsList) { 135 var assetValue = asset.Value; 136 foreach (string format in allSupportedFormats) { 137 if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) { 138 string activeSlide = assetNumber == 0 ? "active" : ""; 139 140 <div class="carousel-item @activeSlide" data-bs-interval="99999"> 141 @{@RenderAsset(asset, assetNumber, "mobile")} 142 </div> 143 assetNumber++; 144 } 145 } 146 } 147 </div> 148 </div> 149 150 @if (totalAssets > 1) { 151 <div id="SmallScreenImagesThumbnails_@Model.ID" class="grid grid-4 grid-md-6 gap-2 overflow-x-auto my-3"> 152 @foreach (MediaViewModel asset in assetsList) { 153 var assetValue = asset.Value; 154 foreach (string format in allSupportedFormats) { 155 if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) { 156 string imagePath = Dynamicweb.Context.Current.Server.UrlEncode(assetValue); 157 imagePath = assetValue.IndexOf("youtu.be", StringComparison.OrdinalIgnoreCase) >= 0 || assetValue.IndexOf("youtube", StringComparison.OrdinalIgnoreCase) >= 0 ? "https://img.youtube.com/vi/" + assetValue.Substring(assetValue.LastIndexOf('/') + 1) + "/mqdefault.jpg" : imagePath; 158 string imagePathThumb = imagePath.IndexOf("youtube", StringComparison.OrdinalIgnoreCase) < 0 && imagePath.IndexOf(".mp4", StringComparison.OrdinalIgnoreCase) < 0 ? $"/Admin/Public/GetImage.ashx?image={imagePath}&width=180&format=webp" : imagePath; 159 string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/"; 160 161 string videoId = assetValue.Substring(assetValue.LastIndexOf('/') + 1); 162 string vimeoJsClass = assetValue.IndexOf("vimeo", StringComparison.OrdinalIgnoreCase) >= 0 ? "js-vimeo-video-thumbnail" : ""; 163 164 bool isDocument = false; 165 foreach (string documentFormat in supportedDocumentFormats) { 166 if (assetValue.IndexOf(documentFormat, StringComparison.OrdinalIgnoreCase) >= 0) { 167 isDocument = true; 168 } 169 } 170 171 string assetName = asset.Name; 172 assetName += !string.IsNullOrEmpty(asset.Keywords) ? " " + asset.Keywords : ""; 173 string assetTitle = !string.IsNullOrEmpty(asset.DisplayName) ? "title=\"" + asset.DisplayName + "\"" : ""; 174 175 if (!isDocument) { 176 RatioSettings ratioSettings = GetRatioSettings("desktop"); 177 178 <div class="border outline-none @(ratioSettings.CssClass)" style="@(ratioSettings.CssVariable); cursor: pointer" data-bs-target="#SmallScreenImages_@Model.ID" data-bs-slide-to="@thumbnailNumber"> 179 <div class="d-flex align-items-center justify-content-center overflow-hidden position-absolute h-100"> 180 @foreach (string videoFormat in supportedVideoFormats) { //Videos 181 if (assetValue.IndexOf(videoFormat, StringComparison.OrdinalIgnoreCase) >= 0) { 182 <div class="icon-3 position-absolute text-light" style="z-index: 1">@ReadFile(iconPath + "play-circle.svg")</div> 183 } 184 } 185 </div> 186 @if (imagePathThumb.IndexOf(".mp4", StringComparison.OrdinalIgnoreCase) < 0) { 187 <img src="@imagePathThumb" alt="@assetName" @assetTitle class="p-0 p-lg-1 @vimeoJsClass w-100 h-100" style="object-fit: contain" data-video-id="@videoId"> 188 } else { 189 string videoType = Path.GetExtension(asset.Value).ToLower(); 190 191 <video preload="auto" class="h-100 w-100" style="object-fit: contain;"> 192 <source src="@imagePathThumb" type="video/@videoType.Replace(".", "")"> 193 </video> 194 } 195 </div> 196 } else { 197 <a href="@assetValue" class="ratio ratio-4x3 border outline-none" style="cursor: pointer" download title="@asset.Value"> 198 @if (asset.Value.IndexOf(".pdf", StringComparison.OrdinalIgnoreCase) >= 0) { 199 <div class="d-flex align-items-center justify-content-center overflow-hidden h-100"> 200 <div class="icon-3 position-absolute text-light" style="z-index: 1">@ReadFile(iconPath + "download.svg")</div> 201 </div> 202 <img src="@imagePathThumb" alt="@assetName" @assetTitle class="p-0 p-lg-1 mw-100 mh-100" style="object-fit: cover;"> 203 } else { 204 <div class="d-flex align-items-center justify-content-center overflow-hidden h-100"> 205 <div class="icon-3 position-absolute" style="z-index: 1">@ReadFile(iconPath + "file-text.svg")</div> 206 </div> 207 } 208 </a> 209 } 210 211 thumbnailNumber++; 212 } 213 } 214 } 215 </div> 216 } 217 218 @if (showBadges) { 219 <div class="position-absolute top-0 left-0 p-2 p-lg-3"> 220 @RenderPartial("Components/EcommerceBadge.cshtml", product, badgeParms) 221 </div> 222 } 223 </div> 224 225 @* Modal with slides *@ 226 <div class="modal fade swift_products-details-images-modal" id="modal_@Model.ID" tabindex="-1" aria-labelledby="productDetailsGalleryModalTitle_@Model.ID" aria-hidden="true"> 227 <div class="modal-dialog modal-dialog-centered modal-xl"> 228 <div class="modal-content"> 229 <div class="modal-header visually-hidden"> 230 <h5 class="modal-title" id="productDetailsGalleryModalTitle_@Model.ID">@product.Title</h5> 231 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> 232 </div> 233 <div class="modal-body p-2 p-lg-3 h-100"> 234 <div id="ModalCarousel_@Model.ID" class="carousel@(GetArrowsColor()) h-100" data-bs-ride="carousel"> 235 <div class="position-absolute end-0" style="z-index: 999;"> 236 <button type="button" class="btn-close text-right" data-bs-dismiss="modal" aria-label="Close"></button> 237 </div> 238 <div class="carousel-inner h-100"> 239 @foreach (MediaViewModel asset in assetsList) { 240 var assetValue = !string.IsNullOrEmpty(asset.Value) ? asset.Value : product.DefaultImage.Value; 241 foreach (string format in supportedImageFormats.Concat(supportedVideoFormats).ToArray()) { 242 if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) { 243 string imagePath = assetValue; 244 string activeSlide = modalAssetNumber == 0 ? "active" : ""; 245 246 var parms = new Dictionary<string, object>(); 247 parms.Add("cssClass", "d-block mw-100 mh-100 m-auto"); 248 parms.Add("fullwidth", true); 249 parms.Add("columns", Model.GridRowColumnCount); 250 251 <div class="carousel-item @activeSlide h-100" data-bs-interval="99999"> 252 @foreach (string imageFormat in supportedImageFormats) { //Images 253 if (assetValue.IndexOf(imageFormat, StringComparison.OrdinalIgnoreCase) >= 0) { 254 @RenderPartial("Components/Image.cshtml", new FileViewModel { Path = imagePath }, parms) 255 } 256 } 257 258 @foreach (string videoFormat in supportedVideoFormats) { //Videos 259 if (assetValue.IndexOf(videoFormat, StringComparison.OrdinalIgnoreCase) >= 0) { 260 {@RenderVideoPlayer(asset, "modal")} 261 } 262 } 263 </div> 264 265 modalAssetNumber++; 266 } 267 } 268 } 269 <button class="carousel-control-prev" type="button" data-bs-target="#ModalCarousel_@Model.ID" data-bs-slide="prev"> 270 <span class="carousel-control-prev-icon" aria-hidden="true"></span> 271 <span class="visually-hidden">@Translate("Previous")</span> 272 </button> 273 <button class="carousel-control-next" type="button" data-bs-target="#ModalCarousel_@Model.ID" data-bs-slide="next"> 274 <span class="carousel-control-next-icon" aria-hidden="true"></span> 275 <span class="visually-hidden">@Translate("Next")</span> 276 </button> 277 </div> 278 </div> 279 </div> 280 </div> 281 </div> 282 </div> 283 } else if (Pageview.IsVisualEditorMode) { 284 RatioSettings ratioSettings = GetRatioSettings("desktop"); 285 286 <div class="h-100 @theme"> 287 <div class="d-block @(ratioSettings.CssClass)@(ratioSettings.Fill)" style="@(ratioSettings.CssVariable)"> 288 <img src="/Files/Images/missing_image.jpg" loading="lazy" decoding="async" class="mh-100 mw-100" style="object-fit: cover;"> 289 </div> 290 </div> 291 } 292 } else if (Pageview.IsVisualEditorMode) { 293 <div class="alert alert-dark m-0">@Translate("No products available")</div> 294 } 295 296 @helper RenderAsset(MediaViewModel asset, int assetNumber, string size = "desktop") { 297 string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("ImageTheme")) ? " theme " + Model.Item.GetRawValueString("ImageTheme").Replace(" ", "").Trim().ToLower() : ""; 298 string assetValue = asset.Value; 299 300 <div class="h-100 @(theme)"> 301 @foreach (string format in supportedImageFormats) { //Images 302 if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) { 303 {@RenderImage(asset, assetNumber, size)} 304 } 305 } 306 @foreach (string format in supportedVideoFormats) { //Videos 307 if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) { 308 if (Model.Item.GetString("OpenVideoInModal") == "true") { 309 {@RenderVideoScreendump(asset, assetNumber, size)} 310 } else { 311 {@RenderVideoPlayer(asset, size)} 312 } 313 } 314 } 315 @foreach (string format in supportedDocumentFormats) { //Documents 316 if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) { 317 {@RenderDocument(asset, assetNumber, size)} 318 } 319 } 320 </div> 321 } 322 323 @helper RenderImage(MediaViewModel asset, int number, string size = "desktop") { 324 if (product is object) 325 { 326 string productName = product.Name; 327 string imagePath = !string.IsNullOrEmpty(asset.Value) ? asset.Value : product.DefaultImage.Value; 328 string imageLinkPath = Dynamicweb.Context.Current.Server.UrlEncode(imagePath); 329 330 RatioSettings ratioSettings = GetRatioSettings(size); 331 332 var parms = new Dictionary<string, object>(); 333 parms.Add("alt", productName + asset.Keywords); 334 parms.Add("itemprop", "image"); 335 parms.Add("fullwidth", true); 336 parms.Add("columns", Model.GridRowColumnCount); 337 if (!string.IsNullOrEmpty(asset.DisplayName)) { 338 parms.Add("title", asset.DisplayName); 339 } 340 341 if (ratioSettings.Ratio == "fill" && galleryLayout != "grid") { 342 parms.Add("cssClass", "w-100 h-100 image-zoom-lg-l-hover"); 343 } else { 344 parms.Add("cssClass", "mw-100 mh-100"); 345 } 346 347 <a href="@imageLinkPath" class="d-block @(ratioSettings.CssClass)@(ratioSettings.Fill)" style="@(ratioSettings.CssVariable)" data-bs-toggle="modal" data-bs-target="#modal_@Model.ID"> 348 <div class="d-flex align-items-center justify-content-center overflow-hidden h-100" data-bs-target="#ModalCarousel_@Model.ID" data-bs-slide-to="@number"> 349 @RenderPartial("Components/Image.cshtml", new FileViewModel { Path = imagePath }, parms) 350 </div> 351 </a> 352 } 353 } 354 355 @helper RenderVideoScreendump(MediaViewModel asset, int number, string size = "desktop") { 356 if (product is object) 357 { 358 string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/"; 359 360 string videoScreendumpPath = !string.IsNullOrEmpty(asset.Value) ? asset.Value : ""; 361 string videoId = videoScreendumpPath.Substring(videoScreendumpPath.LastIndexOf('/') + 1); 362 videoScreendumpPath = videoScreendumpPath.IndexOf("youtu.be", StringComparison.OrdinalIgnoreCase) >= 0 || videoScreendumpPath.IndexOf("youtube", StringComparison.OrdinalIgnoreCase) >= 0 ? "https://img.youtube.com/vi/" + videoId + "/maxresdefault.jpg" : videoScreendumpPath; 363 364 string vimeoJsClass = videoScreendumpPath.IndexOf("vimeo", StringComparison.OrdinalIgnoreCase) >= 0 ? "js-vimeo-video-thumbnail" : ""; 365 videoScreendumpPath = videoScreendumpPath.IndexOf("vimeo", StringComparison.OrdinalIgnoreCase) >= 0 ? "" : videoScreendumpPath; 366 367 string productName = product.Name; 368 productName += !string.IsNullOrEmpty(asset.Keywords) ? " " + asset.Keywords : ""; 369 string assetTitle = !string.IsNullOrEmpty(asset.DisplayName) ? "title=\"" + asset.DisplayName + "\"" : ""; 370 371 RatioSettings ratioSettings = GetRatioSettings(size); 372 373 <div class="d-block @(ratioSettings.CssClass)@(ratioSettings.Fill)" style="@(ratioSettings.CssVariable); cursor: pointer" data-bs-toggle="modal" data-bs-target="#modal_@Model.ID"> 374 <div class="d-flex align-items-center justify-content-center overflow-hidden h-100" data-bs-target="#ModalCarousel_@Model.ID" data-bs-slide-to="@number"> 375 <div class="icon-5 position-absolute" style="z-index: 1">@ReadFile(iconPath + "play-circle.svg")</div> 376 @if (videoScreendumpPath.IndexOf(".mp4", StringComparison.OrdinalIgnoreCase) < 0) 377 { 378 <img src="@videoScreendumpPath" loading="lazy" decoding="async" alt="@productName" @assetTitle class="@vimeoJsClass mw-100 mh-100" data-video-id="@videoId" style="object-fit: cover;" onload="CheckIfVideoThumbnailExist(this)"> 379 } 380 else 381 { 382 string videoType = Path.GetExtension(asset.Value).ToLower(); 383 384 <video preload="auto" class="h-100 w-100" style="object-fit: contain;"> 385 <source src="@asset.Value" type="video/@videoType.Replace(".", "")"> 386 </video> 387 } 388 </div> 389 </div> 390 391 <script> 392 function CheckIfVideoThumbnailExist(image) { 393 if (image.width == 120) { 394 const lowQualityImage = "https://img.youtube.com/vi/@(videoId)/hqdefault.jpg" 395 image.src = lowQualityImage; 396 } 397 } 398 </script> 399 } 400 } 401 402 @helper RenderVideoPlayer(MediaViewModel asset, string size = "desktop") { 403 if (product is object) 404 { 405 string assetName = !string.IsNullOrEmpty(asset.DisplayName) ? asset.DisplayName : asset.Name; 406 string assetValue = asset.Value; 407 string videoId = asset.Value.Substring(asset.Value.LastIndexOf('/') + 1); 408 string type = assetValue.IndexOf("youtu.be", StringComparison.OrdinalIgnoreCase) >= 0 || assetValue.IndexOf("youtube", StringComparison.OrdinalIgnoreCase) >= 0 ? "youtube" : ""; 409 type = assetValue.IndexOf("vimeo", StringComparison.OrdinalIgnoreCase) >= 0 ? "vimeo" : type; 410 type = assetValue.IndexOf(".mp4", StringComparison.OrdinalIgnoreCase) >= 0 || assetValue.IndexOf(".webm", StringComparison.OrdinalIgnoreCase) >= 0 ? "selfhosted" : type; 411 412 string openInModal = Model.Item.GetString("OpenVideoInModal"); 413 bool autoPlay = Model.Item.GetBoolean("VideoAutoPlay"); 414 415 <div class="h-100" itemscope itemtype="https://schema.org/VideoObject"> 416 <span class="visually-hidden" itemprop="name">@assetName</span> 417 <span class="visually-hidden" itemprop="contentUrl">@asset.Value</span> 418 <span class="visually-hidden" itemprop="thumbnailUrl">@asset.Value</span> 419 420 @if (type != "selfhosted") 421 { 422 <div 423 id="player_@(Pageview.CurrentParagraph.ID)_@(videoId)_@size" 424 class="plyr__video-embed" 425 data-plyr-provider="@(type)" 426 data-plyr-embed-id="@videoId" 427 style="--plyr-color-main: var(--swift-foreground-color); height: 100%"> 428 </div> 429 430 <script type="module" src="/Files/Templates/Designs/Swift/Assets/js/plyr.js"></script> 431 432 <script type="module"> 433 var player = new Plyr('#player_@(Pageview.CurrentParagraph.ID)_@(videoId)_@size', { 434 type: 'video', 435 youtube: { 436 noCookie: true, 437 showinfo: 0 438 }, 439 fullscreen: { 440 enabled: true, 441 iosNative: true, 442 } 443 }); 444 445 @if (autoPlay && openInModal == "false") 446 { 447 <text> 448 player.config.autoplay = true; 449 player.config.muted = true; 450 player.config.volume = 0; 451 player.media.loop = true; 452 453 player.on('ready', function() { 454 if (player.config.autoplay === true) { 455 player.media.play(); 456 } 457 }); 458 </text> 459 } 460 461 @if (openInModal == "true") 462 { 463 <text> 464 var productDetailsGalleryModal = document.querySelector('#modal_@Model.ID') 465 productDetailsGalleryModal.addEventListener('hidden.bs.modal', function (event) { 466 player.media.pause(); 467 }) 468 </text> 469 } 470 </script> 471 } 472 else 473 { 474 string autoPlayAttributes = (autoPlay && openInModal == "false") ? "loop autoplay muted playsinline" : ""; 475 string videoType = Path.GetExtension(assetValue).ToLower(); 476 477 <video preload="auto" @autoPlayAttributes class="h-100 w-100" style="object-fit: cover;" controls> 478 <source src="@assetValue" type="video/@videoType.Replace(".", "")"> 479 </video> 480 } 481 </div> 482 } 483 } 484 485 @helper RenderDocument(MediaViewModel asset, int number, string size = "desktop") { 486 if (product is object) 487 { 488 string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/"; 489 490 string productName = product.Name; 491 string imagePath = !string.IsNullOrEmpty(asset.Value) ? asset.Value : product.DefaultImage.Value; 492 string imageLinkPath = imagePath; 493 494 RatioSettings ratioSettings = GetRatioSettings(size); 495 496 var parms = new Dictionary<string, object>(); 497 parms.Add("alt", productName + asset.Keywords); 498 parms.Add("itemprop", "image"); 499 parms.Add("fullwidth", true); 500 parms.Add("columns", Model.GridRowColumnCount); 501 if (!string.IsNullOrEmpty(asset.DisplayName)) { 502 parms.Add("title", asset.DisplayName); 503 } 504 505 if (ratioSettings.Ratio == "fill" && galleryLayout != "grid") { 506 parms.Add("cssClass", "w-100 h-100 image-zoom-lg-l-hover"); 507 } else { 508 parms.Add("cssClass", "mw-100 mh-100"); 509 } 510 511 <a href="@imageLinkPath" class="d-block @(ratioSettings.CssClass)@(ratioSettings.Fill)" style="@(ratioSettings.CssVariable)" download alt="@Translate("Download")"> 512 <div class="d-flex align-items-center justify-content-center overflow-hidden h-100"> 513 <div class="icon-5 position-absolute" style="z-index: 1">@ReadFile(iconPath + "download.svg")</div> 514 @if (asset.Value.IndexOf(".pdf", StringComparison.OrdinalIgnoreCase) >= 0) { 515 @RenderPartial("Components/Image.cshtml", new FileViewModel { Path = imagePath }, parms) 516 } 517 </div> 518 </a> 519 } 520 } 521
Error executing template "Designs/Swift/Paragraph/Manufacturer_Mennt.cshtml" System.NullReferenceException: Object reference not set to an instance of an object. at CompiledRazorTemplates.Dynamic.RazorEngine_18c352f516cb44b78c35259e90f5ffcc.Execute() in D:\dynamicweb.net\Solutions\Mennt\bekken3x.cloud.dynamicweb-cms.com\files\Templates\Designs\Swift\Paragraph\Manufacturer_Mennt.cshtml:line 35 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.Ecommerce.ProductCatalog 3 4 @{ 5 ProductViewModel product = null; 6 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails")) 7 { 8 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"]; 9 } 10 else if (Pageview.Page.Item["DummyProduct"] != null && Pageview.IsVisualEditorMode) 11 { 12 var pageViewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(Pageview.Page); 13 ProductListViewModel productList = pageViewModel.Item.GetValue("DummyProduct") != null ? pageViewModel.Item.GetValue("DummyProduct") as ProductListViewModel : new ProductListViewModel(); 14 15 if (productList?.Products is object) 16 { 17 product = productList.Products[0]; 18 } 19 } 20 } 21 22 @if (product is object) { 23 24 string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("Theme")) ? " theme " + Model.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : ""; 25 26 string titleFontSize = Model.Item.GetRawValueString("TitleFontSize", "display-4"); 27 28 string contentPadding = Model.Item.GetRawValueString("ContentPadding", ""); 29 contentPadding = contentPadding == "none" ? string.Empty : contentPadding; 30 contentPadding = contentPadding == "small" ? " p-2 p-md-3" : contentPadding; 31 contentPadding = contentPadding == "large" ? " p-4 p-md-5" : contentPadding; 32 33 string horizontalAlign = Model.Item.GetRawValueString("HorizontalAlignment", ""); 34 horizontalAlign = horizontalAlign == "center" ? "text-center" : horizontalAlign; 35 horizontalAlign = horizontalAlign == "end" ? "text-end" : horizontalAlign; 36 37 <div class="@(theme) @horizontalAlign @contentPadding"> 38 <a class="manuLink" href="/produkter?Brand=[@product.Manufacturer.Name]"><span class="@titleFontSize">@product.Manufacturer.Name</span></a> 39 </div> 40 41 }else if (Pageview.IsVisualEditorMode) 42 { 43 44 <div class="alert alert-dark m-0">@Translate("leverandør vil bli vist her!")</div> 45 46 } 47 48
Error executing template "Designs/Swift/Paragraph/Swift_ProductBadges.cshtml" System.NullReferenceException: Object reference not set to an instance of an object. at CompiledRazorTemplates.Dynamic.RazorEngine_dbffffa25681455f98085095676cd31c.Execute() in D:\dynamicweb.net\Solutions\Mennt\bekken3x.cloud.dynamicweb-cms.com\files\Templates\Designs\Swift\Paragraph\Swift_ProductBadges.cshtml:line 72 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 3 @using Dynamicweb.Content 4 @using Dynamicweb.Ecommerce.ProductCatalog 5 6 @{ 7 ProductViewModel product = null; 8 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails")) 9 { 10 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"]; 11 } 12 else if (Pageview.Page.Item["DummyProduct"] != null && Pageview.IsVisualEditorMode) 13 { 14 var pageViewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(Pageview.Page); 15 ProductListViewModel productList = pageViewModel.Item.GetValue("DummyProduct") != null ? pageViewModel.Item.GetValue("DummyProduct") as ProductListViewModel : new ProductListViewModel(); 16 17 if (productList?.Products is object) 18 { 19 product = productList.Products[0]; 20 } 21 } 22 } 23 24 @if (product is object) { 25 var badgeParms = new Dictionary<string, object>(); 26 badgeParms.Add("size", "h7"); 27 badgeParms.Add("saleBadgeType", Model.Item.GetRawValue("SaleBadgeType")); 28 badgeParms.Add("saleBadgeCssClassName", Model.Item.GetRawValue("SaleBadgeDesign")); 29 badgeParms.Add("newBadgeCssClassName", Model.Item.GetRawValue("NewBadgeDesign")); 30 badgeParms.Add("newPublicationDays", Model.Item.GetInt32("NewPublicationDays")); 31 badgeParms.Add("campaignBadgesValues", Model.Item.GetRawValueString("CampaignBadges")); 32 33 string badgeSize = Model.Item.GetRawValueString("BadgeSize", "fs-2"); 34 string horizontalAlign = Model.Item.GetRawValueString("HorizontalAlignment", ""); 35 horizontalAlign = horizontalAlign == "center" ? "text-center" : horizontalAlign; 36 horizontalAlign = horizontalAlign == "end" ? "text-end" : horizontalAlign; 37 38 Dictionary<string, ParagraphInfoViewModel> badgeConfigurations; 39 List<string> campaignBadgesValues = Model.Item.GetRawValueString("CampaignBadges") != null ? Model.Item.GetRawValueString("CampaignBadges").Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() : new List<string>(); 40 41 if (Dynamicweb.Context.Current.Items.Contains("badgeConfigurations")) 42 { 43 badgeConfigurations = (Dictionary<string, ParagraphInfoViewModel>)Dynamicweb.Context.Current.Items["badgeConfigurations"]; 44 } 45 else 46 { 47 var badgesPage = Pageview.AreaSettings.GetLink("EcommerceBadgesPage") != null ? Pageview.AreaSettings.GetLink("EcommerceBadgesPage").PageId : 0; 48 var allBadges = badgesPage != 0 ? Dynamicweb.Content.Services.Paragraphs.GetParagraphsByPageId(badgesPage) : null; 49 50 badgeConfigurations = new Dictionary<string, ParagraphInfoViewModel>(); 51 foreach (Paragraph badge in allBadges) 52 { 53 var paragraphviewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreateParagraphInfoViewModel(badge); 54 string cssClassName = paragraphviewModel.Item.GetString("CssClassName").Trim().ToLower(); 55 if (!badgeConfigurations.ContainsKey(cssClassName)) 56 { 57 badgeConfigurations.Add(cssClassName, paragraphviewModel); 58 } 59 } 60 Dynamicweb.Context.Current.Items.Add("badgeConfigurations", badgeConfigurations); 61 } 62 63 int badgesCount = 0; 64 if (badgeConfigurations.Any()) 65 { 66 foreach (string campaign in campaignBadgesValues) 67 { 68 if (!string.IsNullOrEmpty(campaign)) 69 { 70 71 FieldValueViewModel availableCampaignsObject; 72 product.ProductFields.TryGetValue("Campaign", out availableCampaignsObject); 73 74 if (availableCampaignsObject != null) 75 { 76 string campaignType = string.Empty; 77 78 if (badgeConfigurations.ContainsKey(campaign)) 79 { 80 ParagraphInfoViewModel paragraphviewModel; 81 if (badgeConfigurations.TryGetValue(campaign, out paragraphviewModel)) 82 { 83 campaignType = paragraphviewModel.Item.GetRawValueString("CampaignType"); 84 } 85 } 86 87 List<FieldOptionValueViewModel> availableCampaigns = (List<FieldOptionValueViewModel>)availableCampaignsObject.Value; 88 89 foreach (FieldOptionValueViewModel availableOption in availableCampaigns) 90 { 91 if (campaignType == availableOption.Value) 92 { 93 badgesCount++; 94 break; 95 } 96 } 97 } 98 } 99 } 100 } 101 102 bool saleBadgeEnabled = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("SaleBadgeDesign")) && Model.Item.GetRawValueString("SaleBadgeDesign") != "none" ? true : false; 103 bool newBadgeEnabled = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("NewBadgeDesign")) && Model.Item.GetRawValueString("NewBadgeDesign") != "none" ? true : false; 104 DateTime createdDate = product.Created.Value; 105 bool showBadges = saleBadgeEnabled && product.Discount.Price != 0 ? true : false; 106 showBadges = (newBadgeEnabled && Model.Item.GetInt32("NewPublicationDays") == 0) || (newBadgeEnabled && (createdDate.AddDays(Model.Item.GetInt32("NewPublicationDays")) > DateTime.Now)) ? true : showBadges; 107 showBadges = (!string.IsNullOrEmpty(Model.Item.GetRawValueString("CampaignBadges")) && badgesCount != 0) ? true : showBadges; 108 109 if (showBadges) 110 { 111 <div class="@badgeSize @horizontalAlign item_@Model.Item.SystemName.ToLower()"> 112 @RenderPartial("Components/EcommerceBadge.cshtml", product, badgeParms) 113 </div> 114 } 115 else if (Pageview.IsVisualEditorMode) 116 { 117 <span class="badge bg-success text-light rounded-0">@Translate("Badge example")</span> 118 } 119 } 120 else if (Pageview.IsVisualEditorMode) 121 { 122 <span class="badge bg-success text-light rounded-0">@Translate("Badge example")</span> 123 } 124 125
Error executing template "/Designs/Swift/Paragraph/Swift_ProductVariantSelector_Mennt.cshtml" System.InvalidCastException: Unable to cast object of type 'Dynamicweb.Ecommerce.ProductCatalog.ProductViewModel' to type 'Mennt.ThreeXWorkWear.Custom.ViewModels.CustomProductViewmodel'. at CompiledRazorTemplates.Dynamic.RazorEngine_ff2f44a682af420593759ba2333a093b.Execute() in D:\dynamicweb.net\Solutions\Mennt\bekken3x.cloud.dynamicweb-cms.com\files\Templates\Designs\Swift\Paragraph\Swift_ProductVariantSelector_Mennt.cshtml:line 113 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 System.Collections.Generic 3 @using System.Linq 4 @using Dynamicweb.Ecommerce.ProductCatalog 5 @using Dynamicweb.Ecommerce.Variants 6 @using Mennt.ThreeXWorkWear.Custom.ViewModels 7 8 @functions { 9 //Find contrast color (white, black) 10 public static string GetContrastColor(string hexString) 11 { 12 System.Drawing.Color bg = System.Drawing.ColorTranslator.FromHtml(hexString); 13 14 int nThreshold = 105; 15 int bgDelta = Convert.ToInt32((bg.R * 0.299) + (bg.G * 0.587) + 16 (bg.B * 0.114)); 17 18 string foreColor = (255 - bgDelta < nThreshold) ? "#333" : "#fff"; 19 return foreColor; 20 } 21 22 public string GetLayoutForVariantGroup(string variantGroupId) 23 { 24 string showVariantGroups = !string.IsNullOrEmpty(Model.Item.GetString("ShowVariantGroupOptions")) ? Model.Item.GetString("ShowVariantGroupOptions") : "all"; 25 string defaultVariantGroupLayout = Model.Item.GetRawValueString("DefaultVariantGroupLayout", "button"); 26 var selectedVariantGroupsList = !string.IsNullOrEmpty(Model.Item.GetRawValueString("VariantGroups")) ? Model.Item.GetItems("VariantGroups") : new List<Dynamicweb.Frontend.ItemViewModel>(); 27 28 if (showVariantGroups == "all" || selectedVariantGroupsList == null || !selectedVariantGroupsList.Any()) return defaultVariantGroupLayout; 29 30 foreach (var selectedVariantGroupListItem in selectedVariantGroupsList) 31 { 32 var variantGroups = selectedVariantGroupListItem.GetRawValueString("VariantGroups").Split(','); 33 if (variantGroups.Any(s => s.Equals(variantGroupId))) return selectedVariantGroupListItem.GetRawValueString("VariantGroupLayout"); 34 } 35 36 return defaultVariantGroupLayout; 37 } 38 39 //Collect all variant images 40 public static Dictionary<string, string> GetVariantImages(List<VariantInfoViewModel> variantInfo, Dictionary<string, string> list) 41 { 42 foreach (var variantGroup in variantInfo) 43 { 44 if (variantGroup.Image?.Value != null && !list.ContainsKey(variantGroup.OptionID)) 45 { 46 list.Add(variantGroup.OptionID, variantGroup.Image.Value); 47 } 48 49 if (variantGroup.VariantInfo != null) 50 { 51 GetVariantImages(variantGroup.VariantInfo, list); 52 } 53 } 54 55 return list; 56 } 57 58 private string GetDefaultOrVariantGroupValue(string variantGroupId, string itemField, string itemFieldDefaultValue, Dictionary<string, string> fieldValueMapping) 59 { 60 string itemFieldValue = Model.Item.GetRawValueString(itemField, itemFieldDefaultValue); 61 itemFieldValue = fieldValueMapping.ContainsKey(itemFieldValue) ? fieldValueMapping[itemFieldValue] : itemFieldValue; 62 63 // If no variantGroup (i.e. Visual Editor), return default value 64 if (string.IsNullOrEmpty(variantGroupId)) return itemFieldValue; 65 66 string showVariantGroups = Model.Item.GetString("ShowVariantGroupOptions", "all"); 67 var selectedVariantGroupsList = !string.IsNullOrEmpty(Model.Item.GetRawValueString("VariantGroups")) ? Model.Item.GetItems("VariantGroups") : new List<Dynamicweb.Frontend.ItemViewModel>(); 68 // If no exceptions or settings are all the same, return default value 69 if (showVariantGroups == "all" || selectedVariantGroupsList == null || !selectedVariantGroupsList.Any()) return itemFieldValue; 70 71 // Get specific value for variant group 72 foreach (var selectedVariantGroupListItem in selectedVariantGroupsList) 73 { 74 var variantGroups = selectedVariantGroupListItem.GetRawValueString("VariantGroups").Split(','); 75 if (!variantGroups.Any(s => s.Equals(variantGroupId))) continue; 76 77 itemFieldValue = selectedVariantGroupListItem.GetRawValueString(itemField, itemFieldDefaultValue); 78 itemFieldValue = fieldValueMapping.ContainsKey(itemFieldValue) ? fieldValueMapping[itemFieldValue] : itemFieldValue; 79 } 80 81 return itemFieldValue; 82 } 83 84 private bool GetDefaultOrVariantGroupValue(string variantGroupId, string itemField) 85 { 86 bool itemFieldValue = Model.Item.GetBoolean(itemField); 87 88 // If no variantGroup (i.e. Visual Editor), return default value 89 if (string.IsNullOrEmpty(variantGroupId)) return itemFieldValue; 90 91 string showVariantGroups = Model.Item.GetString("ShowVariantGroupOptions", "all"); 92 var selectedVariantGroupsList = !string.IsNullOrEmpty(Model.Item.GetRawValueString("VariantGroups")) ? Model.Item.GetItems("VariantGroups") : new List<Dynamicweb.Frontend.ItemViewModel>(); 93 // If no exceptions or settings are all the same, return default value 94 if (showVariantGroups == "all" || selectedVariantGroupsList == null || !selectedVariantGroupsList.Any()) return itemFieldValue; 95 96 // Get specific value for variant group 97 foreach (var selectedVariantGroupListItem in selectedVariantGroupsList) 98 { 99 var variantGroups = selectedVariantGroupListItem.GetRawValueString("VariantGroups").Split(','); 100 if (!variantGroups.Any(s => s.Equals(variantGroupId))) continue; 101 102 itemFieldValue = selectedVariantGroupListItem.GetBoolean(itemField); 103 } 104 105 return itemFieldValue; 106 } 107 } 108 109 @{ 110 CustomProductViewmodel product = null; 111 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails")) 112 { 113 product = (CustomProductViewmodel)Dynamicweb.Context.Current.Items["ProductDetails"]; 114 } 115 else if (Pageview.Page.Item["DummyProduct"] != null && Pageview.IsVisualEditorMode) 116 { 117 var pageViewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(Pageview.Page); 118 ProductListViewModel productList = pageViewModel.Item.GetValue("DummyProduct") != null ? pageViewModel.Item.GetValue("DummyProduct") as ProductListViewModel : new ProductListViewModel(); 119 120 if (productList?.Products is object) 121 { 122 product = (CustomProductViewmodel)productList.Products[0]; 123 } 124 } 125 } 126 127 @if ((product is object)) 128 { 129 bool hideGroupHeaders = Model.Item.GetBoolean("HideGroupHeaders"); 130 var productVariantGroups = product.VariantGroups(); 131 132 if (productVariantGroups.Any()) 133 { 134 string[] variantId = product.VariantId.Split('.'); 135 int groupNumber = 1; 136 137 string baseUrl = $"Default.aspx?ID={GetPageIdByNavigationTag("Shop")}&GroupID={product.PrimaryOrDefaultGroup.Id}&ProductID={product.Id}"; 138 string variantUrl = ""; 139 if (!string.IsNullOrEmpty(product.VariantId)) 140 { 141 variantUrl = Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl($"Default.aspx?ID={GetPageIdByNavigationTag("Shop")}&GroupID={product.PrimaryOrDefaultGroup.Id}&ProductID={product.Id}&VariantID={product.VariantId}"); 142 } 143 144 Dictionary<string, string> variantImages = new Dictionary<string, string>(); 145 variantImages = GetVariantImages(product.VariantInfo.VariantInfo, variantImages); 146 147 if (product.ColorVariants != null && product.ColorVariants.Any()) 148 { 149 var selectedColorOptions = product.ColorVariants.FirstOrDefault(x => x.Active)?.ColorVariantOptions; 150 151 if (selectedColorOptions != null) 152 { 153 var colorName = String.Join("/", selectedColorOptions.Select(x => x.Name)); 154 string selectedColors = String.Join(",", selectedColorOptions.Select(x => x.Color)); 155 string[] colorArray = selectedColors.Split(','); 156 @*<div>HasVariants: @product.HasVariants</div> 157 <div>TotalVariantStock: @product.TotalVariantStock</div>*@ 158 <div class="mb-3"> 159 <h3 class="h6">Farge - @colorName</h3> 160 <div class="d-flex gap-2 flex-wrap"> 161 @foreach (var option in product.ColorVariants.OrderBy(x => x.ProductId).ToList()) 162 { 163 var active = option.Active ? "active" : string.Empty; 164 var variantLinkPart = !string.IsNullOrEmpty(product.VariantId) ? $"&VariantID={product.VariantId}" : string.Empty; 165 var link = Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl($"Default.aspx?ID={GetPageIdByNavigationTag("Shop")}&GroupID={product.PrimaryOrDefaultGroup.Id}&ProductID={option.ProductId}{variantLinkPart}"); 166 167 if (selectedColorOptions.Count() == 2 && option.ColorVariantOptions.Count() == 2) { 168 var colorVariantOptionPrimary = option.ColorVariantOptions[0]; 169 var colorVariantOptionSecondary = option.ColorVariantOptions[1]; 170 var contrastColorPrimary = GetContrastColor(colorVariantOptionPrimary.Color); 171 var contrastColorSecondary = GetContrastColor(colorVariantOptionSecondary.Color); 172 173 <button type="button" class="btn colorbox rounded-circle variant-option border js-variant-option split-button @active" style="background: linear-gradient(135deg, @colorVariantOptionPrimary.Color 50%, @colorVariantOptionSecondary.Color 50%);" onclick="swift.PageUpdater.AddPreloaders(null, document.querySelector('#content')); window.location = '@link';"> 174 <span class="visually-hidden">@(colorVariantOptionPrimary.Color)/@(colorVariantOptionSecondary.Color)</span> 175 </button> 176 } 177 else 178 { 179 var colorVariantOption = option.ColorVariantOptions[0]; 180 var contrastColor = GetContrastColor(colorVariantOption.Color); 181 182 if(option.ColorVariantOptions.Count() == 2){ 183 var colorVariantOptionPrimary = option.ColorVariantOptions[0]; 184 var colorVariantOptionSecondary = option.ColorVariantOptions[1]; 185 <button type="button" class="btn colorbox rounded-circle variant-option border js-variant-option split-button @active" style="background: linear-gradient(135deg, @colorVariantOptionPrimary.Color 50%, @colorVariantOptionSecondary.Color 50%);" onclick="swift.PageUpdater.AddPreloaders(null, document.querySelector('#content')); window.location = '@link';"> 186 <span class="visually-hidden">@(colorVariantOptionPrimary.Color)/@(colorVariantOptionSecondary.Color)</span> 187 </button> 188 } 189 else{ 190 <button type="button" class="btn colorbox rounded-circle variant-option border js-variant-option @active" style="background-color: @colorVariantOption.Color; --variantoption-check-color: @contrastColor" onclick="swift.PageUpdater.AddPreloaders(null, document.querySelector('#content')); window.location = '@link';"> 191 <span class="visually-hidden">@colorVariantOption.Color</span> 192 </button> 193 } 194 195 } 196 } 197 </div> 198 </div> 199 } 200 } 201 202 203 @*<form class="d-flex flex-column gap-2 js-variant-selector item_@Model.Item.SystemName.ToLower()" data-combinations="@string.Join(",", product.VariantCombinations())" data-base-url="@baseUrl" data-friendly-url="@variantUrl"> 204 @foreach (var variantGroup in productVariantGroups) 205 { 206 VariantGroupViewModel group = variantGroup; 207 string variantGroupLayout = GetLayoutForVariantGroup(variantGroup.Id); 208 string horizontalAlign = GetDefaultOrVariantGroupValue(variantGroup.Id, "HorizontalAlignment", "", new Dictionary<string, string> { { "center", "justify-content-center" }, { "end", "justify-content-end" } }); 209 string horizontalTextAlign = GetDefaultOrVariantGroupValue(variantGroup.Id, "HorizontalAlignment", "", new Dictionary<string, string> { { "center", "text-center" }, { "end", "text-end" } }); 210 bool showSelectedOptionName = GetDefaultOrVariantGroupValue(variantGroup.Id, "ShowSelectedOptionName"); 211 212 <div> 213 @if (!hideGroupHeaders) 214 { 215 if (@variantGroup.Id != "VARGRP4") { 216 <h3 class="h6 @horizontalTextAlign"> 217 @group.Name 218 219 @if (showSelectedOptionName) 220 { 221 string selectedOptionName = group.Options.FirstOrDefault(opt => variantId.Contains(opt.Id))?.Name ?? string.Empty; 222 <span class="fw-light px-1 swift-selected-option-name">- @selectedOptionName</span> 223 } 224 </h3> 225 } 226 } 227 <div class="d-flex gap-2 @horizontalAlign flex-wrap js-variant-group" data-group-id="@groupNumber"> 228 @if (variantGroupLayout == "button") 229 { 230 foreach (var option in group.Options) 231 { 232 string active = variantId != null && variantId.Contains(option.Id) ? "active" : ""; 233 string buttonId = $"{product.Id}_{option.Id}_{Pageview.CurrentParagraph.ID}"; 234 string contrastColor = string.Empty; 235 string optionLayout = optionLayout = GetDefaultOrVariantGroupValue(variantGroup.Id, "ButtonLayout", "rounded-circle", new Dictionary<string, string> { { "round", "rounded-circle" }, { "square", "" } }); 236 var displayType = group.DisplayType; 237 238 switch (displayType) 239 { 240 case VariantGroupDisplayType.VariantColor: 241 contrastColor = GetContrastColor(option.Color); 242 <button type="button" class="btn colorbox @optionLayout d-inline-block variant-option border js-variant-option @active" style="background-color: @option.Color; --variantoption-check-color: @contrastColor" onclick="swift.VariantSelector.OptionClick(event)" data-variant-id="@option.Id" id="@buttonId"> 243 <span class="visually-hidden">@option.Color</span> 244 </button> 245 break; 246 case VariantGroupDisplayType.VariantImage: 247 string variantImage = string.Empty; 248 if (variantImages.TryGetValue(option.Id, out variantImage)) 249 { 250 <button type="button" class="btn p-0 d-inline-block @optionLayout variant-option js-variant-option @active" onclick="swift.VariantSelector.OptionClick(event)" data-variant-id="@option.Id" id="@(product.Id)_@(option.Id)_@Pageview.CurrentParagraph.ID"> 251 <img class="@optionLayout" src="/Admin/Public/GetImage.ashx?image=@(variantImage)&width=42&format=webp"> 252 </button> 253 } 254 else 255 { 256 <button type="button" class="btn btn-secondary d-inline-block variant-option js-variant-option @active" onclick="swift.VariantSelector.OptionClick(event)" data-variant-id="@option.Id" id="@(product.Id)_@(option.Id)_@Pageview.CurrentParagraph.ID"> 257 @option.Name 258 </button> 259 } 260 261 break; 262 case VariantGroupDisplayType.VariantName: 263 if (@variantGroup.Id != "VARGRP4") { 264 <button type="button" class="btn btn-secondary d-inline-block variant-option js-variant-option @active" onclick="swift.VariantSelector.OptionClick(event)" data-variant-id="@option.Id" id="@buttonId"> 265 @option.Name 266 </button> 267 } 268 break; 269 case VariantGroupDisplayType.VariantOptionImage: 270 <button type="button" class="btn p-0 d-inline-block @optionLayout variant-option js-variant-option @active" onclick="swift.VariantSelector.OptionClick(event)" data-variant-id="@option.Id" id="@(product.Id)_@(option.Id)_@Pageview.CurrentParagraph.ID"> 271 <img class="@optionLayout" src="/Admin/Public/GetImage.ashx?image=@(option.OptionImage.Value)&width=42&format=webp"> 272 </button> 273 break; 274 default: 275 if (!string.IsNullOrEmpty(option.Color)) 276 { 277 contrastColor = GetContrastColor(option.Color); 278 <button type="button" class="btn colorbox @optionLayout d-inline-block variant-option border js-variant-option @active" style="background-color: @option.Color; --variantoption-check-color: @contrastColor" onclick="swift.VariantSelector.OptionClick(event)" data-variant-id="@option.Id" id="@buttonId"> 279 <span class="visually-hidden">@option.Color</span> 280 </button> 281 } 282 else if (!string.IsNullOrEmpty(option.Color) && !string.IsNullOrEmpty(option.Image.Value)) 283 { 284 <button type="button" class="btn p-0 d-inline-block @optionLayout variant-option js-variant-option @active" onclick="swift.VariantSelector.OptionClick(event)" data-variant-id="@option.Id" id="@buttonId"> 285 <img src="/Admin/Public/GetImage.ashx?image=@(option.Image.Value)&width=42&format=webp"> 286 </button> 287 } 288 else 289 { 290 <button type="button" class="btn btn-secondary d-inline-block variant-option js-variant-option @active" onclick="swift.VariantSelector.OptionClick(event)" data-variant-id="@option.Id" id="@buttonId"> 291 @option.Name 292 </button> 293 } 294 break; 295 } 296 } 297 } 298 else 299 { 300 <select class="form-select" id="VariantDropdown_@variantGroup.Id" aria-label="@variantGroup.Name" onchange="swift.VariantSelector.OptionClick(event)"> 301 @if (string.IsNullOrEmpty(product.VariantId)) 302 { 303 <option value="" class="variant-option js-variant-option" data-variant-id="">@Translate("Nothing selected")</option> 304 } 305 306 @foreach (var option in variantGroup.Options) 307 { 308 string active = variantId != null && variantId.Contains(option.Id) ? "active" : ""; 309 var selected = variantId != null && variantId.Contains(option.Id) ? "selected" : ""; 310 var value = $"{product.Id}_{option.Id}"; 311 312 <option value="@(value)" class="variant-option js-variant-option @active" data-variant-id="@option.Id" id="@(value)_@(Pageview.CurrentParagraph.ID)" @selected>@option.Name</option> 313 } 314 </select> 315 } 316 </div> 317 </div> 318 319 groupNumber++; 320 } 321 </form>*@ 322 323 <script type="module"> 324 swift.VariantSelector.init(); 325 </script> 326 } 327 else if (Pageview.IsVisualEditorMode) 328 { 329 string horizontalAlign = GetDefaultOrVariantGroupValue("", "HorizontalAlignment", "", new Dictionary<string, string> { { "center", "justify-content-center" }, { "end", "justify-content-end" } }); 330 string horizontalTextAlign = GetDefaultOrVariantGroupValue("", "HorizontalAlignment", "", new Dictionary<string, string> { { "center", "text-center" }, { "end", "text-end" } }); 331 332 <form class="d-flex flex-column js-variant-selector item_@Model.Item.SystemName.ToLower()" data-combinations="VO1,VO2,VO3,VO4"> 333 <div> 334 @if (!hideGroupHeaders) 335 { 336 <h3 class="h6 @horizontalTextAlign">@Translate("Sizes")test</h3> 337 } 338 <div class="mb-3 @horizontalAlign js-variant-group" data-group-id="0"> 339 <button type="button" class="btn btn-secondary d-inline-block mb-2 variant-option js-variant-option" onclick="swift.VariantSelector.OptionClick(event)" data-variant-id="VO1" id="@(product.Id)_VO1_@Pageview.CurrentParagraph.ID">S</button> 340 <button type="button" class="btn btn-secondary d-inline-block mb-2 variant-option js-variant-option" onclick="swift.VariantSelector.OptionClick(event)" data-variant-id="VO2" id="@(product.Id)_VO2_@Pageview.CurrentParagraph.ID">M</button> 341 <button type="button" class="btn btn-secondary d-inline-block mb-2 variant-option js-variant-option" onclick="swift.VariantSelector.OptionClick(event)" data-variant-id="VO3" id="@(product.Id)_VO3_@Pageview.CurrentParagraph.ID">L</button> 342 <button type="button" class="btn btn-secondary d-inline-block mb-2 variant-option js-variant-option" onclick="swift.VariantSelector.OptionClick(event)" data-variant-id="VO4" id="@(product.Id)_VO4_@Pageview.CurrentParagraph.ID">XL</button> 343 </div> 344 </div> 345 </form> 346 347 <script type="module"> 348 swift.VariantSelector.init(); 349 </script> 350 } 351 } 352 else if (Pageview.IsVisualEditorMode) 353 { 354 <div class="alert alert-dark m-0" role="alert"> 355 <span>@Translate("No products available")</span> 356 </div> 357 } 358 359 360
Error executing template "/Designs/Swift/Paragraph/Swift_ProductStock_Mennt.cshtml" System.InvalidCastException: Unable to cast object of type 'Dynamicweb.Ecommerce.ProductCatalog.ProductViewModel' to type 'Mennt.ThreeXWorkWear.Custom.ViewModels.CustomProductViewmodel'. at CompiledRazorTemplates.Dynamic.RazorEngine_0b39ea4982a84a96aa4b7c157796f586.Execute() in D:\dynamicweb.net\Solutions\Mennt\bekken3x.cloud.dynamicweb-cms.com\files\Templates\Designs\Swift\Paragraph\Swift_ProductStock_Mennt.cshtml:line 9 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.Ecommerce.ProductCatalog 3 @using Mennt.ThreeXWorkWear.Custom.ViewModels 4 5 @{ 6 CustomProductViewmodel product = null; 7 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails")) 8 { 9 product = (CustomProductViewmodel)Dynamicweb.Context.Current.Items["ProductDetails"]; 10 } 11 else if (Pageview.Page.Item["DummyProduct"] != null && Pageview.IsVisualEditorMode) 12 { 13 var pageViewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(Pageview.Page); 14 ProductListViewModel productList = pageViewModel.Item.GetValue("DummyProduct") != null ? pageViewModel.Item.GetValue("DummyProduct") as ProductListViewModel : new ProductListViewModel(); 15 16 if (productList?.Products is object) 17 { 18 product = (CustomProductViewmodel)productList.Products[0]; 19 } 20 } 21 22 bool isErpConnectionDown = !Dynamicweb.Core.Converter.ToBoolean(Dynamicweb.Context.Current.Items["IsWebServiceConnectionAvailable"]); 23 bool hideStock = Model.Item.GetBoolean("HideStockState") || (Pageview.AreaSettings.GetBoolean("ErpDownHideStock") && isErpConnectionDown); 24 } 25 26 @if (product is object && !hideStock) 27 { 28 bool IsNeverOutOfStock = product.NeverOutOfstock; 29 30 string horizontalAlign = Model.Item.GetRawValueString("HorizontalAlignment", ""); 31 horizontalAlign = horizontalAlign == "center" ? "text-center" : horizontalAlign; 32 horizontalAlign = horizontalAlign == "end" ? "text-end" : horizontalAlign; 33 bool hasExpectedDelivery = product.ExpectedDelivery != null && product.ExpectedDelivery > DateTime.Now; 34 string expectedDeliveryDate = product.ExpectedDelivery?.ToShortDateString() ?? ""; 35 36 string liveInfoClass = ""; 37 string productInfoFeed = ""; 38 bool isLazyLoadingForProductInfoEnabled = Dynamicweb.Core.Converter.ToBoolean(Dynamicweb.Context.Current.Items["IsLazyLoadingForProductInfoEnabled"]); 39 if (isLazyLoadingForProductInfoEnabled) 40 { 41 if (Dynamicweb.Context.Current.Items.Contains("ProductInfoFeed")) 42 { 43 productInfoFeed = Dynamicweb.Context.Current.Items["ProductInfoFeed"]?.ToString(); 44 if (!string.IsNullOrEmpty(productInfoFeed)) 45 { 46 productInfoFeed = $"data-product-info-feed=\"{productInfoFeed}\""; 47 } 48 } 49 liveInfoClass = "js-live-info"; 50 } 51 52 var orderItemModel = product.ProductFields.Values.FirstOrDefault(x => x.SystemName == "orderItem"); 53 var orderItemValue = orderItemModel.Value.ToString(); 54 var orderItemTextModel = product.ProductFields.Values.FirstOrDefault(x => x.SystemName == "orderItemText"); 55 var orderItemTextValue = orderItemTextModel.Value.ToString(); 56 57 if (!Pageview.IsVisualEditorMode) 58 { 59 string deliveryLabel = !string.IsNullOrEmpty(product.StockDeliveryText) ? $"{product.StockDeliveryText}" : ""; 60 deliveryLabel += !string.IsNullOrEmpty(product.StockDeliveryValue) ? $" {product.StockDeliveryValue}" : ""; 61 62 if (isLazyLoadingForProductInfoEnabled) 63 { 64 string inStockStateLabel = !string.IsNullOrEmpty(product.StockStatus) ? product.StockStatus : Translate("In stock"); 65 string noStockStateLabel = !string.IsNullOrEmpty(product.StockStatus) ? product.StockStatus : Translate("Out of Stock"); 66 67 <div class="js-stock-state @horizontalAlign item_@Model.Item.SystemName.ToLower() @liveInfoClass" data-product-id="@product.Id" data-variant-id="@product.VariantId" @productInfoFeed> 68 <div class="js-stock-state spinner-border"> 69 70 <div class="small d-none" data-show-if="LiveProductInfo.product.StockLevel > 0"> 71 @if (!Model.Item.GetBoolean("HideInventory")) 72 { 73 <span class="text-success test js-text-stock"></span> 74 } 75 <span class="text-success">@inStockStateLabel</span> 76 <span class="opacity-75">@deliveryLabel</span> 77 </div> 78 79 <div class="small text-danger d-none" data-show-if="LiveProductInfo.product.StockLevel <= 0">@noStockStateLabel</div> 80 81 <div class="d-none" data-show-if="LiveProductInfo.product.ExpectedDelivery != null && new Date(LiveProductInfo.product.ExpectedDelivery) > new Date()"> 82 <span>@Translate("Expected back in stock"): </span> 83 <span class="js-text-expected-delivery"></span> 84 </div> 85 } 86 else 87 { 88 <span>test</span> 89 } 90 </div> 91 </div> 92 } 93 else 94 { 95 string firstUnitId = product?.UnitOptions?.FirstOrDefault() != null ? product.UnitOptions.FirstOrDefault().Id : ""; 96 string defaultUnitId = !string.IsNullOrEmpty(product.DefaultUnitId) ? product.DefaultUnitId : firstUnitId; 97 string unitId = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.Form.Get("UnitId")) ? Dynamicweb.Context.Current.Request.Form.Get("UnitId") : defaultUnitId; 98 99 var reserveMode = Dynamicweb.Ecommerce.Frontend.Cart.ProductReserve.Mode; 100 double? reservedAmount = 0; 101 if (reserveMode == Dynamicweb.Ecommerce.Frontend.Cart.ProductReserveMode.AddToCart) 102 { 103 reservedAmount = Dynamicweb.Ecommerce.Frontend.Cart.ProductReserve.GetReservedAmount(product.Id, product.VariantId, 0, unitId); 104 } 105 double? currentStockLevel = product.StockLevel - reservedAmount; 106 107 string stockStateLabel = currentStockLevel > 0 ? Translate("In stock") : Translate("Out of stock"); 108 stockStateLabel = !string.IsNullOrEmpty(product.StockStatus) ? product.StockStatus : stockStateLabel; 109 110 string stockStateCss = currentStockLevel > 0 ? "text-success" : "text-danger"; 111 string stockStateIconCss = currentStockLevel > 0 ? "bg-success" : "bg-danger"; 112 113 string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/"; 114 115 string stockIcon = currentStockLevel > 0 ? "check-circle.svg" : "check-circle.svg"; 116 117 var variantsInStock = "False"; 118 119 if (product.VariantInfo.VariantInfo != null) 120 { 121 foreach (var variant in product.VariantInfo.VariantInfo) 122 { 123 if (variant.Stock > 0) 124 { 125 variantsInStock = "True"; 126 127 break; 128 } 129 } 130 } 131 132 133 <div class="js-stock-state @horizontalAlign item_@Model.Item.SystemName.ToLower()"> 134 135 @if (product.TotalVariantStock <= 0 && variantsInStock == "False") 136 { 137 138 <div class="d-flex align-items-center justify-content-sm-start" style="color: #ff7400;"> 139 <span class="icon-3 me-2"> 140 @ReadFile(iconPath + "alert-triangle.svg") 141 </span> 142 @if (hasExpectedDelivery) 143 { 144 <span>@Translate("Forventet inn") @expectedDeliveryDate</span> 145 } 146 else 147 { 148 if (!string.IsNullOrEmpty(orderItemTextValue)) 149 { 150 <span>@orderItemTextValue</span> 151 } 152 else 153 { 154 <span>@Translate("Bestillingsvare: 5-7 virkedager")</span> 155 } 156 157 } 158 159 </div> 160 } 161 else 162 { 163 <div class="d-flex align-items-center"> 164 <span class="icon-3 me-2 bg-succes text-success"> 165 @ReadFile(iconPath + @stockIcon) 166 </span> 167 168 @if (product.VariantInfo.VariantInfo == null) 169 { 170 <span class="text-success">@product.StockLevel stk. på lager</span> 171 } 172 else 173 { 174 <span class="text-success">På lager</span> 175 } 176 177 </div> 178 179 } 180 </div> 181 } 182 } 183 else if (Pageview.IsVisualEditorMode) 184 { 185 <div class="alert alert-info">@Translate("No products available")</div> 186 } 187 } 188
Error executing template "Designs/Swift/Paragraph/Swift_TechnicalSpecifications_Mennt.cshtml" System.NullReferenceException: Object reference not set to an instance of an object. at CompiledRazorTemplates.Dynamic.RazorEngine_5026e57e361d433dbade71ea8842e849.Execute() in D:\dynamicweb.net\Solutions\Mennt\bekken3x.cloud.dynamicweb-cms.com\files\Templates\Designs\Swift\Paragraph\Swift_TechnicalSpecifications_Mennt.cshtml:line 43 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.Ecommerce.ProductCatalog 3 @using System.Linq 4 @using Dynamicweb.Core 5 @using Dynamicweb.Environment 6 @using System.IO 7 @using System.Web.Hosting 8 9 @{ 10 ProductViewModel product = null; 11 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails")) 12 { 13 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"]; 14 } 15 else if (Pageview.Page.Item["DummyProduct"] != null && Pageview.IsVisualEditorMode) 16 { 17 var pageViewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(Pageview.Page); 18 ProductListViewModel productList = pageViewModel.Item.GetValue("DummyProduct") != null ? pageViewModel.Item.GetValue("DummyProduct") as ProductListViewModel : new ProductListViewModel(); 19 20 if (productList?.Products is object) 21 { 22 product = productList.Products[0]; 23 } 24 } 25 } 26 27 @if (product is object) 28 { 29 bool hideTitle = Model.Item.GetBoolean("HideTitle"); 30 31 string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("Theme")) ? " theme " + Model.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : ""; 32 string titleFontSize = Model.Item.GetRawValueString("TitleFontSize", "display-4"); 33 34 string contentPadding = Model.Item.GetRawValueString("ContentPadding", ""); 35 contentPadding = contentPadding == "small" ? "p-2 p-md-3" : contentPadding; 36 contentPadding = contentPadding == "large" ? "p-4 p-md-5" : contentPadding; 37 38 string maxWidth = Model.Item.GetRawValueString("TextReadability", "max-width-on"); 39 maxWidth = maxWidth == "max-width-on" ? "mw-75ch d-inline-block" : maxWidth; 40 maxWidth = maxWidth == "max-width-off" ? "" : maxWidth; 41 42 <!-- START Custom fields --> 43 var materialsModel = product.ProductFields.Values.FirstOrDefault(x => x.SystemName == "materials"); 44 var materialsValue = materialsModel.Value.ToString(); 45 46 var cleaningModel = product.ProductFields.Values.FirstOrDefault(x => x.SystemName == "cleaning"); 47 string[] cleaning = cleaningModel.ToString().Split(','); 48 49 var certificationsModel = product.ProductFields.Values.FirstOrDefault(x => x.SystemName == "certifications"); 50 string[] certifications = certificationsModel.ToString().Split(','); 51 52 var documents = product.AssetCategories; 53 54 var productID = Dynamicweb.Ecommerce.Products.Product.GetProductById(product.Id); 55 var categories = productID.GetCategories(); 56 57 <!-- END Custom fields --> 58 @*<pre>Model:<code class="language-json">@System.Text.Json.JsonSerializer.Serialize(Model)</code></pre> 59 <pre>Product:<code class="language-json">@System.Text.Json.JsonSerializer.Serialize(product)</code></pre>*@ 60 61 62 if (!string.IsNullOrEmpty(materialsValue) || !string.IsNullOrEmpty(cleaningModel.ToString()) || !string.IsNullOrEmpty(certificationsModel.ToString()) || documents.Count() > 0) 63 { 64 <div class="@(theme) h-100 item_@Model.Item.SystemName.ToLower()"> 65 <div class="@(contentPadding)" style="display: block !important"> 66 @if (!hideTitle && !string.IsNullOrEmpty(Model.Item.GetString("Title"))) 67 { 68 <div class="text-start pb-2 pb-lg-4"> 69 <h2 class="@titleFontSize @(maxWidth)">@Model.Item.GetString("Title")</h2> 70 </div> 71 } 72 73 <div class="accordion accordion-flush" id="accordion"> 74 @if (!string.IsNullOrEmpty(materialsValue)) 75 { 76 <div class="accordion-item"> 77 <h2 class="accordion-header" id="flush-headingOne"> 78 <button class="accordion-button collapsed text-uppercase fw-bold" type="button" data-bs-toggle="collapse" data-bs-target="#flush-collapseOne" aria-expanded="false" aria-controls="flush-collapseOne"> 79 @materialsModel.Name 80 </button> 81 </h2> 82 <div id="flush-collapseOne" class="accordion-collapse collapse" aria-labelledby="flush-headingOne" data-bs-parent="#accordion"> 83 <div class="accordion-body">@materialsValue</div> 84 85 <div class="accordion-body pt-0"> 86 @foreach (var item in categories) 87 { 88 var fields = item.Fields; 89 var categoreyId = item.Id; 90 91 foreach (var field in fields) 92 { 93 var value = productID.GetCategoryValue(categoreyId, field.Id); 94 95 if (value != null) 96 { 97 if (field.Label != "Farge" && field.Label != "Trykkgruppe" && field.Label != "Type trykk") 98 { 99 <div class="d-flex mb-2"> 100 <div class="fw-bold w-50">@Translate(field.Label)</div> 101 <div>@Translate(value.ToString())</div> 102 </div> 103 } 104 } 105 } 106 } 107 </div> 108 </div> 109 </div> 110 } 111 112 @if (!string.IsNullOrEmpty(cleaningModel.ToString())) 113 { 114 <div class="accordion-item"> 115 <h2 class="accordion-header" id="flush-headingThree"> 116 <button class="accordion-button collapsed text-uppercase fw-bold" type="button" data-bs-toggle="collapse" data-bs-target="#flush-collapseThree" aria-expanded="false" aria-controls="flush-collapseThree"> 117 @cleaningModel.Name 118 </button> 119 </h2> 120 <div id="flush-collapseThree" class="accordion-collapse collapse" aria-labelledby="flush-headingThree" data-bs-parent="#accordion"> 121 <div class="accordion-body"> 122 <div class="d-flex align-items-center"> 123 @foreach (var item in cleaning) 124 { 125 var iconFormatted = item.Replace(" ", "").ToLower(); 126 var iconURL = "/Files/Images/Vask og vedlikehold/" + iconFormatted + ".svg"; 127 <div> 128 <img width="70" src="@iconURL" alt="@item" /> 129 </div> 130 } 131 </div> 132 </div> 133 </div> 134 </div> 135 } 136 137 @if (!string.IsNullOrEmpty(certificationsModel.ToString())) 138 { 139 <div class="accordion-item"> 140 <h2 class="accordion-header" id="flush-headingFour"> 141 <button class="accordion-button collapsed text-uppercase fw-bold" type="button" data-bs-toggle="collapse" data-bs-target="#flush-collapseFour" aria-expanded="false" aria-controls="flush-collapseFour"> 142 @certificationsModel.Name 143 </button> 144 </h2> 145 <div id="flush-collapseFour" class="accordion-collapse collapse" aria-labelledby="flush-headingFour" data-bs-parent="#accordion"> 146 <div class="accordion-body"> 147 <div class="row gap-2"> 148 @foreach (var item in certifications) 149 { 150 var iconFormatted = item.Replace(" ", "").Replace("/", "-").ToLower(); 151 var iconPath = HostingEnvironment.MapPath("~/Files/Images/Sertifiseringer/" + iconFormatted + ".svg"); 152 153 var iconURL = "/Files/Images/Sertifiseringer/" + iconFormatted + ".svg"; 154 <div class="d-flex flex-column col-3 text-center p-0"> 155 @if (File.Exists(iconPath)) // Check if the SVG exists 156 { 157 <img src="@iconURL" alt="@item" height="20" /> 158 } 159 <span>@item</span> 160 </div> 161 162 } 163 </div> 164 </div> 165 </div> 166 </div> 167 } 168 169 @foreach (var item in documents) 170 { 171 if (item.SystemName == "Documents") 172 { 173 174 <div class="accordion-item"> 175 <h2 class="accordion-header" id="flush-headingFive"> 176 <button class="accordion-button collapsed text-uppercase fw-bold" type="button" data-bs-toggle="collapse" data-bs-target="#flush-collapseFive" aria-expanded="false" aria-controls="flush-collapseFive"> 177 @item.Name 178 </button> 179 </h2> 180 <div id="flush-collapseFive" class="accordion-collapse collapse" aria-labelledby="flush-headingFive" data-bs-parent="#accordion"> 181 <div class="accordion-body"> 182 <div class="d-flex align-items-center"> 183 @foreach (var x in item.Assets) 184 { 185 string assetName = !string.IsNullOrEmpty(x.DisplayName) ? x.DisplayName : x.Value.Substring( x.Value.LastIndexOf('/') + 1); 186 string assetURL = x.Value; 187 string imagePath = !string.IsNullOrEmpty(x.Value) ? x.Value : product.DefaultImage.Value; 188 imagePath = $"/Admin/Public/GetImage.ashx?image={imagePath}&width=60&format=webp"; 189 190 <div> 191 <img src="@imagePath" alt="assetName" /> 192 <a href="@assetURL" target="_blank" class="ms-3 text-decoration-none">@assetName</a> 193 </div> 194 } 195 </div> 196 </div> 197 </div> 198 </div> 199 } 200 201 if (item.SystemName == "Sizeguide") 202 { 203 204 <div class="accordion-item"> 205 <h2 class="accordion-header" id="flush-headingSix"> 206 <button class="accordion-button collapsed text-uppercase fw-bold" type="button" data-bs-toggle="collapse" data-bs-target="#flush-collapseSix" aria-expanded="false" aria-controls="flush-collapseSix"> 207 @item.Name 208 </button> 209 </h2> 210 <div id="flush-collapseSix" class="accordion-collapse collapse" aria-labelledby="flush-headingSix" data-bs-parent="#accordion"> 211 <div class="accordion-body"> 212 <div class="d-flex align-items-center"> 213 @foreach (var x in item.Assets) 214 { 215 string assetName = !string.IsNullOrEmpty(x.DisplayName) ? x.DisplayName : x.Value.Substring( x.Value.LastIndexOf('/') + 1); 216 string assetURL = x.Value; 217 string imagePath = !string.IsNullOrEmpty(x.Value) ? x.Value : product.DefaultImage.Value; 218 imagePath = $"/Admin/Public/GetImage.ashx?image={imagePath}&width=60&format=webp"; 219 220 <div> 221 <img src="@imagePath" alt="assetName" /> 222 <a href="@assetURL" target="_blank" class="ms-3 text-decoration-none">@assetName</a> 223 </div> 224 } 225 </div> 226 </div> 227 </div> 228 </div> 229 } 230 } 231 </div> 232 233 </div> 234 </div> 235 } 236 } 237 else if (Pageview.IsVisualEditorMode) 238 { 239 <div class="alert alert-dark m-0">@Translate("Technical specifications will be shown here, if any")</div> 240 } 241
Error executing template "Designs/Swift/Paragraph/Swift_RelatedProducts.cshtml" System.NullReferenceException: Object reference not set to an instance of an object. at CompiledRazorTemplates.Dynamic.RazorEngine_dc20d48c7f304742acb28e51705420fd.Execute() in D:\dynamicweb.net\Solutions\Mennt\bekken3x.cloud.dynamicweb-cms.com\files\Templates\Designs\Swift\Paragraph\Swift_RelatedProducts.cshtml:line 164 at RazorEngine.Templating.TemplateBase.RazorEngine.Templating.ITemplate.Run(ExecuteContext context, TextWriter reader) at RazorEngine.Templating.RazorEngineService.RunCompile(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass16_0.<RunCompile>b__0(TextWriter writer) at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter) at Dynamicweb.Rendering.RazorTemplateRenderingProvider.Render(Template template) at Dynamicweb.Rendering.TemplateRenderingService.Render(Template template) at Dynamicweb.Rendering.Template.RenderRazorTemplate()
1 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.ParagraphViewModel> 2 @using Dynamicweb.Core 3 @using Dynamicweb.Ecommerce.ProductCatalog 4 5 @{ 6 ProductViewModel product = null; 7 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails")) 8 { 9 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"]; 10 } 11 else if (Pageview.Page.Item["DummyProduct"] != null && Pageview.IsVisualEditorMode) 12 { 13 var pageViewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(Pageview.Page); 14 ProductListViewModel productList = pageViewModel.Item.GetValue("DummyProduct") != null ? pageViewModel.Item.GetValue("DummyProduct") as ProductListViewModel : new ProductListViewModel(); 15 16 if (productList?.Products is object) 17 { 18 product = productList.Products[0]; 19 } 20 } 21 22 string title = Model?.Item?.GetRawValueString("Title", Translate("Products")); 23 string campaignValues = Model.Item.GetRawValueString("CampaignBadges", string.Empty); 24 25 //Styling 26 string titleFontSize = Model.Item.GetRawValueString("TitleFontSize", "h3"); 27 string subtitleFontSize = Model.Item.GetRawValueString("SubtitleFontSize", "fs-5"); 28 string buttonStyle = Model.Item.GetRawValueString("ButtonStyle", ""); 29 buttonStyle = buttonStyle == "primary" ? " btn-primary" : buttonStyle; 30 buttonStyle = buttonStyle == "secondary" ? " btn-secondary" : buttonStyle; 31 buttonStyle = buttonStyle == "link" ? " btn-link" : buttonStyle; 32 string maxWidth = Model.Item.GetRawValueString("TextReadability", ""); 33 maxWidth = maxWidth == "max-width-on" ? " mw-75ch" : maxWidth; 34 maxWidth = maxWidth == "max-width-off" ? "" : maxWidth; 35 36 string generalTheme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("GeneralTheme")) ? " theme " + Model.Item.GetRawValueString("GeneralTheme").Replace(" ", "").Trim().ToLower() : ""; 37 string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("Theme")) ? " theme " + Model.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : ""; 38 string imageTheme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("ImageTheme")) ? " theme " + Model.Item.GetRawValueString("ImageTheme").Replace(" ", "").Trim().ToLower() : ""; 39 40 //Link generation 41 string pageId = !string.IsNullOrEmpty(Model.Item.GetRawValueString("ProductSliderServicePage")) ? Model.Item.GetLink("ProductSliderServicePage").PageId.ToString() : ""; 42 if (string.IsNullOrEmpty(pageId)) 43 { 44 pageId = GetPageIdByNavigationTag("ProductSliderService").ToString(); 45 } 46 47 string url = "/Default.aspx?ID=" + pageId; 48 if (!url.Contains("LayoutTemplate", StringComparison.OrdinalIgnoreCase)) 49 { 50 url += url.Contains("?") ? "&LayoutTemplate=Designs/Swift/Swift_PageClean.cshtml" : "?LayoutTemplate=Designs/Swift/Swift_PageClean.cshtml"; 51 } 52 if (Pageview.IsVisualEditorMode) 53 { 54 url += "&VisualEdit=True"; 55 } 56 57 bool isLazyLoadingForProductInfoEnabled = Dynamicweb.Core.Converter.ToBoolean(Dynamicweb.Context.Current.Items["IsLazyLoadingForProductInfoEnabled"]); 58 if (isLazyLoadingForProductInfoEnabled) 59 { 60 url += "&getproductinfo=true"; 61 } 62 63 //Source type 64 string sourceType = Model.Item.GetRawValueString("RelationType", "trending"); 65 IList<string> relateFromGroupIds = new List<string> { }; 66 IList<string> relateFromProductVariantIds = new List<string> { }; 67 IList<string> relateFromProductIds = new List<string> { }; 68 bool hasVariants = false; 69 70 //--- VARIANTS --- 71 if (sourceType == "variants" && Model.Item.GetValue<ProductListViewModel>("ProductsToRelateToVariants") is ProductListViewModel productsToRelateToVariants) 72 { 73 foreach (var productSelection in productsToRelateToVariants.Products) 74 { 75 relateFromProductIds.Add(productSelection.Id); 76 } 77 } 78 79 //--- MOST SOLD --- 80 if (sourceType == "most-sold" && Model.Item.GetValue<IList<ProductGroupViewModel>>("GroupsToRelateToMostSold") is IList<ProductGroupViewModel> groupsToRelateToMostSold) 81 { 82 foreach (var fromGroup in groupsToRelateToMostSold) 83 { 84 relateFromGroupIds.Add(fromGroup.Id); 85 } 86 } 87 88 //--- TRENDING --- 89 if (sourceType == "trending" && Model.Item.GetValue<IList<ProductGroupViewModel>>("GroupsToRelateToTrending") is IList<ProductGroupViewModel> groupsToRelateToTrending) 90 { 91 foreach (var fromGroup in groupsToRelateToTrending) 92 { 93 relateFromGroupIds.Add(fromGroup.Id); 94 } 95 } 96 97 //--- LATEST --- 98 if (sourceType == "latest" && Model.Item.GetValue<IList<ProductGroupViewModel>>("GroupsToRelateToLatest") is IList<ProductGroupViewModel> groupsToRelateToLatest) 99 { 100 foreach (var fromGroup in groupsToRelateToLatest) 101 { 102 relateFromGroupIds.Add(fromGroup.Id); 103 } 104 } 105 106 //--- FREQUENTLY BOUGHT --- 107 if (sourceType == "frequently" && Model.Item.GetValue<ProductListViewModel>("ProductsToRelateTo") is ProductListViewModel productsToRelateTo) 108 { 109 foreach (var fromProduct in productsToRelateTo.Products) 110 { 111 relateFromProductIds.Add(fromProduct.Id); 112 } 113 } 114 115 //--- SELECTED PRODUCTS --- 116 if ((sourceType == "selected" || sourceType == "frequently") && Model.Item.GetValue<ProductListViewModel>("Products") is ProductListViewModel products) 117 { 118 hasVariants = products.Products.Any(p => !string.IsNullOrEmpty(p.VariantId)); 119 foreach (var productSelection in products.Products) 120 { 121 if (hasVariants) 122 { 123 if (!string.IsNullOrEmpty(productSelection.VariantId)) 124 { 125 relateFromProductVariantIds.Add($"{productSelection.Id} {productSelection.VariantId}"); 126 } 127 else 128 { 129 relateFromProductVariantIds.Add($"{productSelection.Id}"); 130 } 131 } 132 relateFromProductIds.Add($"{productSelection.Id}"); 133 } 134 } 135 136 //--- RELATED PRODUCTS --- 137 if (sourceType == "related-products" && Model.Item.GetValue<ProductListViewModel>("ProductsToRelateTo2") is ProductListViewModel selectedRelationProduct) 138 { 139 if (selectedRelationProduct.Products.Any()) 140 { 141 product = selectedRelationProduct.Products.FirstOrDefault(); 142 } 143 144 if (product?.RelatedGroups != null) 145 { 146 foreach (var group in product.RelatedGroups) 147 { 148 foreach (var relatedProduct in group.Products) 149 { 150 if (!string.IsNullOrEmpty(relatedProduct.VariantId)) 151 { 152 relateFromProductVariantIds.Add($"{relatedProduct.ProductId} {relatedProduct.VariantId}"); 153 } 154 else 155 { 156 relateFromProductVariantIds.Add($"{relatedProduct.ProductId}"); 157 } 158 } 159 } 160 } 161 } 162 163 //Create group id collection and products id collection strings 164 string groupIds = product is object ? product.PrimaryOrDefaultGroup.Id : string.Join(",", relateFromGroupIds); 165 string productVariantIds = relateFromProductVariantIds.Count > 0 ? string.Join(",", relateFromProductVariantIds) : ""; 166 string productIds = product is object && relateFromProductIds.Count == 0 ? product.Id : string.Join(",", relateFromProductIds); 167 168 //Set the parameters to the url 169 string linkParameters = ""; 170 linkParameters += sourceType != "related-products" && sourceType != "frequently" && sourceType != "selected" ? "&GroupId=" + groupIds : ""; 171 linkParameters += !string.IsNullOrEmpty(productIds) && sourceType != "most-sold" && sourceType != "trending" && sourceType != "latest" && sourceType != "frequently" && sourceType != "related-products" ? "&MainProductId=" + productIds : ""; 172 linkParameters += !string.IsNullOrEmpty(productVariantIds) && sourceType == "related-products" ? "&ProductVariantId=" + productVariantIds : ""; 173 linkParameters += sourceType == "variants" ? "&IsVariant=true" : ""; 174 linkParameters += sourceType == "latest" ? "&SortBy=Created" : ""; 175 linkParameters += sourceType == "most-sold" ? "&SortBy=OrderCount" : ""; 176 linkParameters += sourceType == "trending" ? "&SortBy=OrderCountGrowth" : ""; 177 linkParameters += !string.IsNullOrEmpty(productIds) && sourceType == "frequently" ? $"&BoughtWithProductIds=[{productIds}]" : ""; 178 var productListPageId = GetPageIdByNavigationTag("Shop"); 179 string link = "/Default.aspx?ID=" + productListPageId + linkParameters; 180 181 // Slider settings (documentation: swiffyslider.com/configuration) 182 string navigationStyle = $"{Model.Item.GetRawValueString("NavigationStyle", "slider-nav-round")}"; 183 string navigationPlacement = $"{Model.Item.GetRawValueString("NavigationPlacement", "slider-nav-on-slides")}"; 184 string indicatorStyle = $"{Model.Item.GetRawValueString("IndicatorStyle", "slider-indicators-hidden")}"; 185 string revealSlides = Model.Item.GetRawValueString("RevealSlides", "no-reveal") == "reveal" ? "slider-item-reveal" : string.Empty; 186 string navigationAlwaysVisible = (Model.Item.GetBoolean("NavigationAlwaysVisible")) ? "slider-nav-visible" : string.Empty; 187 string navigationVisibleOnTouch = (Model.Item.GetBoolean("NavigationVisibleOnTouch")) ? "slider-nav-touch" : string.Empty; 188 string navigationShowScrollbar = (Model.Item.GetBoolean("NavigationShowScrollbar")) ? "slider-nav-scrollbar" : string.Empty; 189 string navigationSmall = (Model.Item.GetBoolean("NavigationSmall")) ? "slider-nav-sm" : string.Empty; 190 string navigationInvertColors = (Model.Item.GetBoolean("NavigationInvertColors")) ? "slider-nav-dark" : string.Empty; 191 string navigationSlideEntirePage = (Model.Item.GetBoolean("NavigationSlideEntirePage")) ? "slider-nav-page" : string.Empty; 192 string navigationNoLoop = (Model.Item.GetBoolean("NavigationNoLoop")) ? "slider-nav-noloop" : string.Empty; 193 string indicatorsOutsideSlider = (Model.Item.GetBoolean("IndicatorsOutsideSlider") && indicatorStyle != string.Empty) ? "slider-indicators-outside" : string.Empty; 194 string indicatorsHighlightActive = (Model.Item.GetBoolean("IndicatorsHighlightActive")) ? "slider-indicators-highlight" : string.Empty; 195 string indicatorsInvertColors = (Model.Item.GetBoolean("IndicatorsInvertedColors")) ? "slider-indicators-dark" : string.Empty; 196 string indicatorsVisibleOnSmallDevices = (Model.Item.GetBoolean("IndicatorsVisibleOnSmallDevices")) ? "slider-indicators-sm" : string.Empty; 197 198 bool productsFound = true; 199 if (string.IsNullOrEmpty(groupIds) && string.IsNullOrEmpty(productIds) && string.IsNullOrEmpty(productVariantIds)) 200 { 201 if (Pageview.IsVisualEditorMode) 202 { 203 productIds = product.Id; 204 sourceType = "selected"; 205 } 206 else 207 { 208 productsFound = false; 209 } 210 } 211 } 212 213 @*Container element for the request*@ 214 @if (productsFound) 215 { 216 <form method="post" action="@url" id="RelatedProductsForm_@Model.ID" data-response-target-element="RelatedProducts_@Model.ID" data-preloader="inline" data-update-url="false" class="item_@Model.Item.SystemName.ToLower()"> 217 <input type="hidden" name="ModelID" value="@Model.ID"> 218 <input type="hidden" name="SourceType" value="@sourceType"> 219 220 @*--- SLIDER SETTINGS ---*@ 221 <input type="hidden" name="NavigationStyle" value="@navigationStyle"> 222 <input type="hidden" name="NavigationPlacement" value="@navigationPlacement"> 223 <input type="hidden" name="IndicatorStyle" value="@indicatorStyle"> 224 <input type="hidden" name="RevealSlides" value="@revealSlides"> 225 <input type="hidden" name="NavigationAlwaysVisible" value="@(navigationAlwaysVisible)"> 226 <input type="hidden" name="NavigationVisibleOnTouch" value="@(navigationVisibleOnTouch)"> 227 <input type="hidden" name="NavigationShowScrollbar" value="@(navigationShowScrollbar)"> 228 <input type="hidden" name="NavigationSmall" value="@(navigationSmall)"> 229 <input type="hidden" name="NavigationInvertColors" value="@(navigationInvertColors)"> 230 <input type="hidden" name="NavigationNoLoop" value="@(navigationNoLoop)"> 231 <input type="hidden" name="NavigationSlideEntirePage" value="@(navigationSlideEntirePage)"> 232 <input type="hidden" name="IndicatorsOutsideSlider" value="@(indicatorsOutsideSlider)"> 233 <input type="hidden" name="IndicatorsHighlightActive" value="@(indicatorsHighlightActive)"> 234 <input type="hidden" name="IndicatorsInvertColors" value="@(indicatorsInvertColors)"> 235 <input type="hidden" name="IndicatorsVisibleOnSmallDevices" value="@(indicatorsVisibleOnSmallDevices)"> 236 237 @*--- VARIANTS ---*@ 238 @if (sourceType == "variants") 239 { 240 <input type="hidden" name="isVariant" value="true"> 241 <input type="hidden" name="MainProductID" id="MainProductID_@Model.ID" value="@productIds"> 242 } 243 244 @*--- MOST SOLD ---*@ 245 @if (sourceType == "most-sold") 246 { 247 <input type="hidden" name="SortBy" value="OrderCount"> 248 if (groupIds != "") 249 { 250 <input type="hidden" name="GroupId" value="@groupIds"> 251 } 252 } 253 254 @*--- TRENDING ---*@ 255 @if (sourceType == "trending") 256 { 257 <input type="hidden" name="SortBy" value="OrderCountGrowth"> 258 if (groupIds != "") 259 { 260 <input type="hidden" name="GroupId" value="@groupIds"> 261 } 262 } 263 264 @*--- FREQUENTLY BOUGHT ---*@ 265 @if (sourceType == "frequently" && !string.IsNullOrEmpty(productIds)) 266 { 267 <input type="hidden" name="BoughtWithProductIds" value="[@productIds]"> 268 } 269 @if (sourceType != "frequently" && hasVariants) 270 { 271 <input type="hidden" name="ProductVariantId" value="@productVariantIds"> 272 } 273 274 @*--- LATEST ---*@ 275 @if (sourceType == "latest") 276 { 277 <input type="hidden" name="SortBy" value="Created"> 278 <input type="hidden" name="GroupId" value="@groupIds"> 279 } 280 281 @*--- SELECTED PRODUCTS ---*@ 282 @if (sourceType == "selected" && !string.IsNullOrEmpty(productIds) && !hasVariants) 283 { 284 <input type="hidden" name="MainProductId" id="MainProductID_@Model.ID" value="@productIds"> 285 } 286 @if (sourceType == "selected" && hasVariants) 287 { 288 <input type="hidden" name="ProductVariantId" value="@productVariantIds"> 289 } 290 291 @*--- RELATED PRODUCTS ---*@ 292 @if (sourceType == "related-products") 293 { 294 <input type="hidden" name="ProductVariantId" id="MainProductID_@Model.ID" value="@productVariantIds"> 295 } 296 297 @* General parameters *@ 298 <input type="hidden" name="Link" value="@link"> 299 <input type="hidden" name="HideTitle" value="@Model.Item.GetString("HideTitle")"> 300 301 @if (Model.Item.GetInt32("ProductsCount") != 0) 302 { 303 <input type="hidden" name="PageSize" value="@Model.Item.GetInt32("ProductsCount")"> 304 } 305 <input type="hidden" name="HeadingTitle" id="RelatedProductsTitle_@Model.ID" value="@title"> 306 @if (!string.IsNullOrEmpty(Model.Item.GetString("Subtitle"))) 307 { 308 <input type="hidden" name="Subtitle" value="@Model.Item.GetString("Subtitle")"> 309 } 310 @if (!string.IsNullOrEmpty(Model.Item.GetString("LinkText"))) 311 { 312 <input type="hidden" name="LinkText" value="@Model.Item.GetString("LinkText")"> 313 } 314 @if (!string.IsNullOrEmpty(Model.Item.GetString("ImageAspectRatio"))) 315 { 316 string ratio = Model.Item.GetRawValueString("ImageAspectRatio", ""); 317 ratio = ratio != "0" ? ratio : ""; 318 <input type="hidden" name="ImageAspectRatio" value="@ratio"> 319 } 320 @if (!string.IsNullOrEmpty(Model.Item.GetString("Layout"))) 321 { 322 <input type="hidden" name="Layout" value="@Model.Item.GetRawValueString("Layout")"> 323 } 324 @if (titleFontSize != "") 325 { 326 <input type="hidden" name="TitleFontSize" value="@titleFontSize"> 327 } 328 @if (subtitleFontSize != "") 329 { 330 <input type="hidden" name="SubtitleFontSize" value="@subtitleFontSize"> 331 } 332 @if (buttonStyle != "") 333 { 334 <input type="hidden" name="ButtonStyle" value="@buttonStyle"> 335 } 336 @if (generalTheme != "") 337 { 338 <input type="hidden" name="GeneralTheme" value="@generalTheme"> 339 } 340 @if (theme != "") 341 { 342 <input type="hidden" name="Theme" value="@theme"> 343 } 344 @if (imageTheme != "") 345 { 346 <input type="hidden" name="ImageTheme" value="@imageTheme"> 347 } 348 @if (!string.IsNullOrEmpty(Model.Item.GetString("ContentPadding"))) 349 { 350 string contentPadding = Model.Item.GetRawValueString("ContentPadding"); 351 <input type="hidden" name="ContentPadding" value="@contentPadding"> 352 } 353 <input type="hidden" name="TextReadability" value="@maxWidth"> 354 <input type="hidden" name="ParentColumnSize" id="ParentColumnSize_@Model.ID" value="12"> 355 356 <input type="hidden" name="SaleBadgeType" value="@Model.Item.GetRawValue("SaleBadgeType")"> 357 <input type="hidden" name="SaleBadgeCssClassName" value="@Model.Item.GetRawValue("SaleBadgeDesign")"> 358 <input type="hidden" name="NewBadgeCssClassName" value="@Model.Item.GetRawValue("NewBadgeDesign")"> 359 <input type="hidden" name="NewPublicationDays" value="@Model.Item.GetInt32("NewPublicationDays")"> 360 361 @if (campaignValues != "") 362 { 363 <input type="hidden" name="CampaignBadgesValues" value="@campaignValues"> 364 } 365 </form> 366 367 <script type="module" src="/Files/Templates/Designs/Swift/Assets/js/swiffy-slider.js"></script> 368 <script type="module"> 369 swift.AssetLoader.Load('/Files/Templates/Designs/Swift/Assets/css/swiffy-slider.min.css', 'css'); 370 </script> 371 372 if (Pageview.IsVisualEditorMode) 373 { 374 <div class="alert alert-info" role="alert"> 375 <span>@Translate("Product slider: Edit this column to configure")</span> 376 </div> 377 } 378 379 if (sourceType != "related-products") 380 { 381 <div class="w-100 h-100"> 382 <div id="@Model.ID" class="user-select-none" style="scroll-margin-top:var(--header-height,150px)"></div> 383 <div id="RelatedProducts_@Model.ID" class="h-100 swift_product_slider_container"></div> 384 </div> 385 } 386 else if (product?.RelatedGroups != null) 387 { 388 @* Create multiple slider containers, if type is Product relation *@ 389 <div class="grid w-100 h-100@(generalTheme)" style="grid-row-gap: 4rem"> 390 <div id="@Model.ID" class="user-select-none" style="scroll-margin-top:var(--header-height,150px)"></div> 391 @foreach (var group in product.RelatedGroups) 392 { 393 <div id="RelatedProducts_@(Model.ID)_@group.Id" class="g-col-12 h-100 swift_product_slider_container"></div> 394 } 395 </div> 396 } 397 398 @* Initialize *@ 399 if (sourceType != "related-products") 400 { 401 <script type="module"> 402 if (document.querySelector("#RelatedProducts_@Model.ID").closest("[data-col-size]")) { 403 document.querySelector("#ParentColumnSize_@Model.ID").value = document.querySelector("#RelatedProducts_@Model.ID").closest("[data-col-size]").getAttribute("data-col-size"); 404 } 405 swift.PageUpdater.Update(document.querySelector("#RelatedProductsForm_@Model.ID")).then(function () { 406 setTimeout(function() { 407 const isVisualEditor = @(Converter.ToString(Pageview.IsVisualEditorMode).ToLowerInvariant()); 408 const productSliderContainer = document.querySelector(".swift_product_slider_container"); 409 410 if (productSliderContainer && productSliderContainer.innerHTML !== "") { 411 productSliderContainer.classList.remove("d-none"); 412 } 413 else if (!isVisualEditor) { 414 productSliderContainer.closest("[class*=column]").classList.add("d-none"); 415 } 416 }, 150); 417 }); 418 </script> 419 } 420 else if (product?.RelatedGroups != null) 421 { 422 @* Create multiple sliders, if type is Product relation *@ 423 foreach (var group in product.RelatedGroups) 424 { 425 IList<string> fromProductIds = new List<string> { }; 426 427 foreach (var relatedProduct in group.Products) 428 { 429 if (!string.IsNullOrEmpty(relatedProduct.VariantId)) 430 { 431 fromProductIds.Add($"{relatedProduct.ProductId} {relatedProduct.VariantId}"); 432 } 433 else 434 { 435 fromProductIds.Add($"{relatedProduct.ProductId}"); 436 } 437 } 438 <script type="module"> 439 document.querySelector("#ParentColumnSize_@Model.ID").value = document.querySelector("#RelatedProducts_@(Model.ID)_@group.Id").closest("[data-col-size]").getAttribute("data-col-size"); 440 document.querySelector("#MainProductID_@Model.ID").value = "@string.Join(",", fromProductIds)"; 441 document.querySelector("#RelatedProductsTitle_@Model.ID").value = "@group.Name"; 442 document.querySelector("#RelatedProductsForm_@Model.ID").setAttribute("data-response-target-element", "RelatedProducts_@(Model.ID)_@group.Id"); 443 444 swift.PageUpdater.Update(document.querySelector("#RelatedProductsForm_@Model.ID")); 445 </script> 446 } 447 } 448 } 449
Sorry. There is nothing to view here