Error executing template "Designs/Swift/eCom/ProductCatalog/ProductViewDetail.cshtml"
System.Data.SqlClient.SqlException (0x80131904): Transaction (Process ID 87) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
   at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
   at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
   at System.Data.SqlClient.SqlDataReader.TryHasMoreRows(Boolean& moreRows)
   at System.Data.SqlClient.SqlDataReader.TryReadInternal(Boolean setTimeout, Boolean& more)
   at System.Data.SqlClient.SqlDataReader.Read()
   at Dynamicweb.Ecommerce.Products.ProductRepository.Dynamicweb.Ecommerce.Products.IProductRepository.GetProductKeysByGroupId(String groupId, Boolean useOrderBy, Boolean includeVariants, String productLanguageId, Boolean doRefactoring, Boolean useAssortments)
   at Dynamicweb.Ecommerce.Orders.Discounts.Discount.ProcessProductSelections(HashSet`1& productKeys, HashSet`1& includedQueries, HashSet`1& excludedQueries)
   at Dynamicweb.Ecommerce.Orders.Discounts.Discount.GetRelevantProductKeys()
   at Dynamicweb.Ecommerce.Orders.Discounts.DiscountService.StatelessSetLookup(Discount discount, ConcurrentDictionary`2 lookup)
   at Dynamicweb.Ecommerce.Orders.Discounts.DiscountService.InitializeLookup()
   at System.Lazy`1.CreateValue()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Lazy`1.get_Value()
   at Dynamicweb.Ecommerce.Orders.Discounts.DiscountService.GetDiscounts(DiscountApplyType[] discountTypes, String[] productKeys, User user)
   at Dynamicweb.Ecommerce.Orders.Discounts.DiscountInfoCollection.LoadDiscounts()
   at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.GetDiscountInfo(PriceViewModelSettings settings, Product product)
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.LazyInitValue()
   at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.<>c__DisplayClass3_2.<BulkCreateView>b__46()
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.LazyInitValue()
   at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.<>c__DisplayClass3_2.<BulkCreateView>b__48()
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.LazyInitValue()
   at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.GetPrice(PriceViewModelSettings settings, IList`1 products, Boolean& pricesHasBeenPrepared, Object lock, Lazy`1 priceInfo)
   at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.<>c__DisplayClass3_2.<BulkCreateView>b__49()
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.LazyInitValue()
   at CompiledRazorTemplates.Dynamic.RazorEngine_83acea8c3dfa4852bf3043a4bc23aff5.Execute() in D:\dynamicweb.net\Solutions\brdklee.cloud.dynamicweb-cms.com\files\Templates\Designs\Swift\eCom\ProductCatalog\ProductViewDetail.cshtml:line 53
   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()
ClientConnectionId:fef7765e-6e46-4ec9-ae86-c26a77b01d5e
Error Number:1205,State:52,Class:13

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: @PriceViewModelExtensions.ToStringInvariant(Model.Price), 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: @PriceViewModelExtensions.ToStringInvariant(Model.Price) 61 } 62 ] 63 }); 64 </script> 65 66 <script> 67 window.addEventListener('load', function (event) { 68 swift.Video.init(); 69 }); 70 </script> 71
Error executing template "Designs/Swift/Paragraph/Swift_ProductDetailsImage.cshtml"
System.Data.SqlClient.SqlException (0x80131904): Transaction (Process ID 87) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
   at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
   at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
   at System.Data.SqlClient.SqlDataReader.TryHasMoreRows(Boolean& moreRows)
   at System.Data.SqlClient.SqlDataReader.TryReadInternal(Boolean setTimeout, Boolean& more)
   at System.Data.SqlClient.SqlDataReader.Read()
   at Dynamicweb.Ecommerce.Products.ProductRepository.Dynamicweb.Ecommerce.Products.IProductRepository.GetProductKeysByGroupId(String groupId, Boolean useOrderBy, Boolean includeVariants, String productLanguageId, Boolean doRefactoring, Boolean useAssortments)
   at Dynamicweb.Ecommerce.Orders.Discounts.Discount.ProcessProductSelections(HashSet`1& productKeys, HashSet`1& includedQueries, HashSet`1& excludedQueries)
   at Dynamicweb.Ecommerce.Orders.Discounts.Discount.GetRelevantProductKeys()
   at Dynamicweb.Ecommerce.Orders.Discounts.DiscountService.StatelessSetLookup(Discount discount, ConcurrentDictionary`2 lookup)
   at Dynamicweb.Ecommerce.Orders.Discounts.DiscountService.InitializeLookup()
   at System.Lazy`1.CreateValue()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Lazy`1.get_Value()
   at Dynamicweb.Ecommerce.Orders.Discounts.DiscountService.GetDiscounts(DiscountApplyType[] discountTypes, String[] productKeys, User user)
   at Dynamicweb.Ecommerce.Orders.Discounts.DiscountInfoCollection.LoadDiscounts()
   at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.GetDiscountInfo(PriceViewModelSettings settings, Product product)
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.LazyInitValue()
   at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.<>c__DisplayClass3_2.<BulkCreateView>b__46()
   at System.Lazy`1.CreateValue()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Lazy`1.get_Value()
   at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.GetPrice(PriceViewModelSettings settings, IList`1 products, Boolean& pricesHasBeenPrepared, Object lock, Lazy`1 priceInfo)
   at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.<>c__DisplayClass3_2.<BulkCreateView>b__51()
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.LazyInitValue()
   at CompiledRazorTemplates.Dynamic.RazorEngine_fa0cf5cecdde4a9a8e4a64567db54178.Execute() in D:\dynamicweb.net\Solutions\brdklee.cloud.dynamicweb-cms.com\files\Templates\Designs\Swift\Paragraph\Swift_ProductDetailsImage.cshtml:line 121
   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()
ClientConnectionId:fef7765e-6e46-4ec9-ae86-c26a77b01d5e
Error Number:1205,State:52,Class:13

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-10 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="carousel-inner h-100"> 236 @foreach (MediaViewModel asset in assetsList) { 237 var assetValue = !string.IsNullOrEmpty(asset.Value) ? asset.Value : product.DefaultImage.Value; 238 foreach (string format in supportedImageFormats.Concat(supportedVideoFormats).ToArray()) { 239 if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) { 240 string imagePath = assetValue; 241 string activeSlide = modalAssetNumber == 0 ? "active" : ""; 242 243 var parms = new Dictionary<string, object>(); 244 parms.Add("cssClass", "d-block mw-100 mh-100 m-auto"); 245 parms.Add("fullwidth", true); 246 parms.Add("columns", Model.GridRowColumnCount); 247 248 <div class="carousel-item @activeSlide h-100" data-bs-interval="99999"> 249 @foreach (string imageFormat in supportedImageFormats) { //Images 250 if (assetValue.IndexOf(imageFormat, StringComparison.OrdinalIgnoreCase) >= 0) { 251 @RenderPartial("Components/Image.cshtml", new FileViewModel { Path = imagePath }, parms) 252 } 253 } 254 255 @foreach (string videoFormat in supportedVideoFormats) { //Videos 256 if (assetValue.IndexOf(videoFormat, StringComparison.OrdinalIgnoreCase) >= 0) { 257 {@RenderVideoPlayer(asset, "modal")} 258 } 259 } 260 </div> 261 262 modalAssetNumber++; 263 } 264 } 265 } 266 <button class="carousel-control-prev" type="button" data-bs-target="#ModalCarousel_@Model.ID" data-bs-slide="prev"> 267 <span class="carousel-control-prev-icon" aria-hidden="true"></span> 268 <span class="visually-hidden">@Translate("Previous")</span> 269 </button> 270 <button class="carousel-control-next" type="button" data-bs-target="#ModalCarousel_@Model.ID" data-bs-slide="next"> 271 <span class="carousel-control-next-icon" aria-hidden="true"></span> 272 <span class="visually-hidden">@Translate("Next")</span> 273 </button> 274 </div> 275 </div> 276 </div> 277 </div> 278 </div> 279 </div> 280 } else if (Pageview.IsVisualEditorMode) { 281 RatioSettings ratioSettings = GetRatioSettings("desktop"); 282 283 <div class="h-100 @theme"> 284 <div class="d-block @(ratioSettings.CssClass)@(ratioSettings.Fill)" style="@(ratioSettings.CssVariable)"> 285 <img src="/Files/Images/missing_image.jpg" loading="lazy" decoding="async" class="mh-100 mw-100" style="object-fit: cover;"> 286 </div> 287 </div> 288 } 289 } else if (Pageview.IsVisualEditorMode) { 290 <div class="alert alert-dark m-0">@Translate("No products available")</div> 291 } 292 293 @helper RenderAsset(MediaViewModel asset, int assetNumber, string size = "desktop") { 294 string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("ImageTheme")) ? " theme " + Model.Item.GetRawValueString("ImageTheme").Replace(" ", "").Trim().ToLower() : ""; 295 string assetValue = asset.Value; 296 297 <div class="h-100 @(theme)"> 298 @foreach (string format in supportedImageFormats) { //Images 299 if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) { 300 {@RenderImage(asset, assetNumber, size)} 301 } 302 } 303 @foreach (string format in supportedVideoFormats) { //Videos 304 if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) { 305 if (Model.Item.GetString("OpenVideoInModal") == "true") { 306 {@RenderVideoScreendump(asset, assetNumber, size)} 307 } else { 308 {@RenderVideoPlayer(asset, size)} 309 } 310 } 311 } 312 @foreach (string format in supportedDocumentFormats) { //Documents 313 if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) { 314 {@RenderDocument(asset, assetNumber, size)} 315 } 316 } 317 </div> 318 } 319 320 @helper RenderImage(MediaViewModel asset, int number, string size = "desktop") { 321 if (product is object) 322 { 323 string productName = product.Name; 324 string imagePath = !string.IsNullOrEmpty(asset.Value) ? asset.Value : product.DefaultImage.Value; 325 string imageLinkPath = Dynamicweb.Context.Current.Server.UrlEncode(imagePath); 326 327 RatioSettings ratioSettings = GetRatioSettings(size); 328 329 var parms = new Dictionary<string, object>(); 330 parms.Add("alt", productName + asset.Keywords); 331 parms.Add("itemprop", "image"); 332 parms.Add("fullwidth", true); 333 parms.Add("columns", Model.GridRowColumnCount); 334 if (!string.IsNullOrEmpty(asset.DisplayName)) { 335 parms.Add("title", asset.DisplayName); 336 } 337 338 if (ratioSettings.Ratio == "fill" && galleryLayout != "grid") { 339 parms.Add("cssClass", "w-100 h-100 image-zoom-lg-l-hover"); 340 } else { 341 parms.Add("cssClass", "mw-100 mh-100"); 342 } 343 344 <a href="@imageLinkPath" class="d-block @(ratioSettings.CssClass)@(ratioSettings.Fill)" style="@(ratioSettings.CssVariable)" data-bs-toggle="modal" data-bs-target="#modal_@Model.ID"> 345 <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"> 346 @RenderPartial("Components/Image.cshtml", new FileViewModel { Path = imagePath }, parms) 347 </div> 348 </a> 349 } 350 } 351 352 @helper RenderVideoScreendump(MediaViewModel asset, int number, string size = "desktop") { 353 if (product is object) 354 { 355 string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/"; 356 357 string videoScreendumpPath = !string.IsNullOrEmpty(asset.Value) ? asset.Value : ""; 358 string videoId = videoScreendumpPath.Substring(videoScreendumpPath.LastIndexOf('/') + 1); 359 videoScreendumpPath = videoScreendumpPath.IndexOf("youtu.be", StringComparison.OrdinalIgnoreCase) >= 0 || videoScreendumpPath.IndexOf("youtube", StringComparison.OrdinalIgnoreCase) >= 0 ? "https://img.youtube.com/vi/" + videoId + "/maxresdefault.jpg" : videoScreendumpPath; 360 361 string vimeoJsClass = videoScreendumpPath.IndexOf("vimeo", StringComparison.OrdinalIgnoreCase) >= 0 ? "js-vimeo-video-thumbnail" : ""; 362 videoScreendumpPath = videoScreendumpPath.IndexOf("vimeo", StringComparison.OrdinalIgnoreCase) >= 0 ? "" : videoScreendumpPath; 363 364 string productName = product.Name; 365 productName += !string.IsNullOrEmpty(asset.Keywords) ? " " + asset.Keywords : ""; 366 string assetTitle = !string.IsNullOrEmpty(asset.DisplayName) ? "title=\"" + asset.DisplayName + "\"" : ""; 367 368 RatioSettings ratioSettings = GetRatioSettings(size); 369 370 <div class="d-block @(ratioSettings.CssClass)@(ratioSettings.Fill)" style="@(ratioSettings.CssVariable); cursor: pointer" 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="@number"> 372 <div class="icon-5 position-absolute" style="z-index: 1">@ReadFile(iconPath + "play-circle.svg")</div> 373 @if (videoScreendumpPath.IndexOf(".mp4", StringComparison.OrdinalIgnoreCase) < 0) 374 { 375 <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)"> 376 } 377 else 378 { 379 string videoType = Path.GetExtension(asset.Value).ToLower(); 380 381 <video preload="auto" class="h-100 w-100" style="object-fit: contain;"> 382 <source src="@asset.Value" type="video/@videoType.Replace(".", "")"> 383 </video> 384 } 385 </div> 386 </div> 387 388 <script> 389 function CheckIfVideoThumbnailExist(image) { 390 if (image.width == 120) { 391 const lowQualityImage = "https://img.youtube.com/vi/@(videoId)/hqdefault.jpg" 392 image.src = lowQualityImage; 393 } 394 } 395 </script> 396 } 397 } 398 399 @helper RenderVideoPlayer(MediaViewModel asset, string size = "desktop") { 400 if (product is object) 401 { 402 string assetName = !string.IsNullOrEmpty(asset.DisplayName) ? asset.DisplayName : asset.Name; 403 string assetValue = asset.Value; 404 string videoId = asset.Value.Substring(asset.Value.LastIndexOf('/') + 1); 405 string type = assetValue.IndexOf("youtu.be", StringComparison.OrdinalIgnoreCase) >= 0 || assetValue.IndexOf("youtube", StringComparison.OrdinalIgnoreCase) >= 0 ? "youtube" : ""; 406 type = assetValue.IndexOf("vimeo", StringComparison.OrdinalIgnoreCase) >= 0 ? "vimeo" : type; 407 type = assetValue.IndexOf(".mp4", StringComparison.OrdinalIgnoreCase) >= 0 || assetValue.IndexOf(".webm", StringComparison.OrdinalIgnoreCase) >= 0 ? "selfhosted" : type; 408 409 string openInModal = Model.Item.GetString("OpenVideoInModal"); 410 bool autoPlay = Model.Item.GetBoolean("VideoAutoPlay"); 411 412 <div class="h-100" itemscope itemtype="https://schema.org/VideoObject"> 413 <span class="visually-hidden" itemprop="name">@assetName</span> 414 <span class="visually-hidden" itemprop="contentUrl">@asset.Value</span> 415 <span class="visually-hidden" itemprop="thumbnailUrl">@asset.Value</span> 416 417 @if (type != "selfhosted") 418 { 419 <div 420 id="player_@(Pageview.CurrentParagraph.ID)_@(videoId)_@size" 421 class="plyr__video-embed" 422 data-plyr-provider="@(type)" 423 data-plyr-embed-id="@videoId" 424 style="--plyr-color-main: var(--swift-foreground-color); height: 100%"> 425 </div> 426 427 <script type="module" src="/Files/Templates/Designs/Swift/Assets/js/plyr.js"></script> 428 429 <script type="module"> 430 var player = new Plyr('#player_@(Pageview.CurrentParagraph.ID)_@(videoId)_@size', { 431 type: 'video', 432 youtube: { 433 noCookie: true, 434 showinfo: 0 435 }, 436 fullscreen: { 437 enabled: true, 438 iosNative: true, 439 } 440 }); 441 442 @if (autoPlay && openInModal == "false") 443 { 444 <text> 445 player.config.autoplay = true; 446 player.config.muted = true; 447 player.config.volume = 0; 448 player.media.loop = true; 449 450 player.on('ready', function() { 451 if (player.config.autoplay === true) { 452 player.media.play(); 453 } 454 }); 455 </text> 456 } 457 458 @if (openInModal == "true") 459 { 460 <text> 461 var productDetailsGalleryModal = document.querySelector('#modal_@Model.ID') 462 productDetailsGalleryModal.addEventListener('hidden.bs.modal', function (event) { 463 player.media.pause(); 464 }) 465 </text> 466 } 467 </script> 468 } 469 else 470 { 471 string autoPlayAttributes = (autoPlay && openInModal == "false") ? "loop autoplay muted playsinline" : ""; 472 string videoType = Path.GetExtension(assetValue).ToLower(); 473 474 <video preload="auto" @autoPlayAttributes class="h-100 w-100" style="object-fit: cover;" controls> 475 <source src="@assetValue" type="video/@videoType.Replace(".", "")"> 476 </video> 477 } 478 </div> 479 } 480 } 481 482 @helper RenderDocument(MediaViewModel asset, int number, string size = "desktop") { 483 if (product is object) 484 { 485 string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/"; 486 487 string productName = product.Name; 488 string imagePath = !string.IsNullOrEmpty(asset.Value) ? asset.Value : product.DefaultImage.Value; 489 string imageLinkPath = imagePath; 490 491 RatioSettings ratioSettings = GetRatioSettings(size); 492 493 var parms = new Dictionary<string, object>(); 494 parms.Add("alt", productName + asset.Keywords); 495 parms.Add("itemprop", "image"); 496 parms.Add("fullwidth", true); 497 parms.Add("columns", Model.GridRowColumnCount); 498 if (!string.IsNullOrEmpty(asset.DisplayName)) { 499 parms.Add("title", asset.DisplayName); 500 } 501 502 if (ratioSettings.Ratio == "fill" && galleryLayout != "grid") { 503 parms.Add("cssClass", "w-100 h-100 image-zoom-lg-l-hover"); 504 } else { 505 parms.Add("cssClass", "mw-100 mh-100"); 506 } 507 508 <a href="@imageLinkPath" class="d-block @(ratioSettings.CssClass)@(ratioSettings.Fill)" style="@(ratioSettings.CssVariable)" download alt="@Translate("Download")"> 509 <div class="d-flex align-items-center justify-content-center overflow-hidden h-100"> 510 <div class="icon-5 position-absolute" style="z-index: 1">@ReadFile(iconPath + "download.svg")</div> 511 @if (asset.Value.IndexOf(".pdf", StringComparison.OrdinalIgnoreCase) >= 0) { 512 @RenderPartial("Components/Image.cshtml", new FileViewModel { Path = imagePath }, parms) 513 } 514 </div> 515 </a> 516 } 517 } 518

KLEEdrive T3A B35

Ikke på lager

Opret dig som kunde under "Log ind" eller send os en forespørgsel!

Error executing template "/Designs/Swift/Paragraph/Swift_ProductPrice_Custom.cshtml"
System.Data.SqlClient.SqlException (0x80131904): Transaction (Process ID 87) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
   at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
   at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
   at System.Data.SqlClient.SqlDataReader.TryHasMoreRows(Boolean& moreRows)
   at System.Data.SqlClient.SqlDataReader.TryReadInternal(Boolean setTimeout, Boolean& more)
   at System.Data.SqlClient.SqlDataReader.Read()
   at Dynamicweb.Ecommerce.Products.ProductRepository.Dynamicweb.Ecommerce.Products.IProductRepository.GetProductKeysByGroupId(String groupId, Boolean useOrderBy, Boolean includeVariants, String productLanguageId, Boolean doRefactoring, Boolean useAssortments)
   at Dynamicweb.Ecommerce.Orders.Discounts.Discount.ProcessProductSelections(HashSet`1& productKeys, HashSet`1& includedQueries, HashSet`1& excludedQueries)
   at Dynamicweb.Ecommerce.Orders.Discounts.Discount.GetRelevantProductKeys()
   at Dynamicweb.Ecommerce.Orders.Discounts.DiscountService.StatelessSetLookup(Discount discount, ConcurrentDictionary`2 lookup)
   at Dynamicweb.Ecommerce.Orders.Discounts.DiscountService.InitializeLookup()
   at System.Lazy`1.CreateValue()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Lazy`1.get_Value()
   at Dynamicweb.Ecommerce.Orders.Discounts.DiscountService.GetDiscounts(DiscountApplyType[] discountTypes, String[] productKeys, User user)
   at Dynamicweb.Ecommerce.Orders.Discounts.DiscountInfoCollection.LoadDiscounts()
   at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.GetDiscountInfo(PriceViewModelSettings settings, Product product)
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.LazyInitValue()
   at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.<>c__DisplayClass3_2.<BulkCreateView>b__46()
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.LazyInitValue()
   at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.<>c__DisplayClass3_2.<BulkCreateView>b__48()
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.LazyInitValue()
   at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.GetPrice(PriceViewModelSettings settings, IList`1 products, Boolean& pricesHasBeenPrepared, Object lock, Lazy`1 priceInfo)
   at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.<>c__DisplayClass3_2.<BulkCreateView>b__49()
   at System.Lazy`1.CreateValue()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Lazy`1.get_Value()
   at CompiledRazorTemplates.Dynamic.RazorEngine_fd0c119cc2b247cca49b3e73d294d4c9.Execute() in D:\dynamicweb.net\Solutions\brdklee.cloud.dynamicweb-cms.com\files\Templates\Designs\Swift\Paragraph\Swift_ProductPrice_Custom.cshtml:line 107
   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()
ClientConnectionId:fef7765e-6e46-4ec9-ae86-c26a77b01d5e
Error Number:1205,State:52,Class:13

1 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.ParagraphViewModel> 2 @using Dynamicweb.Ecommerce.ProductCatalog; 3 @using System.Linq; 4 @using Dynamicweb.Environment; 5 @using Dynamicweb.Core; 6 @using CustomCode.Models; 7 @using CustomCode.Helpers; 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.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 string anonymousUsersLimitations = Pageview.AreaSettings.GetRawValueString("AnonymousUsers", ""); 26 bool anonymousUser = Pageview.User == null; 27 bool isErpConnectionDown = !Dynamicweb.Core.Converter.ToBoolean(Dynamicweb.Context.Current.Items["IsWebServiceConnectionAvailable"]); 28 bool hidePrice = anonymousUsersLimitations.Contains("price") && anonymousUser || Pageview.AreaSettings.GetBoolean("ErpDownHidePrices") && isErpConnectionDown; 29 30 bool productIsDiscontinued = product is object && product.Discontinued; 31 bool doNotShowPriceIfProductIsDiscontinued = Model.Item.GetBoolean("DoNotShowPriceIfProductIsDiscontinued"); 32 var isDiscontinued = productIsDiscontinued && doNotShowPriceIfProductIsDiscontinued; 33 } 34 @if (!hidePrice && product != null && product.Id != null && !isDiscontinued) 35 { 36 bool showInformativePrice = Model.Item.GetBoolean("ShowInformativePrice"); 37 string unitId = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.Form.Get("UnitId")) ? Dynamicweb.Context.Current.Request.Form.Get("UnitId") : string.Empty; 38 39 string priceFontSize = Model.Item.GetRawValueString("PriceSize", "fs-2"); 40 int priceFontSizeNumber = int.Parse(string.Concat(priceFontSize.Where(Char.IsDigit))); 41 string priceTextFontSize = "fs-" + (priceFontSizeNumber + 2).ToString(); 42 string badgeFontSize = "fs-" + (priceFontSizeNumber > 3 ? priceFontSizeNumber - 2 : 1).ToString(); 43 44 string horizontalAlign = Model.Item.GetRawValueString("HorizontalAlignment", ""); 45 string layout = Model.Item.GetRawValueString("Layout", "horizontal"); 46 string textAlign = horizontalAlign == "center" ? "text-center" : string.Empty; 47 textAlign = horizontalAlign == "end" ? "text-end" : textAlign; 48 49 horizontalAlign = horizontalAlign == "center" && layout == "horizontal" ? "justify-content-center" : horizontalAlign; 50 horizontalAlign = horizontalAlign == "end" && layout == "horizontal" ? "justify-content-end" : horizontalAlign; 51 horizontalAlign = horizontalAlign == "center" && layout == "vertical" ? "align-items-center" : horizontalAlign; 52 horizontalAlign = horizontalAlign == "end" && layout == "vertical" ? "align-items-end" : horizontalAlign; 53 54 string flexDirection = layout == "horizontal" ? string.Empty : "flex-column"; 55 string flexGap = layout == "horizontal" ? "gap-3" : "gap-2"; 56 string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("Theme")) ? "theme " + Model.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : ""; 57 theme = GetViewParameter("theme") != null ? GetViewParameterString("theme") : theme; 58 59 string contentPadding = Model.Item.GetRawValueString("ContentPadding", ""); 60 contentPadding = contentPadding == "none" ? "p-0" : contentPadding; 61 contentPadding = contentPadding == "small" ? "p-1 px-md-2 py-md-1" : contentPadding; 62 contentPadding = contentPadding == "large" ? "p-2 px-md-3 py-md-2" : contentPadding; 63 64 var user = Dynamicweb.Security.UserManagement.User.GetCurrentFrontendUser(); 65 66 string showPricesWithVat = Pageview.Area.EcomPricesWithVat.ToLower(); 67 bool neverShowVat = string.IsNullOrEmpty(showPricesWithVat); 68 69 string priceMin; 70 string priceMax; 71 double minQty = (product.PurchaseMinimumQuantity ?? 1) == 0 ? 1 : (double)product.PurchaseMinimumQuantity; 72 73 string liveInfoClass = ""; 74 string productInfoFeed = ""; 75 76 List<SalesAgreement> salesAgreements = SalesAgreementHelper.GetSalesAgreements(); 77 List<string> ItemNumbers = new List<string>(); 78 bool containsSaleAgreement = false; 79 80 foreach (SalesAgreement salesAgreement in salesAgreements) 81 { 82 foreach (SalesAgreementLine item in salesAgreement.Items) 83 { 84 ItemNumbers.Add(item.ItemNumber); 85 } 86 } 87 if (ItemNumbers.Contains(product.Number)) 88 { 89 containsSaleAgreement = true; 90 } 91 92 bool isLazyLoadingForProductInfoEnabled = Dynamicweb.Core.Converter.ToBoolean(Dynamicweb.Context.Current.Items["IsLazyLoadingForProductInfoEnabled"]); 93 if (isLazyLoadingForProductInfoEnabled) 94 { 95 if (Dynamicweb.Context.Current.Items.Contains("ProductInfoFeed")) 96 { 97 productInfoFeed = Dynamicweb.Context.Current.Items["ProductInfoFeed"]?.ToString(); 98 if (!string.IsNullOrEmpty(productInfoFeed)) 99 { 100 productInfoFeed = $"data-product-info-feed=\"{productInfoFeed}\""; 101 } 102 } 103 liveInfoClass = "js-live-info"; 104 } 105 106 <div class="@textAlign @liveInfoClass item_@Model.Item.SystemName.ToLower()" data-product-id="@product.Id" data-variant-id="@product.VariantId" @productInfoFeed> 107 @if (product.Price.Price == 0) 108 { 109 <div class="@priceFontSize m-0 d-flex @flexDirection @flexGap @horizontalAlign @theme justify-content-end" itemprop="offers" itemscope itemtype="http://schema.org/Offer"> 110 <span itemprop="priceCurrency" content="@product.Price.CurrencyCode" class="d-none"></span> 111 <span class="@theme @contentPadding"> 112 <span class="text-price">@Translate("Unknown Price")</span> 113 </span> 114 </div> 115 } 116 else if (containsSaleAgreement == true) 117 { 118 <div class="@priceFontSize m-0 d-flex @flexDirection @flexGap @horizontalAlign @theme justify-content-end" itemprop="offers" itemscope itemtype="http://schema.org/Offer"> 119 <span itemprop="priceCurrency" content="@product.Price.CurrencyCode" class="d-none"></span> 120 <span class="@theme @contentPadding"> 121 <span class="text-price">@Translate("Price for sales agreement")</span> 122 </span> 123 </div> 124 } 125 else 126 { 127 128 if (showInformativePrice && product.PriceInformative.Price != 0) 129 { 130 <div class="opacity-50"> 131 <span>@Translate("RRP") </span> 132 <span class="text-decoration-line-through text-price">@product.PriceInformative.PriceFormatted</span> 133 </div> 134 } 135 136 137 <div class="@priceTextFontSize m-0 d-flex @flexDirection @flexGap @horizontalAlign @theme justify-content-end" itemprop="offers" itemscope itemtype="https://schema.org/Offer"> 138 <span itemprop="priceCurrency" content="@product.Price.CurrencyCode" class="d-none"></span> 139 140 @* Price *@ 141 @if (showPricesWithVat == "false" && !neverShowVat) 142 { 143 if (isLazyLoadingForProductInfoEnabled && !Pageview.IsVisualEditorMode) 144 { 145 <span itemprop="price" content="" class="d-none"></span> 146 <span class="text-decoration-line-through js-text-decoration-line-through opacity-75 me-3 text-price js-text-price d-none" data-show-if="LiveProductInfo.product.Price.Price != LiveProductInfo.product.PriceBeforeDiscount.Price"></span> 147 148 } 149 else 150 { 151 string beforePrice = !string.IsNullOrEmpty(unitId) ? product.GetPrice(unitId).PriceBeforeDiscount.PriceWithoutVatFormatted : product.PriceBeforeDiscount.PriceWithoutVatFormatted; 152 string standardPrice = !string.IsNullOrEmpty(unitId) ? product.PriceInformative.PriceWithoutVatFormatted : product.PriceInformative.PriceWithoutVatFormatted; 153 <span itemprop="price" content="@product.Price.PriceWithoutVat" class="d-none"></span> 154 155 <div class="order-1 @contentPadding"> 156 <div class="PersonalPriceToggle"> 157 <span class="custom-price"> 158 @Translate("Pris per") 1 @Translate("stk.") 159 </span> 160 <span class="custom-price @priceFontSize ">@beforePrice</span> 161 <span class="custom-price">@Translate("ekskl. moms")</span> 162 @if (product.Price.Price == product.PriceBeforeDiscount.Price) 163 { 164 <span class="custom-price">@Translate("Mindstekøb:") @minQty @Translate("stk.")</span> 165 } 166 </div> 167 168 <div class="StandardPriceToggle" hidden> 169 @if (!string.IsNullOrWhiteSpace(standardPrice)) 170 { 171 <span class="custom-price"> 172 @Translate("Pris per") 1 @Translate("stk.") 173 </span> 174 <span class="custom-price @priceFontSize">@standardPrice</span> 175 <span class="custom-price">@Translate("ekskl. moms")</span> 176 if (product.Price.Price == product.PriceBeforeDiscount.Price) 177 { 178 <span class="custom-price">@Translate("Mindstekøb:") @minQty @Translate("stk.")</span> 179 } 180 } 181 else 182 { 183 <div class="@priceFontSize m-0 d-flex @flexDirection @flexGap @horizontalAlign @theme justify-content-end" itemprop="offers" itemscope itemtype="http://schema.org/Offer"> 184 <span itemprop="priceCurrency" content="@product.Price.CurrencyCode" class="d-none"></span> 185 <span class="@theme @contentPadding"> 186 <span class="text-price">@Translate("Unknown Price")</span> 187 </span> 188 </div> 189 } 190 </div> 191 </div> 192 } 193 } 194 else 195 { 196 if (isLazyLoadingForProductInfoEnabled && !Pageview.IsVisualEditorMode) 197 { 198 <span itemprop="price" content="" class="d-none"></span> 199 <span class="text-decoration-line-through js-text-decoration-line-through opacity-75 me-3 text-price js-text-price d-none" data-show-if="LiveProductInfo.product.Price.Price != LiveProductInfo.product.PriceBeforeDiscount.Price"></span> 200 } 201 else 202 { 203 string beforePrice = !string.IsNullOrEmpty(unitId) ? product.GetPrice(unitId).PriceBeforeDiscount.PriceWithVatFormatted : product.PriceBeforeDiscount.PriceWithVatFormatted; 204 string standardPrice = !string.IsNullOrEmpty(unitId) ? product.PriceInformative.PriceWithVatFormatted : product.PriceInformative.PriceWithVatFormatted; 205 <span itemprop="price" content="@product.Price.PriceWithVat" class="d-none"></span> 206 207 <div class="order-1 @contentPadding "> 208 <div class="PersonalPriceToggle"> 209 <span class="custom-price"> 210 @Translate("Pris per") 1 @Translate("stk.") 211 </span> 212 <span class="custom-price @priceFontSize ">@beforePrice</span> 213 <span class="custom-price">@Translate("inkl. moms")</span> 214 @if (product.Price.Price == product.PriceBeforeDiscount.Price) 215 { 216 <span class="custom-price">@Translate("Mindstekøb:") @minQty @Translate("stk.")</span> 217 } 218 </div> 219 220 <div class="StandardPriceToggle" hidden> 221 @if (!string.IsNullOrWhiteSpace(standardPrice)) 222 { 223 <span class="custom-price"> 224 @Translate("Pris per") 1 @Translate("stk.") 225 </span> 226 <span class="custom-price @priceFontSize">@standardPrice</span> 227 <span class="custom-price">@Translate("ekskl. moms")</span> 228 if (product.Price.Price == product.PriceBeforeDiscount.Price) 229 { 230 <span class="custom-price">@Translate("Mindstekøb:") @minQty @Translate("stk.")</span> 231 } 232 } 233 else 234 { 235 <div class="@priceFontSize m-0 d-flex @flexDirection @flexGap @horizontalAlign @theme justify-content-end" itemprop="offers" itemscope itemtype="http://schema.org/Offer"> 236 <span itemprop="priceCurrency" content="@product.Price.CurrencyCode" class="d-none"></span> 237 <span class="@theme @contentPadding"> 238 <span class="text-price">@Translate("Unknown Price")</span> 239 </span> 240 </div> 241 242 } 243 </div> 244 </div> 245 } 246 } 247 248 @* Total price *@ 249 @if (product.Price.Price != product.PriceBeforeDiscount.Price) 250 { 251 if (showPricesWithVat == "false" && !neverShowVat) 252 { 253 if (isLazyLoadingForProductInfoEnabled && !Pageview.IsVisualEditorMode) 254 { 255 <span class="text-price js-text-price"> 256 <span class="spinner-border" role="status"></span> 257 </span> 258 } 259 else 260 { 261 string price = !string.IsNullOrEmpty(unitId) ? product.GetPrice(unitId).Price.PriceWithoutVatFormatted : product.Price.PriceWithoutVatFormatted; 262 263 var badgeParms = new Dictionary<string, object>(); 264 badgeParms.Add("saleBadgeType", Model.Item.GetRawValue("SaleBadgeType")); 265 badgeParms.Add("saleBadgeCssClassName", Model.Item.GetRawValue("SaleBadgeDesign")); 266 badgeParms.Add("newBadgeCssClassName", Model.Item.GetRawValue("NewBadgeDesign")); 267 badgeParms.Add("newPublicationDays", Model.Item.GetInt32("NewPublicationDays")); 268 badgeParms.Add("campaignBadgesValues", Model.Item.GetRawValueString("CampaignBadges")); 269 270 if (product?.VariantInfo?.VariantInfo != null) 271 { 272 priceMin = product?.VariantInfo?.PriceMin?.PriceWithoutVatFormatted != null ? product.VariantInfo.PriceMin.PriceWithoutVatFormatted : "0"; 273 priceMax = product?.VariantInfo?.PriceMax?.PriceWithoutVatFormatted != null ? product.VariantInfo.PriceMax.PriceWithoutVatFormatted : "0"; 274 if (priceMin != priceMax) 275 { 276 price = priceMin + " - " + priceMax; 277 } 278 } 279 280 <div class="order-2 @contentPadding DiscountWithBadgeToggle"> 281 @if (layout == "horizontal") 282 { 283 284 <span class="custom-price">@Translate("Rabat")</span> 285 <span class="custom-price @priceFontSize">@RenderPartial("Components/EcommerceBadge_Custom.cshtml", product, badgeParms)</span> 286 } 287 else 288 { 289 <span class="custom-price @priceFontSize">@Translate("Rabat")@RenderPartial("Components/EcommerceBadge_Custom.cshtml", product, badgeParms)</span> 290 } 291 </div> 292 <div class="order-3 @contentPadding TotalPriceToggle"> 293 <span class="custom-price"><br></span> 294 <span class="custom-price @priceFontSize fw-bold"> @price</span> 295 <span class="custom-price">@Translate("ekskl. moms")</span> 296 <span class="custom-price">@Translate("Mindstekøb:") @minQty @Translate("stk.")</span> 297 </div> 298 } 299 } 300 else 301 { 302 if (isLazyLoadingForProductInfoEnabled && !Pageview.IsVisualEditorMode) 303 { 304 <span class="text-price js-text-price"> 305 <span class="spinner-border" role="status"></span> 306 </span> 307 } 308 else 309 { 310 string price = !string.IsNullOrEmpty(unitId) ? product.GetPrice(unitId).Price.PriceWithVatFormatted : product.Price.PriceWithVatFormatted; 311 312 var badgeParms = new Dictionary<string, object>(); 313 badgeParms.Add("saleBadgeType", Model.Item.GetRawValue("SaleBadgeType")); 314 badgeParms.Add("saleBadgeCssClassName", Model.Item.GetRawValue("SaleBadgeDesign")); 315 badgeParms.Add("newBadgeCssClassName", Model.Item.GetRawValue("NewBadgeDesign")); 316 badgeParms.Add("newPublicationDays", Model.Item.GetInt32("NewPublicationDays")); 317 badgeParms.Add("campaignBadgesValues", Model.Item.GetRawValueString("CampaignBadges")); 318 319 if (product?.VariantInfo?.VariantInfo != null) 320 { 321 priceMin = product?.VariantInfo?.PriceMin?.PriceWithVatFormatted != null ? product.VariantInfo.PriceMin.PriceWithVatFormatted : "0"; 322 priceMax = product?.VariantInfo?.PriceMax?.PriceWithVatFormatted != null ? product.VariantInfo.PriceMax.PriceWithVatFormatted : "0"; 323 if (priceMin != priceMax) 324 { 325 price = priceMin + " - " + priceMax; 326 } 327 } 328 329 if (product.Price.Price != product.PriceBeforeDiscount.Price) 330 { 331 <div class="order-2 @contentPadding DiscountWithBadgeToggle"> 332 @if (layout == "horizontal") 333 { 334 335 <span class="custom-price">@Translate("Rabat")</span> 336 <span class="custom-price @priceFontSize">@RenderPartial("Components/EcommerceBadge_Custom.cshtml", product, badgeParms)</span> 337 } 338 else 339 { 340 <span class="custom-price @priceFontSize">@Translate("Rabat")@RenderPartial("Components/EcommerceBadge_Custom.cshtml", product, badgeParms)</span> 341 } 342 </div> 343 } 344 <div class="order-3 @contentPadding TotalPriceToggle"> 345 <span class="custom-price"><br /></span> 346 <span class="custom-price @priceFontSize fw-bolder">@price</span> 347 <span class="custom-price">@Translate("inkl. moms")</span> 348 <span class="custom-price">@Translate("Mindstekøb:") @minQty @Translate("stk.")</span> 349 </div> 350 } 351 } 352 } 353 @*</div>*@ 354 @* Stock state for Schema.org, start *@ 355 @{ 356 Uri url = Dynamicweb.Context.Current.Request.Url; 357 } 358 359 <link itemprop="url" href="@url"> 360 361 @{ 362 bool IsNeverOutOfStock = product.NeverOutOfstock; 363 } 364 365 @if (IsNeverOutOfStock) 366 { 367 <span itemprop="availability" class="d-none">@Translate("Available in stock")</span> 368 } 369 else 370 { 371 if (product.StockLevel > 0) 372 { 373 <span itemprop="availability" class="d-none">InStock</span> 374 } 375 else 376 { 377 <span itemprop="availability" class="d-none">OutOfStock</span> 378 } 379 } 380 @* Stock state for Schema.org, stop *@ 381 382 </div> 383 384 //Outcommented do to not want to show prices including VAT 385 @*if (showPricesWithVat == "false" && !neverShowVat) 386 { 387 if (isLazyLoadingForProductInfoEnabled && !Pageview.IsVisualEditorMode) 388 { 389 <small class="opacity-85 fst-normal js-text-price-with-vat d-none" data-suffix="@Translate("Incl. VAT")"></small> 390 } 391 else 392 { 393 string price = !string.IsNullOrEmpty(unitId) ? product.GetPrice(unitId).Price.PriceWithVatFormatted : product.Price.PriceWithVatFormatted; 394 395 if (product?.VariantInfo?.VariantInfo != null) 396 { 397 priceMin = product?.VariantInfo?.PriceMin?.PriceWithVatFormatted != null ? product.VariantInfo.PriceMin.PriceWithVatFormatted : ""; 398 priceMax = product?.VariantInfo?.PriceMax?.PriceWithVatFormatted != null ? product.VariantInfo.PriceMax.PriceWithVatFormatted : ""; 399 } 400 if (priceMin != priceMax) 401 { 402 price = priceMin + " - " + priceMax; 403 } 404 <small class="opacity-85 fst-normal">@price @Translate("Incl. VAT")</small> 405 } 406 }*@ 407 } 408 </div> 409 } 410 else if (Pageview.IsVisualEditorMode) 411 { 412 <div class="alert alert-dark m-0" role="alert"> 413 <span>@Translate("No products available")</span> 414 </div> 415 } 416
Error executing template "Designs/Swift/Paragraph/Swift_ProductAddToCart.cshtml"
System.Data.SqlClient.SqlException (0x80131904): Transaction (Process ID 87) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
   at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
   at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
   at System.Data.SqlClient.SqlDataReader.TryHasMoreRows(Boolean& moreRows)
   at System.Data.SqlClient.SqlDataReader.TryReadInternal(Boolean setTimeout, Boolean& more)
   at System.Data.SqlClient.SqlDataReader.Read()
   at Dynamicweb.Ecommerce.Products.ProductRepository.Dynamicweb.Ecommerce.Products.IProductRepository.GetProductKeysByGroupId(String groupId, Boolean useOrderBy, Boolean includeVariants, String productLanguageId, Boolean doRefactoring, Boolean useAssortments)
   at Dynamicweb.Ecommerce.Orders.Discounts.Discount.ProcessProductSelections(HashSet`1& productKeys, HashSet`1& includedQueries, HashSet`1& excludedQueries)
   at Dynamicweb.Ecommerce.Orders.Discounts.Discount.GetRelevantProductKeys()
   at Dynamicweb.Ecommerce.Orders.Discounts.DiscountService.StatelessSetLookup(Discount discount, ConcurrentDictionary`2 lookup)
   at Dynamicweb.Ecommerce.Orders.Discounts.DiscountService.InitializeLookup()
   at System.Lazy`1.CreateValue()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Lazy`1.get_Value()
   at Dynamicweb.Ecommerce.Orders.Discounts.DiscountService.GetDiscounts(DiscountApplyType[] discountTypes, String[] productKeys, User user)
   at Dynamicweb.Ecommerce.Orders.Discounts.DiscountInfoCollection.LoadDiscounts()
   at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.GetDiscountInfo(PriceViewModelSettings settings, Product product)
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.LazyInitValue()
   at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.<>c__DisplayClass3_2.<BulkCreateView>b__46()
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.LazyInitValue()
   at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.<>c__DisplayClass3_2.<BulkCreateView>b__48()
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.LazyInitValue()
   at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.GetPrice(PriceViewModelSettings settings, IList`1 products, Boolean& pricesHasBeenPrepared, Object lock, Lazy`1 priceInfo)
   at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.<>c__DisplayClass3_2.<BulkCreateView>b__49()
   at System.Lazy`1.CreateValue()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Lazy`1.get_Value()
   at CompiledRazorTemplates.Dynamic.RazorEngine_bfc1f2f0ba854075ba1faf5918511431.Execute() in D:\dynamicweb.net\Solutions\brdklee.cloud.dynamicweb-cms.com\files\Templates\Designs\Swift\Paragraph\Swift_ProductAddToCart.cshtml:line 104
   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()
ClientConnectionId:fef7765e-6e46-4ec9-ae86-c26a77b01d5e
Error Number:1205,State:52,Class:13

1 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.ParagraphViewModel> 2 @using Dynamicweb.Ecommerce.ProductCatalog 3 @using Dynamicweb.Core.Encoders 4 @using Dynamicweb.Ecommerce.CustomerExperienceCenter.Favorites 5 6 7 @{ 8 ProductViewModel product = null; 9 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails")) 10 { 11 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"]; 12 } 13 else if (Pageview.Page.Item["DummyProduct"] != null && Pageview.IsVisualEditorMode) 14 { 15 var pageViewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(Pageview.Page); 16 ProductListViewModel productList = pageViewModel.Item.GetValue("DummyProduct") != null ? pageViewModel.Item.GetValue("DummyProduct") as ProductListViewModel : new ProductListViewModel(); 17 18 if (productList?.Products is object) 19 { 20 product = productList.Products[0]; 21 } 22 } 23 24 string anonymousUsersLimitations = Pageview.AreaSettings.GetRawValueString("AnonymousUsers", ""); 25 bool anonymousUser = Pageview.User == null; 26 bool isErpConnectionDown = !Dynamicweb.Core.Converter.ToBoolean(Dynamicweb.Context.Current.Items["IsWebServiceConnectionAvailable"]); 27 bool hideAddToCart = anonymousUsersLimitations.Contains("cart") && anonymousUser || Pageview.AreaSettings.GetBoolean("ErpDownHideAddToCart") && isErpConnectionDown; 28 hideAddToCart = Pageview.IsVisualEditorMode ? false : hideAddToCart; 29 } 30 31 @if (product is object && !hideAddToCart) { 32 string horizontalAlign = Model.Item.GetRawValueString("HorizontalAlignment", ""); 33 horizontalAlign = horizontalAlign == "center" ? "justify-content-center" : horizontalAlign; 34 horizontalAlign = horizontalAlign == "end" ? "justify-content-end" : horizontalAlign; 35 horizontalAlign = horizontalAlign == "full" ? "" : horizontalAlign; 36 37 bool favoritesSelector = !string.IsNullOrEmpty(Model.Item.GetString("ShowAddToFavorites")) ? Model.Item.GetBoolean("ShowAddToFavorites") : false; 38 bool quantitySelector = !string.IsNullOrEmpty(Model.Item.GetString("ShowQuantitySelector")) ? Model.Item.GetBoolean("ShowQuantitySelector") : false; 39 bool unitsSelector = !string.IsNullOrEmpty(Model.Item.GetString("ShowUnitsSelector")) ? Model.Item.GetBoolean("ShowUnitsSelector") : false; 40 bool hideInventory = !string.IsNullOrEmpty(Model.Item.GetString("HideInventory")) ? Model.Item.GetBoolean("HideInventory") : false; 41 bool hideStockState = !string.IsNullOrEmpty(Model.Item.GetString("HideStockState")) ? Model.Item.GetBoolean("HideStockState") : false; 42 43 string buttonSize = Model.Item.GetRawValueString("ButtonSize", "regular"); 44 string inputSize = string.Empty; 45 46 switch (buttonSize) 47 { 48 case "small": 49 inputSize = " input-group-sm"; 50 buttonSize = " btn-sm"; 51 break; 52 case "regular": 53 buttonSize = string.Empty; 54 break; 55 case "large": 56 inputSize = " input-group-lg"; 57 buttonSize = " btn-lg"; 58 break; 59 } 60 61 string iconPath = "/Files/icons/"; 62 string url = "/Default.aspx?ID=" + (GetPageIdByNavigationTag("CartService")); 63 if (!url.Contains("LayoutTemplate")) 64 { 65 url += url.Contains("?") ? "&LayoutTemplate=Swift_MiniCart.cshtml" : "?LayoutTemplate=Swift_MiniCart.cshtml"; 66 } 67 68 bool isLazyLoadingForProductInfoEnabled = Dynamicweb.Core.Converter.ToBoolean(Dynamicweb.Context.Current.Items["IsLazyLoadingForProductInfoEnabled"]); 69 string disableAddToCart = (product.StockLevel <= 0) ? "disabled" : ""; 70 bool isNeverOutOfStock = product.NeverOutOfstock; 71 disableAddToCart = isNeverOutOfStock && !isLazyLoadingForProductInfoEnabled ? "" : disableAddToCart; 72 73 string whenVariantsExist = Model.Item.GetRawValueString("WhenVariantsExist", "hide"); 74 75 string flexFill = Model.Item.GetRawValueString("HorizontalAlignment", "") == "full" ? "flex-fill" : ""; 76 string fullWidth = Model.Item.GetRawValueString("HorizontalAlignment", "") == "full" ? "w-100" : ""; 77 string addToCartIcon = Model.Item.GetRawValueString("Icon", iconPath + "shopping-cart.svg"); 78 string addToCartLabel = !addToCartIcon.Contains("_none") ? $"<span class=\"icon-2\">{ReadFile(addToCartIcon)}</span>" : ""; 79 addToCartLabel += !addToCartIcon.Contains("_none") && !Model.Item.GetBoolean("HideButtonText") ? " " : ""; 80 addToCartLabel += !Model.Item.GetBoolean("HideButtonText") ? $"<span class=\"d-none d-md-inline\">{Translate("Add to cart")}</span><span class=\"d-inline d-md-none\">{Translate("Add")}</span>" : ""; 81 82 if (product.VariantInfo.VariantInfo == null || whenVariantsExist == "disable") { 83 string unitId = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.Form.Get("UnitId")) ? Dynamicweb.Context.Current.Request.Form.Get("UnitId") : product.DefaultUnitId; 84 if (string.IsNullOrEmpty(unitId) && product?.UnitOptions != null) { 85 if (product.UnitOptions.FirstOrDefault<UnitOptionViewModel>() != null) { 86 unitId = product.UnitOptions.FirstOrDefault<UnitOptionViewModel>().Id; 87 } 88 } 89 90 string minQty = product.PurchaseMinimumQuantity != 1 ? $"min=\"{product.PurchaseMinimumQuantity.ToString()}\"" : "min=\"1\""; 91 string stepQty = product.PurchaseQuantityStep > 1 ? product.PurchaseQuantityStep.ToString() : "1"; 92 string valueQty = product.PurchaseMinimumQuantity > product.PurchaseQuantityStep ? product.PurchaseMinimumQuantity.ToString() : stepQty; 93 disableAddToCart = product.VariantInfo.VariantInfo != null && string.IsNullOrEmpty(product.VariantId) ? "disabled" : disableAddToCart; 94 disableAddToCart = product.Discontinued ? "disabled" : disableAddToCart; 95 96 var reserveMode = Dynamicweb.Ecommerce.Frontend.Cart.ProductReserve.Mode; 97 98 if (unitsSelector && product.UnitOptions.Count > 0) { 99 <form method="post" action="/Default.aspx?ID=@(Pageview.Page.ID)&ProductId=@product.Id" id="UnitSelectorForm_@(product.Id)_@(product.VariantId)_@Model.ID"> 100 <input type="hidden" name="redirect" value="false"> 101 <input type="hidden" name="VariantID" value="@product.VariantId"> 102 <input type="hidden" name="UnitID" class="js-unit-id" value="@unitId"> 103 </form> 104 } 105 106 <div class="d-flex @horizontalAlign @fullWidth js-input-group item_@Model.Item.SystemName.ToLower()"> 107 <form method="post" action="@url" class="@fullWidth" style="z-index: 1"> 108 <input type="hidden" name="redirect" value="false"> 109 <input type="hidden" name="ProductId" value="@product.Id"> 110 <input type="hidden" name="ProductName" value="@HtmlEncoder.HtmlEncode(product.Name)"> 111 <input type="hidden" name="ProductVariantName" value="@product.VariantName"> 112 <input type="hidden" name="ProductCurrency" value="@Dynamicweb.Ecommerce.Common.Context.Currency.Code"> 113 <input type="hidden" name="ProductPrice" value="@PriceViewModelExtensions.ToStringInvariant(product.Price)"> 114 <input type="hidden" name="ProductReferer" value="component_ProductAddToCart"> 115 <input type="hidden" name="cartcmd" value="add"> 116 117 @if (reserveMode == Dynamicweb.Ecommerce.Frontend.Cart.ProductReserveMode.AddToCart) 118 { 119 <input type="hidden" name="GetReservedAmount" value="true"> 120 } 121 122 @if (!string.IsNullOrEmpty(product.VariantId)) 123 { 124 <input type="hidden" name="VariantId" value="@product.VariantId"> 125 } 126 127 @if (!product.NeverOutOfstock) 128 { 129 <input type="hidden" name="Stock" value="@product.StockLevel"> 130 131 <template class="js-out-of-stock-notice"> 132 <div class="modal-header"> 133 <h1 class="modal-title fs-5">@Translate("Stock limit")</h1> 134 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> 135 </div> 136 <div class="modal-body"> 137 @Translate("There are not enough products in stock. The product might be sold out or discontinued. Please adjust the quantity.") 138 </div> 139 </template> 140 } 141 142 @if (stepQty != "1") 143 { 144 <template class="js-step-quantity-warning"> 145 <div class="modal-header"> 146 <h1 class="modal-title fs-5">@Translate("The quantity is not valid")</h1> 147 </div> 148 <div class="modal-body"> 149 @Translate("Please select a quantity that is dividable by") @stepQty 150 </div> 151 </template> 152 } 153 @if (product.PurchaseMinimumQuantity != 1) 154 { 155 <template class="js-min-quantity-warning"> 156 <div class="modal-header"> 157 <h1 class="modal-title fs-5">@Translate("The product could not be added to the cart")</h1> 158 </div> 159 <div class="modal-body"> 160 @Translate("The quantity is not valid. You must buy at least") @product.PurchaseMinimumQuantity 161 </div> 162 </template> 163 } 164 165 @if (quantitySelector || (!anonymousUser && product.VariantInfo.VariantInfo != null) || (!anonymousUser && favoritesSelector)) 166 { 167 <input type="hidden" id="Unit_@(product.Id)_@product.VariantId" name="UnitID" value="@unitId" /> 168 } 169 170 <div class="d-flex flex-row w-100"> 171 @if (!quantitySelector) 172 { 173 <input id="Quantity_@(product.Id)_@product.VariantId" class="swift_quantity_field" name="Quantity" value="@valueQty" type="hidden" @disableAddToCart> 174 } 175 176 @if (unitsSelector && product.UnitOptions.Count > 0) 177 { 178 string selectedUnitName = !string.IsNullOrEmpty(unitId) && product?.UnitOptions != null ? unitId : product.UnitOptions.FirstOrDefault<UnitOptionViewModel>().Name; 179 180 foreach (var unitOption in product.UnitOptions) 181 { 182 if (unitOption.Id == unitId) 183 { 184 selectedUnitName = unitOption.Name; 185 } 186 } 187 188 <div class="d-flex flex-column gap-2 w-100"> 189 <div class="input-group input-primary-button-group flex-nowrap@(inputSize)"> 190 @if (!anonymousUser && favoritesSelector) 191 { 192 @RenderPartial("Components/ToggleFavorite.cshtml", product) 193 } 194 195 @if (quantitySelector) 196 { 197 <input id="Quantity_@(product.Id)_@product.VariantId" name="Quantity" value="@valueQty" step="@stepQty" @minQty class="form-control swift_quantity-field" style="min-width: 60px; max-width: 100px; z-index: 1" type="number" onchange="swift.Cart.UpdateOnEnterKey(event)" onkeyup="swift.Cart.UpdateOnEnterKey(event)" @disableAddToCart> 198 } 199 200 <button class="btn btn-secondary @flexFill dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false"> 201 @selectedUnitName 202 </button> 203 204 <ul class="dropdown-menu swift_unit-field"> 205 @foreach (var unitOption in product.UnitOptions) 206 { 207 var selectedUnit = unitOption.Id == unitId ? "selected" : ""; 208 209 <li> 210 <button type="button" class="btn dropdown-item" data-value="@unitOption.Id" onclick="document.querySelector('#UnitSelectorForm_@(product.Id)_@(product.VariantId)_@Model.ID').querySelector('.js-unit-id').value = this.getAttribute('data-value'); 211 document.querySelector('#Unit_@(product.Id)_@product.VariantId').value = this.getAttribute('data-value'); 212 swift.PageUpdater.Update(document.querySelector('#UnitSelectorForm_@(product.Id)_@(product.VariantId)_@Model.ID'))"> 213 <span>@unitOption.Name</span> 214 <span> 215 @if (unitOption.StockLevel > 0) 216 { 217 if (!Model.Item.GetBoolean("HideInventory")) 218 { 219 <span class="small text-success">@unitOption.StockLevel @Translate("In stock")</span> 220 } 221 else 222 { 223 <span class="small text-success">@Translate("In stock")</span> 224 } 225 } 226 else 227 { 228 <span class="small text-danger">@Translate("Out of Stock")</span> 229 } 230 </span> 231 </button> 232 </li> 233 } 234 </ul> 235 </div> 236 <button type="button" onclick="swift.Cart.Update(event)" class="btn btn-primary @(buttonSize) js-add-to-cart-button" style="white-space: nowrap" @disableAddToCart title="@Translate("Add to cart")" id="AddToCartButton@(product.Id)_@Pageview.CurrentParagraph.ID"> 237 @if (!Model.Item.GetBoolean("HideButtonText")) 238 { 239 <span class="text-nowrap d-flex align-items-center justify-content-center gap-2"> 240 @addToCartLabel 241 </span> 242 } 243 else 244 { 245 @addToCartLabel 246 } 247 </button> 248 </div> 249 } 250 else 251 { 252 if (!anonymousUser && favoritesSelector) 253 { 254 @RenderPartial("Components/ToggleFavorite.cshtml", product) 255 } 256 257 <div class="input-group input-primary-button-group flex-nowrap@(inputSize)"> 258 @if (quantitySelector) 259 { 260 <input id="Quantity_@(product.Id)_@product.VariantId" name="Quantity" value="@valueQty" step="@stepQty" @minQty class="form-control swift_quantity-field" style="min-width: 60px; max-width: 100px; z-index: 1" type="number" onchange="swift.Cart.UpdateOnEnterKey(event)" onkeyup="swift.Cart.UpdateOnEnterKey(event)" @disableAddToCart> 261 } 262 263 <button type="button" onclick="swift.Cart.Update(event)" class="btn btn-primary @(buttonSize) @flexFill js-add-to-cart-button" style="white-space: nowrap" @disableAddToCart title="@Translate("Add to cart")" id="AddToCartButton@(product.Id)_@Pageview.CurrentParagraph.ID"> 264 @if (!Model.Item.GetBoolean("HideButtonText")) 265 { 266 <span class="text-nowrap d-flex align-items-center justify-content-center gap-2"> 267 @addToCartLabel 268 </span> 269 } 270 else 271 { 272 @addToCartLabel 273 } 274 </button> 275 </div> 276 } 277 </div> 278 </form> 279 </div> 280 } else if (whenVariantsExist == "modal") { 281 string buttonText = Translate("Select"); 282 string variantId = !string.IsNullOrWhiteSpace(product.VariantId) ? product.VariantId : product.DefaultVariantId; 283 284 string variantSelectorServicePageId = !string.IsNullOrEmpty(Model.Item.GetString("VariantSelectorServicePageId")) ? Model.Item.GetLink("VariantSelectorServicePageId").PageId.ToString() : ""; 285 variantSelectorServicePageId = variantSelectorServicePageId != "" ? variantSelectorServicePageId : GetPageIdByNavigationTag("VariantSelectorService").ToString(); 286 287 <div class="d-flex @horizontalAlign w-100 item_@Model.Item.SystemName.ToLower()"> 288 @if (!anonymousUser && favoritesSelector) 289 { 290 @RenderPartial("Components/ToggleFavorite.cshtml", product) 291 } 292 <form action="/Default.aspx?ID=@variantSelectorServicePageId" data-response-target-element="DynamicModalContent" data-preloader="inline" style="z-index: 1" class="@fullWidth"> 293 <input type="hidden" name="ProductID" value="@product.Id"> 294 <input type="hidden" name="VariantID" value="@variantId"> 295 <input type="hidden" name="QuantitySelector" value="@quantitySelector.ToString()"> 296 <input type="hidden" name="HideInventory" value="@hideInventory.ToString()"> 297 <input type="hidden" name="HideStockState" value="@hideStockState.ToString()"> 298 <input type="hidden" name="VariantSelectorServicePage" value="@variantSelectorServicePageId"> 299 <input type="hidden" name="ViewType" value="ModalContent"> 300 @if (isLazyLoadingForProductInfoEnabled) 301 { 302 @* If lazy loading is enabled, bypass it because we're loading a modal window, so render everything as if it was server-side *@ 303 <input type="hidden" name="getproductinfo" value="true"> 304 } 305 <button type="button" onclick="swift.PageUpdater.Update(event)" class="btn btn-primary@(buttonSize) @fullWidth" title="@Translate("Select")" data-bs-toggle="modal" data-bs-target="#DynamicModal" id="OpenVariantSelectorModal@(product.Id)_@Pageview.CurrentParagraph.ID">@buttonText</button> 306 </form> 307 </div> 308 } 309 } else if (Pageview.IsVisualEditorMode) { 310 <div class="alert alert-dark m-0">@Translate("No products available")</div> 311 } 312
HS-kode
85015220
Oprindelsesland
Kina
Vægt, kg
23,7
Kan bygges
Nej
Ved at klikke 'Acceptér Alle' så giver du til tilladelse til at vi må indsamle information om dig til forskellige formål, hvilket inkluderer: Funktionalitet, Statistik og Marketing