New 15km bike park in the heart of Pines forrest
This is a legitimate expert-level trail, but much of the difficulty can be mitigated by slowing down and picking your line carefully.
Error executing template "Designs/Swift-v2/eCom/ProductCatalog/ProductViewDetail.cshtml" System.NullReferenceException: Object reference not set to an instance of an object. at CompiledRazorTemplates.Dynamic.RazorEngine_7f4e99bcfe7d471daa1b4a1a0cdf3787.ExecuteAsync() at RazorEngine.Templating.TemplateBase.Run(ExecuteContext context, TextWriter reader) at RazorEngine.Templating.RazorEngineCore.RunTemplate(ICompiledTemplate template, TextWriter writer, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineService.Run(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.DynamicWrapperService.Run(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineServiceExtensions.Run(IRazorEngineService service, String name, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass23_0.<Run>b__0(TextWriter writer) at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter) at RazorEngine.Templating.RazorEngineServiceExtensions.Run(IRazorEngineService service, String name, Type modelType, Object model, DynamicViewBag viewBag) at Dynamicweb.Rendering.RazorTemplateRenderingProvider.Render(Template template) at Dynamicweb.Rendering.TemplateRenderingService.Render(Template template) at Dynamicweb.Rendering.Template.RenderRazorTemplate()
1 @inherits ViewModelTemplate<ProductViewModel> 2 @using Dynamicweb.Rendering 3 @using Dynamicweb.Ecommerce.ProductCatalog 4 @using Dynamicweb.Core 5 6 @{ 7 string metaDescription = string.IsNullOrEmpty(Model.MetaDescription) ? Model.Name : Model.MetaDescription; 8 9 Pageview.Meta.AddTag($"<meta property=\"og:image\" content=\"{Dynamicweb.Context.Current.Request.Url.Scheme}://{Dynamicweb.Context.Current.Request.Url.Host}{Model.DefaultImage.Value}\">"); 10 Pageview.Meta.AddTag($"<meta property=\"og:image:alt\" content=\"{Model.Name}\">"); 11 Pageview.Meta.AddTag($"<meta property=\"og:description\" content=\"{metaDescription}\">"); 12 13 Pageview.Meta.AddTag("twitter:image", Model.DefaultImage.Value); 14 Pageview.Meta.AddTag("twitter:image:alt", Model.Name); 15 Pageview.Meta.AddTag("twitter:description", metaDescription); 16 } 17 18 @{ 19 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails")) 20 { 21 Dynamicweb.Context.Current.Items["ProductDetails"] = Model; 22 } 23 else 24 { 25 Dynamicweb.Context.Current.Items.Add("ProductDetails", Model); 26 } 27 28 bool isLazyLoadingForProductInfoEnabled = Dynamicweb.Core.Converter.ToBoolean(Dynamicweb.Context.Current.Items["IsLazyLoadingForProductInfoEnabled"]); 29 if (isLazyLoadingForProductInfoEnabled) 30 { 31 string showPricesWithVat = Pageview.Area.EcomPricesWithVat.ToLower(); 32 bool neverShowVat = string.IsNullOrEmpty(showPricesWithVat); 33 bool hasVariantId = !string.IsNullOrEmpty(Model.VariantId); 34 string variantIdParam = hasVariantId ? $"/{Model.VariantId}" : ""; 35 string priceFilledProperties = $"Price,PriceFormatted{(showPricesWithVat == "false" && !neverShowVat ? ",PriceWithVat,PriceWithVatFormatted" : "")}"; 36 string productInfoFeed = $@"/dwapi/ecommerce/products/{Model.Id}{variantIdParam} 37 ?UserId={Converter.ToString(Pageview.User?.ID)} 38 &LanguageId={Pageview.Area.EcomLanguageId}&CurrencyCode={Pageview.Area.EcomCurrencyId}&CountryCode={Pageview.Area.EcomCountryCode}&ShopId={Pageview.Area.EcomShopId} 39 &FilledProperties=Id,Price,PriceBeforeDiscount,StockLevel,VariantInfo,NeverOutOfstock,Prices 40 &PriceSettings.ShowPricesWithVat={Pageview.Area.EcomPricesWithVat} 41 &PriceSettings.FilledProperties={priceFilledProperties} 42 &getproductinfo=true"; 43 Dynamicweb.Context.Current.Items["ProductInfoFeed"] = productInfoFeed; 44 45 <script type="module"> 46 swift.LiveProductInfo.init(); 47 </script> 48 } 49 } 50 51 <script> 52 gtag("event", "view_item", { 53 currency: "@Model.Price.CurrencyCode", 54 value: @Model.Price.ToStringInvariant(), 55 items: [ 56 { 57 item_id: "@Model.Number", 58 item_name: "@Dynamicweb.Core.Encoders.HtmlEncoder.JavaScriptStringEncode(Model.Name)", 59 currency: "@Model.Price.CurrencyCode", 60 price: @Model.Price.ToStringInvariant(), 61 discount: @Model.Discount.ToStringInvariant() 62 } 63 ] 64 }); 65 </script> 66 67 <script> 68 window.addEventListener('load', function (event) { 69 swift.Video.init(); 70 }); 71 </script> 72
Error executing template "Designs/Swift-v2/Paragraph/Swift-v2_ProductDetailsImage.cshtml" System.ArgumentNullException: Value cannot be null. (Parameter 'source') at System.Linq.ThrowHelper.ThrowArgumentNullException(ExceptionArgument argument) at System.Linq.Enumerable.Where[TSource](IEnumerable`1 source, Func`2 predicate) at CompiledRazorTemplates.Dynamic.RazorEngine_5026482a799c443aaf15ad0b869cbc1c.ExecuteAsync() at RazorEngine.Templating.TemplateBase.Run(ExecuteContext context, TextWriter reader) at RazorEngine.Templating.RazorEngineCore.RunTemplate(ICompiledTemplate template, TextWriter writer, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineService.Run(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.DynamicWrapperService.Run(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineServiceExtensions.Run(IRazorEngineService service, String name, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass23_0.<Run>b__0(TextWriter writer) at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter) at RazorEngine.Templating.RazorEngineServiceExtensions.Run(IRazorEngineService service, String name, Type modelType, Object model, DynamicViewBag viewBag) 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 @using System.Text.RegularExpressions; 6 7 @functions { 8 public ProductViewModel product { get; set; } = new ProductViewModel(); 9 public string galleryLayout { get; set; } 10 public string[] supportedImageFormats { get; set; } 11 public string[] supportedVideoFormats { get; set; } 12 public string[] supportedDocumentFormats { get; set; } 13 public string[] allSupportedFormats { get; set; } 14 15 public class RatioSettings 16 { 17 public string Ratio { get; set; } 18 public string CssClass { get; set; } 19 public string CssVariable { get; set; } 20 public string Fill { get; set; } 21 } 22 23 public RatioSettings GetRatioSettings(string size = "desktop") 24 { 25 var ratioSettings = new RatioSettings(); 26 27 string ratio = Model.Item.GetRawValueString("ImageAspectRatio", ""); 28 ratio = ratio != "0" ? ratio : ""; 29 string cssClass = ratio != "" && ratio != "fill" ? " ratio" : ""; 30 string cssVariable = ratio != "" && ratio != "fill" ? "--bs-aspect-ratio: " + ratio : ""; 31 cssClass = ratio == "fill" && size == "mobile" ? " ratio" : cssClass; 32 cssVariable = ratio == "fill" && size == "mobile" ? "--bs-aspect-ratio: 66%" : cssVariable; 33 34 ratioSettings.Ratio = ratio; 35 ratioSettings.CssClass = cssClass; 36 ratioSettings.CssVariable = cssVariable; 37 ratioSettings.Fill = ratio == "fill" ? " h-100" : ""; 38 39 return ratioSettings; 40 } 41 42 public string GetArrowsColor() 43 { 44 var invertColor = Model.Item.GetBoolean("InvertModalArrowsColor"); 45 var arrowsColor = invertColor ? " carousel-dark" : string.Empty; 46 return arrowsColor; 47 } 48 49 public string GetThumbnailPlacement() 50 { 51 return Model.Item.GetRawValueString("ThumbnailPlacement", "bottom"); 52 } 53 54 public string GetThumbnailRowSettingCss() 55 { 56 switch (GetThumbnailPlacement()) 57 { 58 case "bottom": 59 return "d-flex flex-wrap"; 60 case "left": 61 return "d-flex flex-column order-first"; 62 case "right": 63 return "d-flex flex-column order-last"; 64 default: 65 return "d-flex flex-wrap"; 66 } 67 } 68 69 public Dictionary<string, object> GetVideoParams(MediaViewModel asset, string size) 70 { 71 string assetName = !string.IsNullOrEmpty(asset.DisplayName) ? asset.DisplayName : asset.Name; 72 string type = GetVideoType(asset.Value); 73 bool openInModal = Model.Item.GetString("OpenVideoInModal") == "true" ? true : false; 74 bool autoPlay = Model.Item.GetBoolean("VideoAutoPlay"); 75 76 var videoParams = new Dictionary<string, object>(); 77 videoParams.Add("AssetName", asset.Name); 78 videoParams.Add("AssetVideoType", type); 79 videoParams.Add("AssetDisplayName", asset.DisplayName); 80 videoParams.Add("OpenVideoInModal", openInModal); 81 videoParams.Add("VideoAutoPlay", autoPlay); 82 videoParams.Add("Size", size); 83 videoParams.Add("Id", Model.ID); 84 return videoParams; 85 86 } 87 88 public string GetVideoType(string assetValue) 89 { 90 string type = assetValue.IndexOf("youtu.be", StringComparison.OrdinalIgnoreCase) >= 0 || assetValue.IndexOf("youtube", StringComparison.OrdinalIgnoreCase) >= 0 ? "youtube" : string.Empty; 91 type = assetValue.IndexOf("vimeo", StringComparison.OrdinalIgnoreCase) >= 0 ? "vimeo" : type; 92 type = string.IsNullOrEmpty(type) ? "selfhosted" : type; 93 94 return type; 95 } 96 97 public string GetYoutubeScreenDump(string assetValue, string quality) 98 { 99 var regex = new Regex(@"(?:youtube\.com\/.*[\?&]v=|youtu\.be\/|youtube\.com\/embed\/)([\w-]+)(?:\?.*)?"); 100 Match match = regex.Match(assetValue); 101 string videoId = match.Success ? match.Groups[1].Value : string.Empty; 102 string youtubeThumbnail = $"https://img.youtube.com/vi/{videoId}/{quality}.jpg"; 103 return youtubeThumbnail; 104 } 105 } 106 107 @{ 108 ProductViewModel product = null; 109 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails")) 110 { 111 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"]; 112 } 113 else if (Pageview.Page.Item["DummyProduct"] != null && Pageview.IsVisualEditorMode) 114 { 115 var pageViewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(Pageview.Page); 116 ProductListViewModel productList = pageViewModel.Item.GetValue("DummyProduct") != null ? pageViewModel.Item.GetValue("DummyProduct") as ProductListViewModel : new ProductListViewModel(); 117 118 if (productList?.Products is object) 119 { 120 product = productList.Products[0]; 121 } 122 } 123 } 124 125 @if (product is object) 126 { 127 @* Supported formats *@ 128 supportedImageFormats = new string[] { ".jpg", ".jpeg", ".webp", ".png", ".gif", ".bmp", ".tiff" }; 129 supportedVideoFormats = new string[] { "youtu.be", "youtube", "vimeo", ".mp4", ".webm" }; 130 supportedDocumentFormats = new string[] { ".pdf", ".docx", ".xlsx", ".ppt", "pptx" }; 131 allSupportedFormats = supportedImageFormats.Concat(supportedVideoFormats).Concat(supportedDocumentFormats).ToArray(); 132 133 @* Collect the assets *@ 134 var selectedAssetCategories = Model.Item.GetList("ImageAssets")?.GetRawValue().OfType<string>(); 135 bool includeImagePatternImages = Model.Item.GetBoolean("ImagePatternImages"); 136 137 @* Needed image data collection to support both DefaultImage, ImagePatterns and Image Assets *@ 138 string defaultImage = product.DefaultImage != null ? product.DefaultImage.Value : ""; 139 IEnumerable<MediaViewModel> assetsImages = product.AssetCategories.Where(x => selectedAssetCategories.Contains(x.SystemName)).SelectMany(x => x.Assets); 140 assetsImages = assetsImages.OrderByDescending(x => x.Value.Equals(defaultImage)); 141 IEnumerable<MediaViewModel> assetsList = new MediaViewModel[] { }; 142 assetsList = assetsList.Union(assetsImages); 143 assetsList = includeImagePatternImages ? assetsList.Union(product.ImagePatternImages) : assetsList; 144 assetsList = includeImagePatternImages && assetsList.Count() == 0 ? assetsList.Append(product.DefaultImage) : assetsList; 145 146 bool defaultImageFallback = Model.Item.GetBoolean("DefaultImageFallback"); 147 bool showOnlyPrimaryImage = Model.Item.GetBoolean("ShowOnlyPrimaryImage"); 148 149 int totalAssets = 0; 150 if (showOnlyPrimaryImage == false) 151 { 152 foreach (MediaViewModel asset in assetsList) 153 { 154 var assetValue = asset.Value; 155 foreach (string format in allSupportedFormats) 156 { 157 if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) 158 { 159 totalAssets++; 160 } 161 } 162 } 163 } 164 165 if ((totalAssets == 0 && product.DefaultImage != null && selectedAssetCategories.Count() == 0) || (showOnlyPrimaryImage == true && product.DefaultImage != null) || totalAssets == 0 && defaultImageFallback) 166 { 167 assetsList = new List<MediaViewModel>() { product.DefaultImage }; 168 totalAssets = 1; 169 } 170 171 @* Get assets from selected categories or get all assets *@ 172 if (totalAssets != 0) 173 { 174 int assetNumber = 0; 175 int thumbnailNumber = 0; 176 int modalAssetNumber = 0; 177 string thumbnailAxisCss = GetThumbnailPlacement() == "bottom" ? "flex-column" : string.Empty; 178 179 <div class="d-flex gap-3 h-100 @(thumbnailAxisCss) item_@Model.Item.SystemName.ToLower()" data-dw-colorscheme="@Model.ColorScheme?.Id"> 180 <div id="SmallScreenImages_@Model.ID" class="carousel@(GetArrowsColor()) col position-relative" data-bs-ride="carousel"> 181 <div class="carousel-inner h-100"> 182 @foreach (MediaViewModel asset in assetsList) 183 { 184 var assetValue = asset.Value; 185 foreach (string format in allSupportedFormats) 186 { 187 if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) 188 { 189 string activeSlide = assetNumber == 0 ? "active" : ""; 190 191 <div class="carousel-item @activeSlide" data-bs-interval="99999"> 192 @{ 193 string size = "mobile"; 194 195 <div class="h-100"> 196 @foreach (string imageFormat in supportedImageFormats) 197 { //Images 198 if (assetValue.IndexOf(imageFormat, StringComparison.OrdinalIgnoreCase) >= 0) 199 { 200 if (product is object) 201 { 202 string productName = product.Name; 203 string imagePath = !string.IsNullOrEmpty(asset.Value) ? asset.Value : product.DefaultImage.Value; 204 205 RatioSettings ratioSettings = GetRatioSettings(size); 206 207 var parms = new Dictionary<string, object>(); 208 parms.Add("alt", productName + asset.Keywords); 209 parms.Add("itemprop", "image"); 210 parms.Add("columns", Model.GridRowColumnCount); 211 parms.Add("eagerLoadNewImages", Model.Item.GetBoolean("DisableLazyLoading")); 212 parms.Add("doNotUseGetimage", Model.Item.GetBoolean("DisableGetImage")); 213 if (!string.IsNullOrEmpty(asset.DisplayName)) 214 { 215 parms.Add("title", asset.DisplayName); 216 } 217 218 if (ratioSettings.Ratio == "fill" && galleryLayout != "grid") 219 { 220 parms.Add("cssClass", "w-100 h-100 image-zoom-lg-l-hover"); 221 } 222 else 223 { 224 parms.Add("cssClass", "mw-100 mh-100"); 225 } 226 227 <a href="@imagePath" class="d-block @(ratioSettings.CssClass)@(ratioSettings.Fill)" style="@(ratioSettings.CssVariable)" data-bs-toggle="modal" data-bs-target="#modal_@Model.ID"> 228 <div class="d-flex align-items-center justify-content-center overflow-hidden h-100" data-bs-target="#ModalCarousel_@Model.ID" data-bs-slide-to="@assetNumber"> 229 @RenderPartial("Components/Image.cshtml", new FileViewModel { Path = imagePath }, parms) 230 </div> 231 </a> 232 } 233 } 234 } 235 @foreach (string videoFormat in supportedVideoFormats) 236 { //Videos 237 if (assetValue.IndexOf(videoFormat, StringComparison.OrdinalIgnoreCase) >= 0) 238 { 239 if (Model.Item.GetString("OpenVideoInModal") == "true") 240 { 241 if (product is object) 242 { 243 string iconPath = "/Files/Templates/Designs/Swift-v2/Assets/icons/"; 244 245 string productName = product.Name; 246 productName += !string.IsNullOrEmpty(asset.Keywords) ? " " + asset.Keywords : ""; 247 string assetTitle = !string.IsNullOrEmpty(asset.DisplayName) ? "title=\"" + asset.DisplayName + "\"" : ""; 248 249 RatioSettings ratioSettings = GetRatioSettings(size); 250 251 string type = GetVideoType(asset.Value); 252 253 string videoScreendumpPath = type == "youtube" ? GetYoutubeScreenDump(asset.Value, "maxresdefault") : string.Empty; 254 videoScreendumpPath = type == "selfhosted" ? asset.Value : videoScreendumpPath; 255 string videoJsClass = type == "vimeo" ? "js-vimeo-video-thumbnail" : ""; 256 257 258 <div class="d-block @(ratioSettings.CssClass)@(ratioSettings.Fill)" style="@(ratioSettings.CssVariable); cursor: pointer" data-bs-toggle="modal" data-bs-target="#modal_@Model.ID"> 259 <div class="d-flex align-items-center justify-content-center overflow-hidden h-100" data-bs-target="#ModalCarousel_@Model.ID" data-bs-slide-to="@assetNumber"> 260 <div class="icon-5 position-absolute" style="z-index: 1">@ReadFile(iconPath + "play-circle.svg")</div> 261 @if (type != "selfhosted") 262 { 263 <img src="@videoScreendumpPath" loading="lazy" decoding="async" alt="@productName" @assetTitle class="@videoJsClass mw-100 mh-100" data-asset-value="@asset.Value" style="object-fit: cover;"> 264 } 265 else 266 { 267 string videoType = Path.GetExtension(asset.Value).ToLower(); 268 269 <video preload="auto" class="h-100 w-100" style="object-fit: contain;"> 270 <source src="@(videoScreendumpPath)#t=0.001" type="video/@videoType.Replace(".", "")"> 271 </video> 272 } 273 </div> 274 </div> 275 276 } 277 } 278 else 279 { 280 if (product is object) 281 { 282 var videoParams = GetVideoParams(asset, size); 283 @RenderPartial("Components/VideoPlayer.cshtml", new FileViewModel { Path = asset.Value}, videoParams); 284 285 } 286 } 287 } 288 } 289 @foreach (string documentFormat in supportedDocumentFormats) 290 { //Documents 291 if (assetValue.IndexOf(documentFormat, StringComparison.OrdinalIgnoreCase) >= 0) 292 { 293 if (product is object) 294 { 295 string iconPath = "/Files/Templates/Designs/Swift-v2/Assets/icons/"; 296 297 string productName = product.Name; 298 string imagePath = !string.IsNullOrEmpty(asset.Value) ? asset.Value : product.DefaultImage.Value; 299 300 RatioSettings ratioSettings = GetRatioSettings(size); 301 302 var parms = new Dictionary<string, object>(); 303 parms.Add("alt", productName + asset.Keywords); 304 parms.Add("itemprop", "image"); 305 parms.Add("fullwidth", true); 306 parms.Add("columns", Model.GridRowColumnCount); 307 if (!string.IsNullOrEmpty(asset.DisplayName)) 308 { 309 parms.Add("title", asset.DisplayName); 310 } 311 312 if (ratioSettings.Ratio == "fill" && galleryLayout != "grid") 313 { 314 parms.Add("cssClass", "w-100 h-100 image-zoom-lg-l-hover"); 315 } 316 else 317 { 318 parms.Add("cssClass", "mw-100 mh-100"); 319 } 320 321 <a href="@imagePath" class="d-block @(ratioSettings.CssClass)@(ratioSettings.Fill)" style="@(ratioSettings.CssVariable)" download alt="@Translate("Download")"> 322 <div class="d-flex align-items-center justify-content-center text-center overflow-hidden h-100 border"> 323 <div class="icon-5 position-absolute" style="z-index: 1">@ReadFile(iconPath + "download.svg")</div> 324 <span>@Translate("Download") @(asset.Name)@Path.GetExtension(asset.Value).ToLower()</span> 325 </div> 326 </a> 327 } 328 329 } 330 } 331 </div> 332 } 333 334 335 </div> 336 assetNumber++; 337 } 338 } 339 } 340 </div> 341 342 </div> 343 344 @if (totalAssets > 1) 345 { 346 <div class="@(GetThumbnailRowSettingCss()) gap-3" id="SmallScreenImagesThumbnails_@Model.ID"> 347 @foreach (MediaViewModel asset in assetsList) 348 { 349 var assetValue = asset.Value; 350 string assetName = asset.Name; 351 assetName += !string.IsNullOrEmpty(asset.Keywords) ? " " + asset.Keywords : ""; 352 string assetTitle = !string.IsNullOrEmpty(asset.DisplayName) ? asset.DisplayName : null; 353 string iconPath = "/Files/Templates/Designs/Swift-v2/Assets/icons/"; 354 355 string imagePath = assetValue; 356 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; 357 string imagePathThumb = assetValue.StartsWith("/Files/", StringComparison.OrdinalIgnoreCase) ? imagePath.IndexOf("youtube", StringComparison.OrdinalIgnoreCase) < 0 && imagePath.IndexOf(".mp4", StringComparison.OrdinalIgnoreCase) < 0 ? $"/Admin/Public/GetImage.ashx?image={imagePath}&width=180&format=webp" : imagePath : assetValue; 358 359 RatioSettings ratioSettings = GetRatioSettings("desktop"); 360 361 <div class="border outline-none @(ratioSettings.CssClass)" style="@(ratioSettings.CssVariable); cursor: pointer; min-width: 7rem; max-width: 8rem;" data-bs-target="#SmallScreenImages_@Model.ID" data-bs-slide-to="@thumbnailNumber"> 362 @foreach (string imageFormat in supportedImageFormats) 363 { //Images 364 if (assetValue.IndexOf(imageFormat, StringComparison.OrdinalIgnoreCase) >= 0) 365 { 366 <img src="@imagePathThumb" alt="@assetName" @assetTitle class="p-0 p-lg-1 w-100 h-100" style="object-fit: contain;"> 367 368 thumbnailNumber++; 369 } 370 } 371 372 @foreach (string videoFormat in supportedVideoFormats) 373 { //Images 374 if (assetValue.IndexOf(videoFormat, StringComparison.OrdinalIgnoreCase) >= 0) 375 { 376 377 string type = GetVideoType(asset.Value); 378 379 string videoScreendumpPath = type == "youtube" ? GetYoutubeScreenDump(asset.Value, "mqdefault") : ""; 380 videoScreendumpPath = type == "vimeo" ? string.Empty : videoScreendumpPath; 381 videoScreendumpPath = type == "selfhosted" ? asset.Value : videoScreendumpPath; 382 string videoJsClass = type == "vimeo" ? "js-vimeo-video-thumbnail" : string.Empty; 383 384 <div class="icon-5 position-absolute" style="z-index: 1">@ReadFile(iconPath + "play-circle.svg")</div> 385 386 if (type != "selfhosted") 387 { 388 <img src="@videoScreendumpPath" loading="lazy" decoding="async" alt="@assetTitle" @assetTitle class="@videoJsClass mw-100 mh-100" data-asset-value="@asset.Value" style="object-fit: cover;" /> 389 } 390 else 391 { 392 string videoType = Path.GetExtension(asset.Value).ToLower(); 393 394 <video preload="auto" class="h-100 w-100" style="object-fit: contain;"> 395 <source src="@(videoScreendumpPath)#t=0.001" type="video/@videoType.Replace(".", "")"> 396 </video> 397 } 398 399 thumbnailNumber++; 400 } 401 } 402 403 @foreach (string documentFormat in supportedDocumentFormats) 404 { //Documents 405 if (assetValue.IndexOf(documentFormat, StringComparison.OrdinalIgnoreCase) >= 0) 406 { 407 <a href="@assetValue" class="ratio ratio-4x3 border outline-none" style="cursor: pointer; min-width: 7rem; max-width: 8rem;" download title="@asset.Value"> 408 <div class="d-flex align-items-center justify-content-center text-center overflow-hidden h-100 border"> 409 <div class="icon-5 position-absolute" style="z-index: 1">@ReadFile(iconPath + "download.svg")</div> 410 <span>@(asset.Name)@Path.GetExtension(asset.Value).ToLower()</span> 411 </div> 412 </a> 413 414 thumbnailNumber++; 415 } 416 } 417 </div> 418 } 419 </div> 420 } 421 </div> 422 423 @* Modal with slides *@ 424 <div class="modal fade swift_products-details-images-modal" id="modal_@Model.ID" tabindex="-1" aria-labelledby="productDetailsGalleryModalTitle_@Model.ID" aria-hidden="true"> 425 <div class="modal-dialog modal-dialog-centered modal-xl"> 426 <div class="modal-content"> 427 <div class="modal-header visually-hidden"> 428 <h5 class="modal-title" id="productDetailsGalleryModalTitle_@Model.ID">@product.Title</h5> 429 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> 430 </div> 431 <div class="modal-body p-2 p-lg-3 h-100"> 432 <div id="ModalCarousel_@Model.ID" class="carousel@(GetArrowsColor()) h-100" data-bs-ride="carousel"> 433 <div class="carousel-inner h-100" data-dw-colorscheme="@Model.ColorScheme?.Id"> 434 @foreach (MediaViewModel asset in assetsList) 435 { 436 var assetValue = !string.IsNullOrEmpty(asset.Value) ? asset.Value : product.DefaultImage.Value; 437 foreach (string supportedFormat in supportedImageFormats.Concat(supportedVideoFormats).ToArray()) 438 { 439 if (assetValue.IndexOf(supportedFormat, StringComparison.OrdinalIgnoreCase) >= 0) 440 { 441 string imagePath = assetValue; 442 string activeSlide = modalAssetNumber == 0 ? "active" : ""; 443 444 var parms = new Dictionary<string, object>(); 445 parms.Add("cssClass", "d-block mw-100 mh-100 m-auto"); 446 parms.Add("fullwidth", true); 447 parms.Add("columns", Model.GridRowColumnCount); 448 449 <div class="carousel-item @activeSlide h-100" data-bs-interval="99999"> 450 @foreach (string imageFormat in supportedImageFormats) 451 { //Images 452 if (assetValue.IndexOf(imageFormat, StringComparison.OrdinalIgnoreCase) >= 0) 453 { 454 @RenderPartial("Components/Image.cshtml", new FileViewModel { Path = imagePath }, parms) 455 } 456 } 457 458 @foreach (string videoFormat in supportedVideoFormats) 459 { //Videos 460 if (assetValue.IndexOf(videoFormat, StringComparison.OrdinalIgnoreCase) >= 0) 461 { 462 var videoParams = GetVideoParams(asset, "modal"); 463 @RenderPartial("Components/VideoPlayer.cshtml", new FileViewModel { Path = asset.Value }, videoParams) 464 } 465 } 466 </div> 467 modalAssetNumber++; 468 } 469 } 470 } 471 <button class="carousel-control-prev carousel-control-area" type="button" data-bs-target="#ModalCarousel_@Model.ID" data-bs-slide="prev"> 472 <span class="carousel-control-prev-icon" aria-hidden="true"></span> 473 <span class="visually-hidden">@Translate("Previous")</span> 474 </button> 475 <button class="carousel-control-next carousel-control-area" type="button" data-bs-target="#ModalCarousel_@Model.ID" data-bs-slide="next"> 476 <span class="carousel-control-next-icon" aria-hidden="true"></span> 477 <span class="visually-hidden">@Translate("Next")</span> 478 </button> 479 </div> 480 </div> 481 </div> 482 </div> 483 </div> 484 </div> 485 } 486 else if (Pageview.IsVisualEditorMode) 487 { 488 RatioSettings ratioSettings = GetRatioSettings("desktop"); 489 490 <div class="h-100" data-dw-colorscheme="@Model.ColorScheme?.Id"> 491 <div class="d-block @(ratioSettings.CssClass)@(ratioSettings.Fill)" style="@(ratioSettings.CssVariable)"> 492 <img src="/Files/Images/missing_image.jpg" loading="lazy" decoding="async" class="mh-100 mw-100" style="object-fit: cover;"> 493 </div> 494 </div> 495 } 496 } 497 else if (Pageview.IsVisualEditorMode) 498 { 499 <div class="alert alert-dark m-0">@Translate("The images will be shown here, if any")</div> 500 } 501 502 503 504
Error executing template "Designs/Swift-v2/Paragraph/Swift-v2_Accordion.cshtml" System.NullReferenceException: Object reference not set to an instance of an object. at CompiledRazorTemplates.Dynamic.RazorEngine_75b7ed891abb45ae976941f5ae3d2ab4.ExecuteAsync() at RazorEngine.Templating.TemplateBase.Run(ExecuteContext context, TextWriter reader) at RazorEngine.Templating.RazorEngineCore.RunTemplate(ICompiledTemplate template, TextWriter writer, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineService.Run(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.DynamicWrapperService.Run(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineServiceExtensions.Run(IRazorEngineService service, String name, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass23_0.<Run>b__0(TextWriter writer) at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter) at RazorEngine.Templating.RazorEngineServiceExtensions.Run(IRazorEngineService service, String name, Type modelType, Object model, DynamicViewBag viewBag) 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 3 @{ 4 string title = Model.Item.GetString("Title"); 5 var accordionItems = Model.Item?.GetItems("Accordion_Items") ?? Enumerable.Empty<Dynamicweb.Frontend.ItemViewModel>().ToList(); 6 } 7 8 <div class="accordion h-100 position-relative item_@Model.Item.SystemName.ToLower()" id="accordion-@Pageview.CurrentParagraph.ID"> 9 @if (!string.IsNullOrEmpty(Model.Item.GetString("Title")) && !Model.Item.GetBoolean("HideTitle")) 10 { 11 string titleFontSize = Model.Item.GetRawValueString("TitleFontSize", "h2"); 12 string headingLevel = Model.Item.GetString("HeadingLevel", "h2"); 13 string headingLevelStart = $"<{headingLevel} class=\"{titleFontSize} mb-4\">"; 14 string headingLevelStop = $"</{headingLevel}>"; 15 16 @headingLevelStart 17 @Model.Item.GetString("Title") 18 @headingLevelStop 19 } 20 @foreach (var item in accordionItems) 21 { 22 <div class="accordion-item"> 23 <h2 class="accordion-header" id="heading-@Pageview.CurrentParagraph.ID-@item.Id"> 24 <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapse-@Pageview.CurrentParagraph.ID-@item.Id" aria-expanded="false" aria-controls="collapse-@Pageview.CurrentParagraph.ID-@item.Id"> 25 @item.GetString("Title") 26 </button> 27 </h2> 28 <div id="collapse-@Pageview.CurrentParagraph.ID-@item.Id" class="accordion-collapse collapse" aria-labelledby="heading-@Pageview.CurrentParagraph.ID-@item.Id" data-bs-parent="#accordion-@Pageview.CurrentParagraph.ID"> 29 <div class="accordion-body mb-0-last-child opacity-75"> 30 @item.GetRawValueString("Content") 31 </div> 32 </div> 33 </div> 34 } 35 <div id="@Model.ID" class="user-select-none position-absolute top-0" style="scroll-margin-top:var(--header-height,150px)"></div> 36 </div> 37
Error executing template "Designs/Swift-v2/Paragraph/Swift-v2_ProductDetailsGallery.cshtml" System.ArgumentNullException: Value cannot be null. (Parameter 'source') at System.Linq.ThrowHelper.ThrowArgumentNullException(ExceptionArgument argument) at System.Linq.Enumerable.Where[TSource](IEnumerable`1 source, Func`2 predicate) at CompiledRazorTemplates.Dynamic.RazorEngine_ecfa4ff9f37a4f8bbd37abf55c3c3d72.ExecuteAsync() at RazorEngine.Templating.TemplateBase.Run(ExecuteContext context, TextWriter reader) at RazorEngine.Templating.RazorEngineCore.RunTemplate(ICompiledTemplate template, TextWriter writer, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineService.Run(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.DynamicWrapperService.Run(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineServiceExtensions.Run(IRazorEngineService service, String name, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass23_0.<Run>b__0(TextWriter writer) at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter) at RazorEngine.Templating.RazorEngineServiceExtensions.Run(IRazorEngineService service, String name, Type modelType, Object model, DynamicViewBag viewBag) 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 @using System.Text.RegularExpressions; 6 7 @functions { 8 public ProductViewModel product { get; set; } = new ProductViewModel(); 9 public string galleryLayout { get; set; } 10 public string[] supportedImageFormats { get; set; } 11 public string[] supportedVideoFormats { get; set; } 12 public string[] supportedDocumentFormats { get; set; } 13 public string[] allSupportedFormats { get; set; } 14 15 public class RatioSettings { 16 public string Ratio { get; set; } 17 public string CssClass { get; set; } 18 public string CssVariable { get; set; } 19 public string Fill { get; set; } 20 } 21 22 public RatioSettings GetRatioSettings(string size = "desktop") { 23 var ratioSettings = new RatioSettings(); 24 25 string ratio = Model.Item.GetRawValueString("ImageAspectRatio", ""); 26 ratio = ratio != "0" ? ratio : ""; 27 string cssClass = ratio != "" && ratio != "fill" ? " ratio" : ""; 28 string cssVariable = ratio != "" && ratio != "fill" ? "--bs-aspect-ratio: " + ratio : ""; 29 cssClass = ratio != "" && ratio == "fill" && size == "mobile" ? " ratio" : cssClass; 30 cssVariable = ratio != "" && ratio == "fill" && size == "mobile" ? "--bs-aspect-ratio: 66%" : cssVariable; 31 32 ratioSettings.Ratio = ratio; 33 ratioSettings.CssClass = cssClass; 34 ratioSettings.CssVariable = cssVariable; 35 ratioSettings.Fill = ratio == "fill" ? " h-100" : ""; 36 37 return ratioSettings; 38 } 39 40 public string GetColumnClass(int total, int assetNumber) { 41 string colClass = total > 1 ? "g-col-lg-6" : "g-col-12"; 42 colClass = galleryLayout == "full-first" && assetNumber == 0 ? "g-col-12" : colClass; 43 colClass = galleryLayout == "full-last" && assetNumber == (total - 1) ? "g-col-12" : colClass; 44 colClass = galleryLayout == "advanced-grid" && assetNumber > 1 ? "g-col-4" : colClass; 45 46 colClass = galleryLayout == "advanced-grid" && total == 1 ? "g-col-12" : colClass; 47 colClass = galleryLayout == "advanced-grid" && total == 3 && assetNumber == 2 ? "g-col-12" : colClass; 48 colClass = galleryLayout == "advanced-grid" && total == 4 && assetNumber == 2 ? "g-col-6" : colClass; 49 colClass = galleryLayout == "advanced-grid" && total == 4 && assetNumber == 3 ? "g-col-6" : colClass; 50 colClass = galleryLayout == "advanced-grid" && total == 6 && assetNumber == 5 ? "g-col-12" : colClass; 51 colClass = galleryLayout == "advanced-grid" && total == 7 && assetNumber == 5 ? "g-col-6" : colClass; 52 colClass = galleryLayout == "advanced-grid" && total == 7 && assetNumber == 6 ? "g-col-6" : colClass; 53 colClass = galleryLayout == "advanced-grid" && total == 9 && assetNumber == 8 ? "g-col-12" : colClass; 54 55 return colClass; 56 } 57 58 public string GetArrowsColor() 59 { 60 var invertColor = Model.Item.GetBoolean("InvertModalArrowsColor"); 61 var arrowsColor = invertColor ? " carousel-dark" : string.Empty; 62 return arrowsColor; 63 } 64 65 public Dictionary<string, object> GetVideoParams(MediaViewModel asset, string size) 66 { 67 string assetName = !string.IsNullOrEmpty(asset.DisplayName) ? asset.DisplayName : asset.Name; 68 string type = GetVideoType(asset.Value); 69 bool openInModal = Model.Item.GetString("OpenVideoInModal") == "true" ? true : false; 70 bool autoPlay = Model.Item.GetBoolean("VideoAutoPlay"); 71 72 var videoParams = new Dictionary<string, object>(); 73 videoParams.Add("AssetName", asset.Name); 74 videoParams.Add("AssetVideoType", type); 75 videoParams.Add("AssetDisplayName", asset.DisplayName); 76 videoParams.Add("OpenVideoInModal", openInModal); 77 videoParams.Add("VideoAutoPlay", autoPlay); 78 videoParams.Add("Size", size); 79 videoParams.Add("Id", Model.ID); 80 return videoParams; 81 } 82 83 public string GetVideoType(string assetValue) 84 { 85 string type = assetValue.IndexOf("youtu.be", StringComparison.OrdinalIgnoreCase) >= 0 || assetValue.IndexOf("youtube", StringComparison.OrdinalIgnoreCase) >= 0 ? "youtube" : string.Empty; 86 type = assetValue.IndexOf("vimeo", StringComparison.OrdinalIgnoreCase) >= 0 ? "vimeo" : type; 87 type = string.IsNullOrEmpty(type) ? "selfhosted" : type; 88 return type; 89 } 90 91 public string GetYoutubeScreenDump(string assetValue, string quality) 92 { 93 var regex = new Regex(@"(?:youtube\.com\/.*[\?&]v=|youtu\.be\/|youtube\.com\/embed\/)([\w-]+)(?:\?.*)?"); 94 Match match = regex.Match(assetValue); 95 string videoId = match.Success ? match.Groups[1].Value : string.Empty; 96 string youtubeThumbnail = $"https://img.youtube.com/vi/{videoId}/{quality}.jpg"; 97 return youtubeThumbnail; 98 } 99 } 100 101 @{ 102 @* Get the product data *@ 103 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails")) 104 { 105 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"]; 106 } 107 else if (Pageview.Page.Item["DummyProduct"] != null && Pageview.IsVisualEditorMode) 108 { 109 var pageViewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(Pageview.Page); 110 ProductListViewModel productList = pageViewModel.Item.GetValue("DummyProduct") != null ? pageViewModel.Item.GetValue("DummyProduct") as ProductListViewModel : new ProductListViewModel(); 111 112 if (productList?.Products is object) 113 { 114 product = productList.Products[0]; 115 } 116 } 117 } 118 119 @if (product is object) 120 { 121 @* Supported formats *@ 122 supportedImageFormats = new string[] { ".jpg", ".jpeg", ".webp", ".png", ".gif", ".bmp", ".tiff" }; 123 supportedVideoFormats = new string[] { "youtu.be", "youtube", "vimeo", ".mp4", ".webm" }; 124 supportedDocumentFormats = new string[] { ".pdf", ".docx", ".xlsx", ".ppt", "pptx" }; 125 allSupportedFormats = supportedImageFormats.Concat(supportedVideoFormats).Concat(supportedDocumentFormats).ToArray(); 126 127 @* Collect the assets *@ 128 var selectedAssetCategories = Model.Item.GetList("ImageAssets")?.GetRawValue().OfType<string>(); 129 bool includeImagePatternImages = Model.Item.GetBoolean("ImagePatternImages"); 130 131 @* Needed image data collection to support both DefaultImage, ImagePatterns and Image Assets *@ 132 string defaultImage = product.DefaultImage != null ? product.DefaultImage.Value : ""; 133 IEnumerable<MediaViewModel> assetsImages = product.AssetCategories.Where(x => selectedAssetCategories.Contains(x.SystemName)).SelectMany(x => x.Assets); 134 assetsImages = assetsImages.OrderByDescending(x => x.Value.Equals(defaultImage)); 135 IEnumerable<MediaViewModel> assetsList = new MediaViewModel[]{}; 136 assetsList = assetsList.Union(assetsImages); 137 assetsList = includeImagePatternImages ? assetsList.Union(product.ImagePatternImages) : assetsList; 138 assetsList = includeImagePatternImages && assetsList.Count() == 0 ? assetsList.Append(product.DefaultImage) : assetsList; 139 140 bool defaultImageFallback = Model.Item.GetBoolean("DefaultImageFallback"); 141 142 int totalAssets = 0; 143 foreach (MediaViewModel asset in assetsList) { 144 var assetValue = asset.Value; 145 foreach (string format in allSupportedFormats) { 146 if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) { 147 totalAssets++; 148 } 149 } 150 } 151 152 if (totalAssets == 0) 153 { 154 if (defaultImageFallback) { 155 assetsList = new List<MediaViewModel>(){ product.DefaultImage }; 156 totalAssets = 1; 157 } else { 158 assetsList = new List<MediaViewModel>(){ }; 159 totalAssets = 0; 160 } 161 } 162 163 galleryLayout = Model.Item.GetRawValueString("Layout", "grid"); 164 165 @* Get assets from selected categories or get all assets *@ 166 if (totalAssets != 0 && assetsList.Count() != 0) { 167 int desktopAssetNumber = 0; 168 int mobileAssetNumber = 0; 169 int mobileAssetThumbnailNumber = 0; 170 int modalAssetNumber = 0; 171 172 @* Desktop: Show the gallery on large screens *@ 173 <div class="d-none d-lg-block h-100 position-relative item_@Model.Item.SystemName.ToLower() desktop" data-dw-colorscheme="@Model.ColorScheme?.Id"> 174 <div class="grid"> 175 @foreach (MediaViewModel asset in assetsList) { 176 var assetName = asset.Value; 177 foreach (string format in allSupportedFormats) { 178 if (assetName.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) { 179 string size = "desktop"; 180 string assetValue = asset.Value; 181 182 <div class="@GetColumnClass(totalAssets, desktopAssetNumber)"> 183 <div class="h-100"> 184 @foreach (string imageFormat in supportedImageFormats) 185 { //Images 186 if (assetValue.IndexOf(imageFormat, StringComparison.OrdinalIgnoreCase) >= 0) 187 { 188 string productName = product.Name; 189 string imagePath = !string.IsNullOrEmpty(asset.Value) ? asset.Value : product.DefaultImage.Value; 190 191 RatioSettings ratioSettings = GetRatioSettings(size); 192 193 var parms = new Dictionary<string, object>(); 194 parms.Add("alt", productName); 195 parms.Add("itemprop", "image"); 196 if (totalAssets > 1) 197 { 198 parms.Add("columns", 2); 199 } 200 else 201 { 202 parms.Add("columns", 1); 203 } 204 parms.Add("eagerLoadNewImages", Model.Item.GetBoolean("DisableLazyLoading")); 205 parms.Add("doNotUseGetimage", Model.Item.GetBoolean("DisableGetImage")); 206 207 if (!string.IsNullOrEmpty(asset.DisplayName)) 208 { 209 parms.Add("title", asset.DisplayName); 210 } 211 212 if (ratioSettings.Ratio == "fill" && galleryLayout != "grid") 213 { 214 parms.Add("cssClass", "w-100 h-100 image-zoom-lg-l-hover"); 215 } 216 else 217 { 218 parms.Add("cssClass", "mw-100 mh-100"); 219 } 220 221 <a href="@imagePath" class="d-block @(ratioSettings.CssClass)@(ratioSettings.Fill)" style="@(ratioSettings.CssVariable)" data-bs-toggle="modal" data-bs-target="#modal_@Model.ID"> 222 <div class="d-flex align-items-center justify-content-center overflow-hidden h-100" data-bs-target="#ModalCarousel_@Model.ID" data-bs-slide-to="@desktopAssetNumber"> 223 @RenderPartial("Components/Image.cshtml", new FileViewModel { Path = imagePath }, parms) 224 </div> 225 </a> 226 } 227 } 228 @foreach (string videoFormat in supportedVideoFormats) 229 { //Videos 230 if (assetValue.IndexOf(videoFormat, StringComparison.OrdinalIgnoreCase) >= 0) 231 { 232 if (Model.Item.GetString("OpenVideoInModal") == "true") 233 { 234 string iconPath = "/Files/Templates/Designs/Swift-v2/Assets/icons/"; 235 236 string type = GetVideoType(asset.Value); 237 string videoScreendumpPath = type == "selfhosted" ? asset.Value : string.Empty; 238 videoScreendumpPath = type == "youtube" ? GetYoutubeScreenDump(asset.Value, "maxresdefault") : videoScreendumpPath; 239 string videoJsClass = type == "vimeo" ? "js-vimeo-video-thumbnail" : string.Empty; 240 241 string productName = product.Name; 242 productName += !string.IsNullOrEmpty(asset.Keywords) ? " " + asset.Keywords : ""; 243 string assetTitle = !string.IsNullOrEmpty(asset.DisplayName) ? "title=\"" + asset.DisplayName + "\"" : ""; 244 245 RatioSettings ratioSettings = GetRatioSettings(size); 246 <div class="d-block @(ratioSettings.CssClass)@(ratioSettings.Fill)" style="@(ratioSettings.CssVariable); cursor: pointer" data-bs-toggle="modal" data-bs-target="#modal_@Model.ID"> 247 <div class="d-flex align-items-center justify-content-center overflow-hidden h-100" data-bs-target="#ModalCarousel_@Model.ID" data-bs-slide-to="@desktopAssetNumber"> 248 <div class="icon-5 position-absolute" style="z-index: 1">@ReadFile(iconPath + "play-circle.svg")</div> 249 @if (type != "selfhosted") 250 { 251 <img src="@videoScreendumpPath" loading="lazy" decoding="async" alt="@productName" @assetTitle class="@videoJsClass mw-100 mh-100" data-asset-value="@asset.Value" style="object-fit: cover;" /> 252 } 253 else 254 { 255 string videoType = Path.GetExtension(asset.Value).ToLower(); 256 257 <video preload="auto" class="h-100 w-100" style="object-fit: contain;"> 258 <source src="@(videoScreendumpPath)#t=0.001" type="video/@videoType.Replace(".", "")"> 259 </video> 260 } 261 </div> 262 </div> 263 264 } 265 else 266 { 267 var videoParams = GetVideoParams(asset, size); 268 @RenderPartial("Components/VideoPlayer.cshtml", new FileViewModel { Path = asset.Value }, videoParams); 269 } 270 } 271 } 272 @foreach (string documentFormat in supportedDocumentFormats) 273 { //Documents 274 if (assetValue.IndexOf(documentFormat, StringComparison.OrdinalIgnoreCase) >= 0) 275 { 276 string iconPath = "/Files/Templates/Designs/Swift-v2/Assets/icons/"; 277 278 string productName = product.Name; 279 string imagePath = !string.IsNullOrEmpty(asset.Value) ? asset.Value : product.DefaultImage.Value; 280 281 RatioSettings ratioSettings = GetRatioSettings(size); 282 283 var parms = new Dictionary<string, object>(); 284 parms.Add("alt", productName); 285 parms.Add("itemprop", "image"); 286 parms.Add("fullwidth", true); 287 parms.Add("columns", Model.GridRowColumnCount); 288 if (!string.IsNullOrEmpty(asset.DisplayName)) 289 { 290 parms.Add("title", asset.DisplayName); 291 } 292 293 if (ratioSettings.Ratio == "fill" && galleryLayout != "grid") 294 { 295 parms.Add("cssClass", "w-100 h-100 image-zoom-lg-l-hover"); 296 } 297 else 298 { 299 parms.Add("cssClass", "mw-100 mh-100"); 300 } 301 302 <a href="@imagePath" class="d-block @(ratioSettings.CssClass)@(ratioSettings.Fill)" style="@(ratioSettings.CssVariable)" download title="@Translate("Download")"> 303 <div class="d-flex align-items-center justify-content-center text-center overflow-hidden h-100 border"> 304 <div class="icon-5 position-absolute" style="z-index: 1">@ReadFile(iconPath + "download.svg")</div> 305 <span>@Translate("Download") @(asset.Name)@Path.GetExtension(asset.Value).ToLower()</span> 306 </div> 307 </a> 308 } 309 } 310 </div> 311 </div> 312 desktopAssetNumber++; 313 } 314 } 315 } 316 </div> 317 318 </div> 319 320 @* Mobile: Show the thumbs on small screens *@ 321 <div class="d-block d-lg-none mx-lg-0 position-relative item_@Model.Item.SystemName.ToLower() mobile" data-dw-colorscheme="@Model.ColorScheme?.Id"> 322 <div id="SmallScreenImages_@Model.ID" class="carousel@(GetArrowsColor())" data-bs-ride="carousel"> 323 <div class="carousel-inner h-100"> 324 @foreach (MediaViewModel asset in assetsList) { 325 var assetValue = asset.Value; 326 foreach (string format in allSupportedFormats) { 327 if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) { 328 string activeSlide = mobileAssetNumber == 0 ? "active" : ""; 329 string size = "mobile"; 330 331 <div class="carousel-item @activeSlide" data-bs-interval="99999"> 332 <div class="h-100"> 333 @foreach (string imageFormat in supportedImageFormats) 334 { //Images 335 if (assetValue.IndexOf(imageFormat, StringComparison.OrdinalIgnoreCase) >= 0) 336 { 337 string productName = product.Name; 338 string imagePath = !string.IsNullOrEmpty(asset.Value) ? asset.Value : product.DefaultImage.Value; 339 340 RatioSettings ratioSettings = GetRatioSettings(size); 341 342 var parms = new Dictionary<string, object>(); 343 parms.Add("alt", productName); 344 parms.Add("itemprop", "image"); 345 if (totalAssets > 1) 346 { 347 parms.Add("columns", 2); 348 } 349 else 350 { 351 parms.Add("columns", 1); 352 } 353 parms.Add("eagerLoadNewImages", Model.Item.GetBoolean("DisableLazyLoading")); 354 parms.Add("doNotUseGetimage", Model.Item.GetBoolean("DisableGetImage")); 355 356 if (!string.IsNullOrEmpty(asset.DisplayName)) 357 { 358 parms.Add("title", asset.DisplayName); 359 } 360 361 if (ratioSettings.Ratio == "fill" && galleryLayout != "grid") 362 { 363 parms.Add("cssClass", "w-100 h-100 image-zoom-lg-l-hover"); 364 } 365 else 366 { 367 parms.Add("cssClass", "mw-100 mh-100"); 368 } 369 370 <a href="@imagePath" class="d-block @(ratioSettings.CssClass)@(ratioSettings.Fill)" style="@(ratioSettings.CssVariable)" data-bs-toggle="modal" data-bs-target="#modal_@Model.ID"> 371 <div class="d-flex align-items-center justify-content-center overflow-hidden h-100" data-bs-target="#ModalCarousel_@Model.ID" data-bs-slide-to="@desktopAssetNumber"> 372 @RenderPartial("Components/Image.cshtml", new FileViewModel { Path = imagePath }, parms) 373 </div> 374 </a> 375 } 376 } 377 @foreach (string videoFormat in supportedVideoFormats) 378 { //Videos 379 if (assetValue.IndexOf(videoFormat, StringComparison.OrdinalIgnoreCase) >= 0) 380 { 381 if (Model.Item.GetString("OpenVideoInModal") == "true") 382 { 383 string iconPath = "/Files/Templates/Designs/Swift-v2/Assets/icons/"; 384 385 string type = GetVideoType(asset.Value); 386 387 string videoScreendumpPath = type == "selfhosted" ? asset.Value : string.Empty; 388 videoScreendumpPath = type == "youtube" ? GetYoutubeScreenDump(asset.Value, "maxresdefault") : videoScreendumpPath; 389 string videoJsClass = type == "vimeo" ? "js-vimeo-video-thumbnail" : ""; 390 391 string productName = product.Name; 392 productName += !string.IsNullOrEmpty(asset.Keywords) ? " " + asset.Keywords : ""; 393 string assetTitle = !string.IsNullOrEmpty(asset.DisplayName) ? "title=\"" + asset.DisplayName + "\"" : ""; 394 395 RatioSettings ratioSettings = GetRatioSettings(size); 396 397 <div class="d-block @(ratioSettings.CssClass)@(ratioSettings.Fill)" style="@(ratioSettings.CssVariable); cursor: pointer" data-bs-toggle="modal" data-bs-target="#modal_@Model.ID"> 398 <div class="d-flex align-items-center justify-content-center overflow-hidden h-100" data-bs-target="#ModalCarousel_@Model.ID" data-bs-slide-to="@desktopAssetNumber"> 399 <div class="icon-5 position-absolute" style="z-index: 1">@ReadFile(iconPath + "play-circle.svg")</div> 400 @if (type != "selfhosted") 401 { 402 <img src="@videoScreendumpPath" loading="lazy" decoding="async" alt="@productName" @assetTitle class="@videoJsClass mw-100 mh-100" data-asset-value="@asset.Value" style="object-fit: cover;" > 403 } 404 else 405 { 406 string videoType = Path.GetExtension(asset.Value).ToLower(); 407 408 <video preload="auto" class="h-100 w-100" style="object-fit: contain;"> 409 <source src="@(videoScreendumpPath)#t=0.001" type="video/@videoType.Replace(".", "")"> 410 </video> 411 } 412 </div> 413 </div> 414 } 415 else 416 { 417 Dictionary<string, object> videoParams = GetVideoParams(asset, size); 418 @RenderPartial("Components/VideoPlayer.cshtml", new FileViewModel { Path = asset.Value }, videoParams); 419 } 420 } 421 } 422 </div> 423 </div> 424 mobileAssetNumber++; 425 } 426 } 427 } 428 </div> 429 </div> 430 431 @if (totalAssets > 1) { 432 <div id="SmallScreenImagesThumbnails_@Model.ID" class="d-flex flex-nowrap gap-2 overflow-x-auto my-3"> 433 @foreach (MediaViewModel asset in assetsList) { 434 var assetValue = asset.Value; 435 foreach (string format in allSupportedFormats) { 436 if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) { 437 string iconPath = "/Files/Templates/Designs/Swift-v2/Assets/icons/"; 438 string type = GetVideoType(asset.Value); 439 440 string videoScreendumpPath = type == "youtube" ? GetYoutubeScreenDump(asset.Value, "maxresdefault") : string.Empty; 441 videoScreendumpPath = type == "selfhosted" ? asset.Value : videoScreendumpPath; 442 string videoJsClass = type == "vimeo" ? "js-vimeo-video-thumbnail" : string.Empty; 443 444 string productName = product.Name; 445 productName += !string.IsNullOrEmpty(asset.Keywords) ? " " + asset.Keywords : ""; 446 string assetTitle = !string.IsNullOrEmpty(asset.DisplayName) ? "title=\"" + asset.DisplayName + "\"" : ""; 447 448 <div class="ratio ratio-4x3 border outline-none" style="flex:0 0 80px" data-bs-target="#SmallScreenImages_@Model.ID" data-bs-slide-to="@mobileAssetThumbnailNumber"> 449 @foreach (string imageFormat in supportedImageFormats) 450 { //Images 451 if (assetValue.IndexOf(imageFormat, StringComparison.OrdinalIgnoreCase) >= 0) 452 { 453 string imagePath = !string.IsNullOrEmpty(asset.Value) ? $"/Admin/Public/GetImage.ashx?image={asset.Value}&width=180&format=webp" : string.Empty; 454 <img src="@imagePath" class="p-1 mw-100 mh-100" style="object-fit: cover;" alt="@productName" @assetTitle > 455 } 456 } 457 @foreach (string videoFormat in supportedVideoFormats) 458 { //Videos 459 if (assetValue.IndexOf(videoFormat, StringComparison.OrdinalIgnoreCase) >= 0) 460 { 461 <div class="d-flex align-items-center justify-content-center overflow-hidden h-100"> 462 <div class="icon-3 position-absolute text-light" style="z-index: 1">@ReadFile(iconPath+"play-circle.svg")</div> 463 </div> 464 if (type != "selfhosted") 465 { 466 467 <img src="@(videoScreendumpPath)" class="p-1 @videoJsClass mw-100 mh-100" data-asset-value="@asset.Value" style="object-fit: cover;" alt="@productName" @assetTitle> 468 469 } 470 else 471 { 472 string videoType = Path.GetExtension(asset.Value).ToLower(); 473 474 <video preload="auto" class="h-100 w-100" style="object-fit: contain;"> 475 <source src="@(videoScreendumpPath)#t=0.001" type="video/@videoType.Replace(".", "")"> 476 </video> 477 } 478 } 479 } 480 @foreach (string documentFormat in supportedDocumentFormats) 481 { //Documents 482 if (assetValue.IndexOf(documentFormat, StringComparison.OrdinalIgnoreCase) >= 0) 483 { 484 string imagePath = !string.IsNullOrEmpty(asset.Value) ? $"/Admin/Public/GetImage.ashx?image={asset.Value}&width=180&format=webp" : string.Empty; 485 486 <a href="@(assetValue)" style="cursor: pointer; min-width: 7rem; max-width: 8rem;" download title="@Translate("Download")"> 487 <div class="d-flex align-items-center justify-content-center text-center overflow-hidden h-100 border"> 488 <div class="icon-5 position-absolute" style="z-index: 1">@ReadFile(iconPath + "download.svg")</div> 489 <span>@Translate("Download") @(asset.Name)@Path.GetExtension(asset.Value).ToLower()</span> 490 </div> 491 </a> 492 } 493 } 494 </div> 495 496 mobileAssetThumbnailNumber++; 497 } 498 } 499 } 500 </div> 501 } 502 503 </div> 504 505 @* Modal with slides *@ 506 <div class="modal fade swift_products-details-images-modal" id="modal_@Model.ID" tabindex="-1" aria-labelledby="productDetailsGalleryModalTitle_@Model.ID" aria-hidden="true"> 507 <div class="modal-dialog modal-dialog-centered modal-xl"> 508 <div class="modal-content"> 509 <div class="modal-header visually-hidden"> 510 <h5 class="modal-title" id="productDetailsGalleryModalTitle_@Model.ID">@product.Title</h5> 511 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> 512 </div> 513 <div class="modal-body p-2 p-lg-3 h-100"> 514 <div id="ModalCarousel_@Model.ID" class="carousel@(GetArrowsColor()) h-100" data-bs-ride="carousel"> 515 <div class="carousel-inner h-100" data-dw-colorscheme="@Model.ColorScheme?.Id"> 516 @foreach (MediaViewModel asset in assetsList) { 517 var assetValue = !string.IsNullOrEmpty(asset.Value) ? asset.Value : product.DefaultImage.Value; 518 foreach (string format in allSupportedFormats) { 519 if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) { 520 string imagePath = assetValue; 521 string activeSlide = modalAssetNumber == 0 ? "active" : ""; 522 523 var parms = new Dictionary<string, object>(); 524 parms.Add("cssClass", "d-block mw-100 mh-100 m-auto"); 525 parms.Add("columns", Model.GridRowColumnCount); 526 parms.Add("eagerLoadNewImages", Model.Item.GetBoolean("DisableLazyLoading")); 527 parms.Add("doNotUseGetimage", Model.Item.GetBoolean("DisableGetImage")); 528 529 <div class="carousel-item @activeSlide h-100" data-bs-interval="99999"> 530 @foreach (string imageFormat in supportedImageFormats) { 531 if (assetValue.IndexOf(imageFormat, StringComparison.OrdinalIgnoreCase) >= 0) { 532 @RenderPartial("Components/Image.cshtml", new FileViewModel { Path = imagePath }, parms) 533 } 534 } 535 536 @foreach (string videoFormat in supportedVideoFormats) { 537 if (assetValue.IndexOf(videoFormat, StringComparison.OrdinalIgnoreCase) >= 0) { 538 539 Dictionary<string, object> videoParams = GetVideoParams(asset, "modal"); 540 @RenderPartial("Components/VideoPlayer.cshtml", new FileViewModel { Path = asset.Value }, videoParams); 541 542 } 543 } 544 </div> 545 546 modalAssetNumber++; 547 } 548 } 549 } 550 <button class="carousel-control-prev carousel-control-area" type="button" data-bs-target="#ModalCarousel_@Model.ID" data-bs-slide="prev"> 551 <span class="carousel-control-prev-icon" aria-hidden="true"></span> 552 <span class="visually-hidden">@Translate("Previous")</span> 553 </button> 554 <button class="carousel-control-next carousel-control-area" type="button" data-bs-target="#ModalCarousel_@Model.ID" data-bs-slide="next"> 555 <span class="carousel-control-next-icon" aria-hidden="true"></span> 556 <span class="visually-hidden">@Translate("Next")</span> 557 </button> 558 </div> 559 </div> 560 </div> 561 </div> 562 </div> 563 </div> 564 } else if (Pageview.IsVisualEditorMode) { 565 RatioSettings ratioSettings = GetRatioSettings("desktop"); 566 567 <div class="h-100" data-dw-colorscheme="@Model.ColorScheme?.Id"> 568 <div class="d-block @(ratioSettings.CssClass)@(ratioSettings.Fill)" style="@(ratioSettings.CssVariable)"> 569 <img src="/Files/Images/missing_image.jpg" loading="lazy" decoding="async" class="mh-100 mw-100" style="object-fit: cover;" alt="@Translate("Missing image")"> 570 </div> 571 </div> 572 } 573 } 574
Error executing template "Designs/Swift-v2/Paragraph/Swift-v2_Accordion.cshtml" System.NullReferenceException: Object reference not set to an instance of an object. at CompiledRazorTemplates.Dynamic.RazorEngine_75b7ed891abb45ae976941f5ae3d2ab4.ExecuteAsync() at RazorEngine.Templating.TemplateBase.Run(ExecuteContext context, TextWriter reader) at RazorEngine.Templating.RazorEngineCore.RunTemplate(ICompiledTemplate template, TextWriter writer, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineService.Run(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.DynamicWrapperService.Run(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineServiceExtensions.Run(IRazorEngineService service, String name, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass23_0.<Run>b__0(TextWriter writer) at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter) at RazorEngine.Templating.RazorEngineServiceExtensions.Run(IRazorEngineService service, String name, Type modelType, Object model, DynamicViewBag viewBag) 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 3 @{ 4 string title = Model.Item.GetString("Title"); 5 var accordionItems = Model.Item?.GetItems("Accordion_Items") ?? Enumerable.Empty<Dynamicweb.Frontend.ItemViewModel>().ToList(); 6 } 7 8 <div class="accordion h-100 position-relative item_@Model.Item.SystemName.ToLower()" id="accordion-@Pageview.CurrentParagraph.ID"> 9 @if (!string.IsNullOrEmpty(Model.Item.GetString("Title")) && !Model.Item.GetBoolean("HideTitle")) 10 { 11 string titleFontSize = Model.Item.GetRawValueString("TitleFontSize", "h2"); 12 string headingLevel = Model.Item.GetString("HeadingLevel", "h2"); 13 string headingLevelStart = $"<{headingLevel} class=\"{titleFontSize} mb-4\">"; 14 string headingLevelStop = $"</{headingLevel}>"; 15 16 @headingLevelStart 17 @Model.Item.GetString("Title") 18 @headingLevelStop 19 } 20 @foreach (var item in accordionItems) 21 { 22 <div class="accordion-item"> 23 <h2 class="accordion-header" id="heading-@Pageview.CurrentParagraph.ID-@item.Id"> 24 <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapse-@Pageview.CurrentParagraph.ID-@item.Id" aria-expanded="false" aria-controls="collapse-@Pageview.CurrentParagraph.ID-@item.Id"> 25 @item.GetString("Title") 26 </button> 27 </h2> 28 <div id="collapse-@Pageview.CurrentParagraph.ID-@item.Id" class="accordion-collapse collapse" aria-labelledby="heading-@Pageview.CurrentParagraph.ID-@item.Id" data-bs-parent="#accordion-@Pageview.CurrentParagraph.ID"> 29 <div class="accordion-body mb-0-last-child opacity-75"> 30 @item.GetRawValueString("Content") 31 </div> 32 </div> 33 </div> 34 } 35 <div id="@Model.ID" class="user-select-none position-absolute top-0" style="scroll-margin-top:var(--header-height,150px)"></div> 36 </div> 37
Error executing template "Designs/Swift-v2/Paragraph/Swift-v2_ProductComponentSlider.cshtml" System.NullReferenceException: Object reference not set to an instance of an object. at CompiledRazorTemplates.Dynamic.RazorEngine_927cb4591d4e4d56b5bc11a494c1d8a4.ExecuteAsync() at RazorEngine.Templating.TemplateBase.Run(ExecuteContext context, TextWriter reader) at RazorEngine.Templating.RazorEngineCore.RunTemplate(ICompiledTemplate template, TextWriter writer, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineService.Run(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.DynamicWrapperService.Run(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineServiceExtensions.Run(IRazorEngineService service, String name, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass23_0.<Run>b__0(TextWriter writer) at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter) at RazorEngine.Templating.RazorEngineServiceExtensions.Run(IRazorEngineService service, String name, Type modelType, Object model, DynamicViewBag viewBag) 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 layout = Model.Item.GetRawValueString("Layout") == "slider" ? "ProductSliderComponent" : "ProductGridComponent"; 23 string lazyHeight = Model.Item.GetBoolean("SetMinHeightForLazyLoading") ? "min-height: 360px" : ""; 24 25 //Link generation 26 string pageId = Model.Item.GetLink("ProductSliderServicePage") != null ? Model.Item.GetLink("ProductSliderServicePage").PageId.ToString() : ""; 27 string servicePageByNavigationTag = GetPageIdByNavigationTag("ProductSliderService") != 0 ? GetPageIdByNavigationTag("ProductSliderService").ToString() : ""; 28 pageId = pageId == "" ? servicePageByNavigationTag : pageId; 29 30 string url = "/Default.aspx?ID=" + pageId; 31 32 if (Pageview.IsVisualEditorMode) 33 { 34 url += "&VisualEdit=True"; 35 } 36 37 bool isLazyLoadingForProductInfoEnabled = Dynamicweb.Core.Converter.ToBoolean(Dynamicweb.Context.Current.Items["IsLazyLoadingForProductInfoEnabled"]); 38 if (isLazyLoadingForProductInfoEnabled) 39 { 40 url += "&getproductinfo=true"; 41 } 42 43 url += $"&ProductListPartial={layout}"; //Use this to render either a slider or a grid 44 45 //Source type 46 string sourceType = Model.Item.GetRawValueString("RelationType", "trending"); 47 IList<string> relateFromProductIds = new List<string> { }; 48 IList<string> relateFromProductVariantIds = new List<string> { }; 49 IList<string> relateFromGroupIds = new List<string> { }; 50 bool hasVariants = false; 51 52 53 ProductListViewModel relateToViewModel = Model.Item.GetValue<ProductListViewModel>("RelateTo"); 54 55 //--- PRODUCTS --- 56 if (sourceType == "variants" || sourceType == "frequently" || sourceType == "selected") 57 { 58 if (relateToViewModel?.Products != null) 59 { 60 hasVariants = relateToViewModel.Products.Any(p => !string.IsNullOrEmpty(p.VariantId)); 61 foreach (var fromProduct in relateToViewModel.Products) 62 { 63 if (hasVariants) 64 { 65 if (!string.IsNullOrEmpty(fromProduct.VariantId)) 66 { 67 relateFromProductVariantIds.Add($"{fromProduct.Id} {fromProduct.VariantId}"); 68 } 69 else 70 { 71 relateFromProductVariantIds.Add($"{fromProduct.Id}"); 72 } 73 } 74 relateFromProductIds.Add($"{fromProduct.Id}"); 75 } 76 } 77 } 78 79 //--- GROUPS --- 80 if (sourceType == "most-sold" || sourceType == "trending" || sourceType == "latest" || sourceType == "custom") 81 { 82 var groupsToRelateTo = Model.Item.GetList("RelateTo")?.GetRawValue().OfType<string>().ToList(); 83 84 if (groupsToRelateTo != null) { 85 foreach (var fromGroup in groupsToRelateTo) 86 { 87 var groupId = fromGroup.Length > 2 ? fromGroup.Remove(0, 2) : fromGroup; 88 89 if (!fromGroup.Contains("p_")) 90 { 91 relateFromGroupIds.Add(groupId); 92 } 93 } 94 } 95 96 if (relateToViewModel?.Products != null) 97 { 98 foreach (var fromProduct in relateToViewModel.Products) 99 { 100 var groupId = fromProduct.PrimaryOrDefaultGroup.Id; 101 relateFromGroupIds.Add(groupId); 102 } 103 } 104 } 105 106 string relationGroupId = Model.Item.GetRawValueString("RelationGroup", string.Empty); 107 108 //--- RELATED GROUP --- 109 if (sourceType == "related") 110 { 111 if (relateToViewModel?.Products != null) 112 { 113 product = relateToViewModel.Products.FirstOrDefault(); 114 } 115 116 if (product?.RelatedGroups != null) 117 { 118 foreach (var relationGroup in product.RelatedGroups) 119 { 120 if (relationGroup.Id == relationGroupId) { 121 hasVariants = relationGroup.Products.Any(p => !string.IsNullOrEmpty(p.VariantId)); 122 foreach (var fromProduct in relationGroup.Products) 123 { 124 if (hasVariants) 125 { 126 if (!string.IsNullOrEmpty(fromProduct.VariantId)) 127 { 128 relateFromProductVariantIds.Add($"{fromProduct.ProductId} {fromProduct.VariantId}"); 129 } 130 else 131 { 132 relateFromProductVariantIds.Add($"{fromProduct.ProductId}"); 133 } 134 } 135 relateFromProductIds.Add($"{fromProduct.ProductId}"); 136 } 137 } 138 } 139 } 140 } 141 142 143 //Create group id collection and products id collection strings 144 string productIds = relateFromProductIds.Count > 0 ? string.Join(",", relateFromProductIds) : ""; 145 string productVariantIds = relateFromProductVariantIds.Count > 0 ? string.Join(",", relateFromProductVariantIds) : ""; 146 string groupIds = relateFromGroupIds.Count > 0 ? string.Join(",", relateFromGroupIds) : ""; 147 148 if (product is object) 149 { 150 if (string.IsNullOrEmpty(productIds) && (sourceType == "variants" || sourceType == "frequently" || sourceType == "selected" || sourceType == "custom")) 151 { 152 productIds = product.Id; 153 } 154 155 if (string.IsNullOrEmpty(groupIds) && (sourceType == "most-sold" || sourceType == "trending" || sourceType == "latest")) 156 { 157 groupIds = product.PrimaryOrDefaultGroup.Id; 158 } 159 } 160 } 161 162 @*Container element for the request*@ 163 @if (!string.IsNullOrEmpty(productIds) || !string.IsNullOrEmpty(groupIds) || (string.IsNullOrEmpty(productIds) && string.IsNullOrEmpty(groupIds) && sourceType != "related")) 164 { 165 <form method="post" action="@url" id="ComponentSliderProductsForm_@Model.ID" data-response-target-element="ComponentSliderProducts_@Model.ID" data-preloader="inline" data-update-url="false" class="item_@Model.Item.SystemName.ToLower()"> 166 <input type="hidden" name="ParagraphId" value="@Model.ID" /> 167 <input type="hidden" name="SortOrder" value="DESC"> 168 <input type="hidden" name="SourceType" value="@sourceType"> 169 170 @if (!string.IsNullOrEmpty(groupIds)) 171 { 172 <input type="hidden" name="GroupId" value="@groupIds"> 173 } 174 @if (sourceType != "frequently" && !string.IsNullOrEmpty(productIds) && !hasVariants) 175 { 176 <input type="hidden" name="MainProductId" value="@productIds"> 177 } 178 @if (sourceType != "frequently" && hasVariants) 179 { 180 <input type="hidden" name="ProductVariantId" value="@productVariantIds"> 181 } 182 183 @if (Model.Item.GetInt32("ProductsCount") != 0) 184 { 185 <input type="hidden" name="PageSize" value="@Model.Item.GetInt32("ProductsCount")"> 186 } 187 188 @if (sourceType == "variants") 189 { 190 <input type="hidden" name="isVariant" value="true"> 191 } 192 @if (sourceType == "most-sold") 193 { 194 <input type="hidden" name="SortBy" value="OrderCount"> 195 } 196 @if (sourceType == "trending") 197 { 198 <input type="hidden" name="SortBy" value="OrderCountGrowth"> 199 } 200 @if (sourceType == "frequently" && !string.IsNullOrEmpty(productIds)) 201 { 202 <input type="hidden" name="BoughtWithProductIds" value="[@productIds]"> 203 } 204 @if (sourceType == "latest") 205 { 206 <input type="hidden" name="SortBy" value="Created"> 207 } 208 </form> 209 210 <script type="module"> 211 import {swiffyslider} from '/Files/Templates/Designs/Swift-v2/Assets/lib/swiffy-slider/dist/js/swiffy-slider.esm.min.js'; 212 window.swiffyslider = swiffyslider; 213 swift.AssetLoader.Load('/Files/Templates/Designs/Swift-v2/Assets/lib/swiffy-slider/dist/css/swiffy-slider.min.css', 'css'); 214 </script> 215 216 <div class="w-100 h-100" data-dw-colorscheme="@Model.ColorScheme?.Id"> 217 <div id="@Model.ID" class="user-select-none" style="scroll-margin-top:var(--header-height,150px)"></div> 218 <div id="ComponentSliderProducts_@Model.ID" class="h-100" style="@lazyHeight"></div> 219 </div> 220 221 <script type="module"> 222 const productSliderContainer = document.querySelector("#ComponentSliderProducts_@Model.ID"); 223 const productSliderForm = document.querySelector("#ComponentSliderProductsForm_@Model.ID"); 224 225 swift.PageUpdater.Update(productSliderForm); 226 productSliderForm.addEventListener("updated.swift.pageupdater", function(e){ 227 if (e.detail.html === "") { 228 productSliderContainer.closest("[data-col-size]").classList.add("d-none"); 229 } 230 }); 231 </script> 232 } 233 else if (Pageview.IsVisualEditorMode == true) 234 { 235 <div class="alert alert-dark" role="alert"> 236 <span>@Translate("Product component slider: The slider will be rendered here, if there is anything to show")</span> 237 </div> 238 } 239
Error executing template "Designs/Swift-v2/Paragraph/Swift-v2_Accordion.cshtml" System.NullReferenceException: Object reference not set to an instance of an object. at CompiledRazorTemplates.Dynamic.RazorEngine_75b7ed891abb45ae976941f5ae3d2ab4.ExecuteAsync() at RazorEngine.Templating.TemplateBase.Run(ExecuteContext context, TextWriter reader) at RazorEngine.Templating.RazorEngineCore.RunTemplate(ICompiledTemplate template, TextWriter writer, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineService.Run(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.DynamicWrapperService.Run(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineServiceExtensions.Run(IRazorEngineService service, String name, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass23_0.<Run>b__0(TextWriter writer) at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter) at RazorEngine.Templating.RazorEngineServiceExtensions.Run(IRazorEngineService service, String name, Type modelType, Object model, DynamicViewBag viewBag) 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 3 @{ 4 string title = Model.Item.GetString("Title"); 5 var accordionItems = Model.Item?.GetItems("Accordion_Items") ?? Enumerable.Empty<Dynamicweb.Frontend.ItemViewModel>().ToList(); 6 } 7 8 <div class="accordion h-100 position-relative item_@Model.Item.SystemName.ToLower()" id="accordion-@Pageview.CurrentParagraph.ID"> 9 @if (!string.IsNullOrEmpty(Model.Item.GetString("Title")) && !Model.Item.GetBoolean("HideTitle")) 10 { 11 string titleFontSize = Model.Item.GetRawValueString("TitleFontSize", "h2"); 12 string headingLevel = Model.Item.GetString("HeadingLevel", "h2"); 13 string headingLevelStart = $"<{headingLevel} class=\"{titleFontSize} mb-4\">"; 14 string headingLevelStop = $"</{headingLevel}>"; 15 16 @headingLevelStart 17 @Model.Item.GetString("Title") 18 @headingLevelStop 19 } 20 @foreach (var item in accordionItems) 21 { 22 <div class="accordion-item"> 23 <h2 class="accordion-header" id="heading-@Pageview.CurrentParagraph.ID-@item.Id"> 24 <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapse-@Pageview.CurrentParagraph.ID-@item.Id" aria-expanded="false" aria-controls="collapse-@Pageview.CurrentParagraph.ID-@item.Id"> 25 @item.GetString("Title") 26 </button> 27 </h2> 28 <div id="collapse-@Pageview.CurrentParagraph.ID-@item.Id" class="accordion-collapse collapse" aria-labelledby="heading-@Pageview.CurrentParagraph.ID-@item.Id" data-bs-parent="#accordion-@Pageview.CurrentParagraph.ID"> 29 <div class="accordion-body mb-0-last-child opacity-75"> 30 @item.GetRawValueString("Content") 31 </div> 32 </div> 33 </div> 34 } 35 <div id="@Model.ID" class="user-select-none position-absolute top-0" style="scroll-margin-top:var(--header-height,150px)"></div> 36 </div> 37
Error executing template "Designs/Swift-v2/Paragraph/Swift-v2_ProductComponentSlider.cshtml" System.NullReferenceException: Object reference not set to an instance of an object. at CompiledRazorTemplates.Dynamic.RazorEngine_927cb4591d4e4d56b5bc11a494c1d8a4.ExecuteAsync() at RazorEngine.Templating.TemplateBase.Run(ExecuteContext context, TextWriter reader) at RazorEngine.Templating.RazorEngineCore.RunTemplate(ICompiledTemplate template, TextWriter writer, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineService.Run(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.DynamicWrapperService.Run(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineServiceExtensions.Run(IRazorEngineService service, String name, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass23_0.<Run>b__0(TextWriter writer) at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter) at RazorEngine.Templating.RazorEngineServiceExtensions.Run(IRazorEngineService service, String name, Type modelType, Object model, DynamicViewBag viewBag) 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 layout = Model.Item.GetRawValueString("Layout") == "slider" ? "ProductSliderComponent" : "ProductGridComponent"; 23 string lazyHeight = Model.Item.GetBoolean("SetMinHeightForLazyLoading") ? "min-height: 360px" : ""; 24 25 //Link generation 26 string pageId = Model.Item.GetLink("ProductSliderServicePage") != null ? Model.Item.GetLink("ProductSliderServicePage").PageId.ToString() : ""; 27 string servicePageByNavigationTag = GetPageIdByNavigationTag("ProductSliderService") != 0 ? GetPageIdByNavigationTag("ProductSliderService").ToString() : ""; 28 pageId = pageId == "" ? servicePageByNavigationTag : pageId; 29 30 string url = "/Default.aspx?ID=" + pageId; 31 32 if (Pageview.IsVisualEditorMode) 33 { 34 url += "&VisualEdit=True"; 35 } 36 37 bool isLazyLoadingForProductInfoEnabled = Dynamicweb.Core.Converter.ToBoolean(Dynamicweb.Context.Current.Items["IsLazyLoadingForProductInfoEnabled"]); 38 if (isLazyLoadingForProductInfoEnabled) 39 { 40 url += "&getproductinfo=true"; 41 } 42 43 url += $"&ProductListPartial={layout}"; //Use this to render either a slider or a grid 44 45 //Source type 46 string sourceType = Model.Item.GetRawValueString("RelationType", "trending"); 47 IList<string> relateFromProductIds = new List<string> { }; 48 IList<string> relateFromProductVariantIds = new List<string> { }; 49 IList<string> relateFromGroupIds = new List<string> { }; 50 bool hasVariants = false; 51 52 53 ProductListViewModel relateToViewModel = Model.Item.GetValue<ProductListViewModel>("RelateTo"); 54 55 //--- PRODUCTS --- 56 if (sourceType == "variants" || sourceType == "frequently" || sourceType == "selected") 57 { 58 if (relateToViewModel?.Products != null) 59 { 60 hasVariants = relateToViewModel.Products.Any(p => !string.IsNullOrEmpty(p.VariantId)); 61 foreach (var fromProduct in relateToViewModel.Products) 62 { 63 if (hasVariants) 64 { 65 if (!string.IsNullOrEmpty(fromProduct.VariantId)) 66 { 67 relateFromProductVariantIds.Add($"{fromProduct.Id} {fromProduct.VariantId}"); 68 } 69 else 70 { 71 relateFromProductVariantIds.Add($"{fromProduct.Id}"); 72 } 73 } 74 relateFromProductIds.Add($"{fromProduct.Id}"); 75 } 76 } 77 } 78 79 //--- GROUPS --- 80 if (sourceType == "most-sold" || sourceType == "trending" || sourceType == "latest" || sourceType == "custom") 81 { 82 var groupsToRelateTo = Model.Item.GetList("RelateTo")?.GetRawValue().OfType<string>().ToList(); 83 84 if (groupsToRelateTo != null) { 85 foreach (var fromGroup in groupsToRelateTo) 86 { 87 var groupId = fromGroup.Length > 2 ? fromGroup.Remove(0, 2) : fromGroup; 88 89 if (!fromGroup.Contains("p_")) 90 { 91 relateFromGroupIds.Add(groupId); 92 } 93 } 94 } 95 96 if (relateToViewModel?.Products != null) 97 { 98 foreach (var fromProduct in relateToViewModel.Products) 99 { 100 var groupId = fromProduct.PrimaryOrDefaultGroup.Id; 101 relateFromGroupIds.Add(groupId); 102 } 103 } 104 } 105 106 string relationGroupId = Model.Item.GetRawValueString("RelationGroup", string.Empty); 107 108 //--- RELATED GROUP --- 109 if (sourceType == "related") 110 { 111 if (relateToViewModel?.Products != null) 112 { 113 product = relateToViewModel.Products.FirstOrDefault(); 114 } 115 116 if (product?.RelatedGroups != null) 117 { 118 foreach (var relationGroup in product.RelatedGroups) 119 { 120 if (relationGroup.Id == relationGroupId) { 121 hasVariants = relationGroup.Products.Any(p => !string.IsNullOrEmpty(p.VariantId)); 122 foreach (var fromProduct in relationGroup.Products) 123 { 124 if (hasVariants) 125 { 126 if (!string.IsNullOrEmpty(fromProduct.VariantId)) 127 { 128 relateFromProductVariantIds.Add($"{fromProduct.ProductId} {fromProduct.VariantId}"); 129 } 130 else 131 { 132 relateFromProductVariantIds.Add($"{fromProduct.ProductId}"); 133 } 134 } 135 relateFromProductIds.Add($"{fromProduct.ProductId}"); 136 } 137 } 138 } 139 } 140 } 141 142 143 //Create group id collection and products id collection strings 144 string productIds = relateFromProductIds.Count > 0 ? string.Join(",", relateFromProductIds) : ""; 145 string productVariantIds = relateFromProductVariantIds.Count > 0 ? string.Join(",", relateFromProductVariantIds) : ""; 146 string groupIds = relateFromGroupIds.Count > 0 ? string.Join(",", relateFromGroupIds) : ""; 147 148 if (product is object) 149 { 150 if (string.IsNullOrEmpty(productIds) && (sourceType == "variants" || sourceType == "frequently" || sourceType == "selected" || sourceType == "custom")) 151 { 152 productIds = product.Id; 153 } 154 155 if (string.IsNullOrEmpty(groupIds) && (sourceType == "most-sold" || sourceType == "trending" || sourceType == "latest")) 156 { 157 groupIds = product.PrimaryOrDefaultGroup.Id; 158 } 159 } 160 } 161 162 @*Container element for the request*@ 163 @if (!string.IsNullOrEmpty(productIds) || !string.IsNullOrEmpty(groupIds) || (string.IsNullOrEmpty(productIds) && string.IsNullOrEmpty(groupIds) && sourceType != "related")) 164 { 165 <form method="post" action="@url" id="ComponentSliderProductsForm_@Model.ID" data-response-target-element="ComponentSliderProducts_@Model.ID" data-preloader="inline" data-update-url="false" class="item_@Model.Item.SystemName.ToLower()"> 166 <input type="hidden" name="ParagraphId" value="@Model.ID" /> 167 <input type="hidden" name="SortOrder" value="DESC"> 168 <input type="hidden" name="SourceType" value="@sourceType"> 169 170 @if (!string.IsNullOrEmpty(groupIds)) 171 { 172 <input type="hidden" name="GroupId" value="@groupIds"> 173 } 174 @if (sourceType != "frequently" && !string.IsNullOrEmpty(productIds) && !hasVariants) 175 { 176 <input type="hidden" name="MainProductId" value="@productIds"> 177 } 178 @if (sourceType != "frequently" && hasVariants) 179 { 180 <input type="hidden" name="ProductVariantId" value="@productVariantIds"> 181 } 182 183 @if (Model.Item.GetInt32("ProductsCount") != 0) 184 { 185 <input type="hidden" name="PageSize" value="@Model.Item.GetInt32("ProductsCount")"> 186 } 187 188 @if (sourceType == "variants") 189 { 190 <input type="hidden" name="isVariant" value="true"> 191 } 192 @if (sourceType == "most-sold") 193 { 194 <input type="hidden" name="SortBy" value="OrderCount"> 195 } 196 @if (sourceType == "trending") 197 { 198 <input type="hidden" name="SortBy" value="OrderCountGrowth"> 199 } 200 @if (sourceType == "frequently" && !string.IsNullOrEmpty(productIds)) 201 { 202 <input type="hidden" name="BoughtWithProductIds" value="[@productIds]"> 203 } 204 @if (sourceType == "latest") 205 { 206 <input type="hidden" name="SortBy" value="Created"> 207 } 208 </form> 209 210 <script type="module"> 211 import {swiffyslider} from '/Files/Templates/Designs/Swift-v2/Assets/lib/swiffy-slider/dist/js/swiffy-slider.esm.min.js'; 212 window.swiffyslider = swiffyslider; 213 swift.AssetLoader.Load('/Files/Templates/Designs/Swift-v2/Assets/lib/swiffy-slider/dist/css/swiffy-slider.min.css', 'css'); 214 </script> 215 216 <div class="w-100 h-100" data-dw-colorscheme="@Model.ColorScheme?.Id"> 217 <div id="@Model.ID" class="user-select-none" style="scroll-margin-top:var(--header-height,150px)"></div> 218 <div id="ComponentSliderProducts_@Model.ID" class="h-100" style="@lazyHeight"></div> 219 </div> 220 221 <script type="module"> 222 const productSliderContainer = document.querySelector("#ComponentSliderProducts_@Model.ID"); 223 const productSliderForm = document.querySelector("#ComponentSliderProductsForm_@Model.ID"); 224 225 swift.PageUpdater.Update(productSliderForm); 226 productSliderForm.addEventListener("updated.swift.pageupdater", function(e){ 227 if (e.detail.html === "") { 228 productSliderContainer.closest("[data-col-size]").classList.add("d-none"); 229 } 230 }); 231 </script> 232 } 233 else if (Pageview.IsVisualEditorMode == true) 234 { 235 <div class="alert alert-dark" role="alert"> 236 <span>@Translate("Product component slider: The slider will be rendered here, if there is anything to show")</span> 237 </div> 238 } 239