Error executing template "Designs/Swift/eCom/ProductCatalog/ProductViewDetail.cshtml" System.Data.SqlClient.SqlException (0x80131904): SHUTDOWN is in progress. Login failed for user 'danzafe.cloud.dynamicweb-cms.com'. Cannot continue the execution because the session is in the kill state. A severe error occurred on the current command. The results, if any, should be discarded. 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.TryConsumeMetaData() at System.Data.SqlClient.SqlDataReader.get_MetaData() at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString, Boolean isInternal, Boolean forDescribeParameterEncryption, Boolean shouldCacheForAlwaysEncrypted) at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, Boolean inRetry, SqlDataReader ds, Boolean describeParameterEncryptionRequest) at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry) at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method) at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method) at Dynamicweb.Data.Database.CreateDataReader(IDbCommand command, CommandBehavior behavior) at Dynamicweb.Data.Database.CreateDataReader(CommandBuilder commandBuilder, IDbConnection connection, IDbTransaction transaction, CommandBehavior behavior, Int32 commandTimeout) at Dynamicweb.Data.Database.CreateDataReader(CommandBuilder commandBuilder, IDbConnection connection, IDbTransaction transaction, Int32 commandTimeout) at Dynamicweb.Ecommerce.Products.DetailRepository.GetInheritedDetailsBulk(List`1 productIds, String detailType, Boolean onlyDefault) at Dynamicweb.Ecommerce.Products.DetailService.GetPrimaryDetailsBulk(IEnumerable`1 productKeys, String detailType) at System.Lazy`1.CreateValue() at System.Lazy`1.LazyInitValue() at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.GetDefaultImage(MediaViewModelSettings settings, String productId, String languageId, String variantId, Lazy`1 productImages, Lazy`1 details) at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.GetDefaultImage(MediaViewModelSettings settings, Product product, Lazy`1 productImages, Lazy`1 details) at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.<>c__DisplayClass3_2.<BulkCreateView>b__62() at System.Lazy`1.CreateValue() at System.Lazy`1.LazyInitValue() at CompiledRazorTemplates.Dynamic.RazorEngine_c54b4806f72d4133a3d93fbeefa4f304.Execute() in D:\dynamicweb.net\Solutions\Flex Media\danzafe.cloud.dynamicweb-cms.com\files\Templates\Designs\Swift\eCom\ProductCatalog\ProductViewDetail.cshtml:line 100 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:6d87c646-476d-4eb9-ae62-8078cd650a39 Error Number:6005,State:1,Class:14
1 @inherits ViewModelTemplate<ProductViewModel> 2 @using Dynamicweb.Rendering 3 @using Dynamicweb.Ecommerce.ProductCatalog 4 @using Dynamicweb.Core 5 @using Dynamicweb.Environment 6 @using System.Web 7 8 @{ 9 string metaDescription = string.IsNullOrEmpty(Model.MetaDescription) ? Model.Name : Model.MetaDescription; 10 string klaviyoID = Pageview.AreaSettings.GetString("KlaviyoPublicKey"); 11 12 string baseUrl = Dynamicweb.Context.Current.Request.Url.Scheme + "://" + Dynamicweb.Context.Current.Request.Url.Host; 13 14 15 16 Pageview.Meta.AddTag($"<meta property=\"og:image\" content=\"{Dynamicweb.Context.Current.Request.Url.Scheme}://{Dynamicweb.Context.Current.Request.Url.Host}{Model.DefaultImage.Value}\">"); 17 Pageview.Meta.AddTag($"<meta property=\"og:image:alt\" content=\"{Model.Name}\">"); 18 Pageview.Meta.AddTag($"<meta property=\"og:description\" content=\"{metaDescription}\">"); 19 20 Pageview.Meta.AddTag("twitter:image", Model.DefaultImage.Value); 21 Pageview.Meta.AddTag("twitter:image:alt", Model.Name); 22 Pageview.Meta.AddTag("twitter:description", metaDescription); 23 } 24 25 @{ 26 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails")) 27 { 28 Dynamicweb.Context.Current.Items["ProductDetails"] = Model; 29 } 30 else 31 { 32 Dynamicweb.Context.Current.Items.Add("ProductDetails", Model); 33 } 34 35 bool isLazyLoadingForProductInfoEnabled = Dynamicweb.Core.Converter.ToBoolean(Dynamicweb.Context.Current.Items["IsLazyLoadingForProductInfoEnabled"]); 36 if (isLazyLoadingForProductInfoEnabled) 37 { 38 string showPricesWithVat = Pageview.Area.EcomPricesWithVat.ToLower(); 39 bool neverShowVat = string.IsNullOrEmpty(showPricesWithVat); 40 bool hasVariantId = !string.IsNullOrEmpty(Model.VariantId); 41 string variantIdParam = hasVariantId ? $"/{Model.VariantId}" : ""; 42 string priceFilledProperties = $"Price,PriceFormatted{(showPricesWithVat == "false" && !neverShowVat ? ",PriceWithVat,PriceWithVatFormatted" : "")}"; 43 string productInfoFeed = $@"/dwapi/ecommerce/products/{Model.Id}{variantIdParam} 44 ?UserId={Converter.ToString(Pageview.User?.ID)} 45 &LanguageId={Pageview.Area.EcomLanguageId}&CurrencyCode={Pageview.Area.EcomCurrencyId}&CountryCode={Pageview.Area.EcomCountryCode}&ShopId={Pageview.Area.EcomShopId} 46 &FilledProperties=Id,Price,PriceBeforeDiscount,StockLevel,VariantInfo,NeverOutOfstock,Prices 47 &PriceSettings.ShowPricesWithVat={Pageview.Area.EcomPricesWithVat} 48 &PriceSettings.FilledProperties={priceFilledProperties} 49 &getproductinfo=true"; 50 Dynamicweb.Context.Current.Items["ProductInfoFeed"] = productInfoFeed; 51 52 <script type="module"> 53 swift.LiveProductInfo.init(); 54 </script> 55 } 56 57 string googleTagManagerID = Pageview.AreaSettings.GetString("GoogleTagManagerID"); 58 string googleAnalyticsMeasurementID = Pageview.AreaSettings.GetString("GoogleAnalyticsMeasurementID"); 59 60 bool allowTracking = true; 61 if (CookieManager.IsCookieManagementActive) 62 { 63 var cookieOptInLevel = CookieManager.GetCookieOptInLevel(); 64 allowTracking = cookieOptInLevel == CookieOptInLevel.All || (cookieOptInLevel == CookieOptInLevel.Functional && CookieManager.GetCookieOptInCategories().Contains("Statistical")); 65 } 66 67 if ((!string.IsNullOrWhiteSpace(googleAnalyticsMeasurementID) || !string.IsNullOrWhiteSpace(googleTagManagerID)) && allowTracking) 68 { 69 <script> 70 gtag("event", "view_item", { 71 currency: "@Model.Price.CurrencyCode", 72 value: @PriceViewModelExtensions.ToStringInvariant(Model.Price), 73 items: [ 74 { 75 item_id: "@Model.Number", 76 item_name: "@Dynamicweb.Core.Encoders.HtmlEncoder.JavaScriptStringEncode(Model.Name)", 77 currency: "@Model.Price.CurrencyCode", 78 price: @PriceViewModelExtensions.ToStringInvariant(Model.Price) 79 } 80 ] 81 }); 82 </script> 83 } 84 85 if ((!string.IsNullOrWhiteSpace(klaviyoID))) 86 { 87 88 ProductViewModelSettings productSetting = new ProductViewModelSettings 89 { 90 LanguageId = Dynamicweb.Ecommerce.Common.Context.LanguageID, 91 CurrencyCode = Dynamicweb.Ecommerce.Common.Context.Currency.Code, 92 CountryCode = Dynamicweb.Ecommerce.Common.Context.Country.Code2, 93 ShopId = Pageview.Area.EcomShopId 94 }; 95 96 var productViewModel = ViewModelFactory.CreateView(productSetting, Model.Id, Model.VariantId); 97 98 string productLink = baseUrl + "/" + productViewModel.GetProductLink(GetPageIdByNavigationTag("Shop"), false); 99 100 string defaultProductImage = productViewModel.DefaultImage.Value; 101 102 defaultProductImage = baseUrl + "/" + defaultProductImage; 103 104 string categories = ""; 105 106 var i=0; 107 var count = Model.ProductCategories.Count(); 108 109 foreach (var category in Model.ProductCategories){ 110 categories += category.Value.Name; 111 112 if (++i != count){ 113 categories += ", "; 114 } 115 116 117 } 118 119 120 121 var groups = Model.ProductCategories; 122 123 string brandName = ""; 124 125 foreach (var group in groups) { 126 foreach (var field in group.Value.Fields){ 127 if (field.Value.Name == "Brand"){ 128 if (field.Value.Value != null){ 129 brandName = field.Value.Value.ToString(); 130 } 131 } 132 } 133 } 134 135 136 137 if ((!string.IsNullOrWhiteSpace(Converter.ToString(Pageview.User?.Email)))) 138 { 139 <script> 140 141 klaviyo.identify({ 142 '$email' : '@(Converter.ToString(Pageview.User?.Email))', 143 '$first_name' : '@(Converter.ToString(Pageview.User?.Name))' 144 }); 145 146 </script> 147 } 148 149 <script type="text/javascript"> 150 var item = { 151 "ProductName": "@Dynamicweb.Core.Encoders.HtmlEncoder.JavaScriptStringEncode(Model.Name)", 152 "ProductID": "@Model.Number", 153 "Categories": "@(categories)", 154 "ImageURL": "@defaultProductImage", 155 "URL": "@(productLink)", 156 "Brand": "@(brandName)", 157 "Price": @PriceViewModelExtensions.ToStringInvariant(Model.Price) 158 }; 159 klaviyo.push(["track", "Viewed Product", item]); 160 </script> 161 162 163 <script> 164 165 166 klaviyo.push(["trackViewedItem", { 167 "Title": "@Dynamicweb.Core.Encoders.HtmlEncoder.JavaScriptStringEncode(Model.Name)", 168 "ItemId": "@Model.Number", 169 "Categories": "@(categories)", 170 "ImageUrl": "@defaultProductImage", 171 "Url": "@(productLink)", 172 "Metadata": { 173 "Price": @PriceViewModelExtensions.ToStringInvariant(Model.Price) 174 } 175 }]); 176 </script> 177 178 } 179 } 180 181 <script> 182 window.addEventListener('load', function (event) { 183 swift.Video.init(); 184 }); 185 </script> 186
Error executing template "Designs/Swift/Paragraph/Swift_ProductDetailsImage.cshtml" System.Data.SqlClient.SqlException (0x80131904): A connection was successfully established with the server, but then an error occurred during the pre-login handshake. (provider: SSL Provider, error: 0 - The handle specified is invalid) ---> System.ComponentModel.Win32Exception (0x80004005): The handle specified is invalid at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection) at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection) at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection) at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions) at System.Data.SqlClient.SqlConnection.TryOpenInner(TaskCompletionSource`1 retry) at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry) at System.Data.SqlClient.SqlConnection.Open() at Dynamicweb.Data.DatabaseConnectionProvider.CreateConnection(Boolean open) at Dynamicweb.Data.Database.CreateConnection() at Dynamicweb.Data.Database.CreateDataReader(CommandBuilder commandBuilder, IDbConnection connection, IDbTransaction transaction, Int32 commandTimeout) at Dynamicweb.Ecommerce.Products.DetailRepository.GetInheritedDetailsBulk(List`1 productIds, String detailType, Boolean onlyDefault) at Dynamicweb.Ecommerce.Products.DetailService.GetDetailsBulk(IEnumerable`1 productKeys, String detailType, Boolean excludeDefaultImage) at System.Lazy`1.CreateValue() at System.Lazy`1.LazyInitValue() at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.GetDetailsByGroupId(Product product, Lazy`1 details) at System.Lazy`1.CreateValue() at System.Lazy`1.LazyInitValue() at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.CreateView(AssetCategoryViewModelSettings settings, Product product, Lazy`1 details) at System.Lazy`1.CreateValue() at System.Lazy`1.LazyInitValue() at CompiledRazorTemplates.Dynamic.RazorEngine_116474503af0489f90f3c2dddabacee1.Execute() in D:\dynamicweb.net\Solutions\Flex Media\danzafe.cloud.dynamicweb-cms.com\files\Templates\Designs\Swift\Paragraph\Swift_ProductDetailsImage.cshtml:line 78 at RazorEngine.Templating.TemplateBase.RazorEngine.Templating.ITemplate.Run(ExecuteContext context, TextWriter reader) at RazorEngine.Templating.RazorEngineService.RunCompile(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass16_0.<RunCompile>b__0(TextWriter writer) at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter) at Dynamicweb.Rendering.RazorTemplateRenderingProvider.Render(Template template) at Dynamicweb.Rendering.TemplateRenderingService.Render(Template template) at Dynamicweb.Rendering.Template.RenderRazorTemplate() ClientConnectionId:1b12ce29-ad47-4859-afb1-e524b2ca4ae2 Error Number:-2146893055,State:0,Class:20
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 = includeImagePatternImages ? assetsList.Union(product.ImagePatternImages) : assetsList; 82 assetsList = assetsList.Union(assetsImages); 83 assetsList = includeImagePatternImages && assetsList.Count() == 0 ? assetsList.Append(product.DefaultImage) : assetsList; 84 85 86 bool defaultImageFallback = Model.Item.GetBoolean("DefaultImageFallback"); 87 bool showOnlyPrimaryImage = Model.Item.GetBoolean("ShowOnlyPrimaryImage"); 88 89 int totalAssets = 0; 90 if (showOnlyPrimaryImage == false) { 91 foreach (MediaViewModel asset in assetsList) { 92 var assetValue = asset.Value; 93 foreach (string format in allSupportedFormats) { 94 if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) { 95 totalAssets++; 96 } 97 } 98 } 99 } 100 101 if((totalAssets == 0 && product.DefaultImage != null && selectedAssetCategories.Count() == 0) || (showOnlyPrimaryImage == true && product.DefaultImage != null) || totalAssets == 0 && defaultImageFallback) 102 { 103 assetsList = new List<MediaViewModel>(){ product.DefaultImage }; 104 totalAssets = 1; 105 } 106 107 108 @* Theme settings *@ 109 string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("Theme")) ? " theme " + Model.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : ""; 110 111 var badgeParms = new Dictionary<string, object>(); 112 badgeParms.Add("size", "h5"); 113 badgeParms.Add("saleBadgeType", Model.Item.GetRawValue("SaleBadgeType")); 114 badgeParms.Add("saleBadgeCssClassName", Model.Item.GetRawValue("SaleBadgeDesign")); 115 badgeParms.Add("newBadgeCssClassName", Model.Item.GetRawValue("NewBadgeDesign")); 116 badgeParms.Add("newPublicationDays", Model.Item.GetInt32("NewPublicationDays")); 117 badgeParms.Add("campaignBadgesValues", Model.Item.GetRawValueString("CampaignBadges")); 118 119 bool saleBadgeEnabled = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("SaleBadgeDesign")) && Model.Item.GetRawValueString("SaleBadgeDesign") != "none" ? true : false; 120 bool newBadgeEnabled = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("NewBadgeDesign")) && Model.Item.GetRawValueString("NewBadgeDesign") != "none" ? true : false; 121 DateTime createdDate = product.Created.Value; 122 bool showBadges = saleBadgeEnabled && product.Discount.Price != 0 ? true : false; 123 showBadges = (newBadgeEnabled && Model.Item.GetInt32("NewPublicationDays") == 0) || (newBadgeEnabled && (createdDate.AddDays(Model.Item.GetInt32("NewPublicationDays")) > DateTime.Now)) ? true : showBadges; 124 showBadges = !string.IsNullOrEmpty(Model.Item.GetRawValueString("CampaignBadges")) ? true : showBadges; 125 126 @* Get assets from selected categories or get all assets *@ 127 if (totalAssets != 0) { 128 int assetNumber = 0; 129 int thumbnailNumber = 0; 130 int modalAssetNumber = 0; 131 var assetsListUnique = assetsList.GroupBy(x => x.Value).Select(g => g.First()).ToList(); 132 133 <div class="h-100@(theme) position-relative item_@Model.Item.SystemName.ToLower()"> 134 <div id="SmallScreenImages_@Model.ID" class="carousel@(GetArrowsColor())" data-bs-ride="carousel"> 135 <div class="carousel-inner h-100"> 136 @foreach (MediaViewModel asset in assetsListUnique) { 137 var assetValue = asset.Value; 138 foreach (string format in allSupportedFormats) { 139 if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) { 140 string activeSlide = assetNumber == 0 ? "active" : ""; 141 142 <div class="carousel-item @activeSlide" data-bs-interval="99999"> 143 144 @{ 145 string imageTheme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("ImageTheme")) ? " theme " + Model.Item.GetRawValueString("ImageTheme").Replace(" ", "").Trim().ToLower() : ""; 146 string size = "mobile"; 147 148 <div class="h-100 @(imageTheme)"> 149 @foreach (string imageFormat in supportedImageFormats) { //Images 150 if (assetValue.IndexOf(imageFormat, StringComparison.OrdinalIgnoreCase) >= 0) { 151 152 if (product is object) 153 { 154 string productName = product.Name; 155 string imagePath = !string.IsNullOrEmpty(asset.Value) ? asset.Value : product.DefaultImage.Value; 156 string imageLinkPath = Dynamicweb.Context.Current.Server.UrlEncode(imagePath); 157 158 RatioSettings ratioSettings = GetRatioSettings(size); 159 160 var parms = new Dictionary<string, object>(); 161 parms.Add("alt", productName + asset.Keywords); 162 parms.Add("itemprop", "image"); 163 parms.Add("fullwidth", true); 164 parms.Add("columns", Model.GridRowColumnCount); 165 if (!string.IsNullOrEmpty(asset.DisplayName)) { 166 parms.Add("title", asset.DisplayName); 167 } 168 169 if (ratioSettings.Ratio == "fill" && galleryLayout != "grid") { 170 parms.Add("cssClass", "w-100 h-100 image-zoom-lg-l-hover"); 171 } else { 172 parms.Add("cssClass", "mw-100 mh-100"); 173 } 174 175 <a href="@imageLinkPath" class="d-block @(ratioSettings.CssClass)@(ratioSettings.Fill)" style="@(ratioSettings.CssVariable)" data-bs-toggle="modal" data-bs-target="#modal_@Model.ID"> 176 <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"> 177 @RenderPartial("Components/Image.cshtml", new FileViewModel { Path = imagePath }, parms) 178 </div> 179 </a> 180 } 181 } 182 } 183 @foreach (string imageFormat in supportedVideoFormats) { //Videos 184 if (assetValue.IndexOf(imageFormat, StringComparison.OrdinalIgnoreCase) >= 0) { 185 if (Model.Item.GetString("OpenVideoInModal") == "true") { 186 187 188 if (product is object) 189 { 190 string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/"; 191 192 string videoScreendumpPath = !string.IsNullOrEmpty(asset.Value) ? asset.Value : ""; 193 string videoId = videoScreendumpPath.Substring(videoScreendumpPath.LastIndexOf('/') + 1); 194 videoScreendumpPath = videoScreendumpPath.IndexOf("youtu.be", StringComparison.OrdinalIgnoreCase) >= 0 || videoScreendumpPath.IndexOf("youtube", StringComparison.OrdinalIgnoreCase) >= 0 ? "https://img.youtube.com/vi/" + videoId + "/maxresdefault.jpg" : videoScreendumpPath; 195 196 string vimeoJsClass = videoScreendumpPath.IndexOf("vimeo", StringComparison.OrdinalIgnoreCase) >= 0 ? "js-vimeo-video-thumbnail" : ""; 197 videoScreendumpPath = videoScreendumpPath.IndexOf("vimeo", StringComparison.OrdinalIgnoreCase) >= 0 ? "" : videoScreendumpPath; 198 199 string productName = product.Name; 200 productName += !string.IsNullOrEmpty(asset.Keywords) ? " " + asset.Keywords : ""; 201 string assetTitle = !string.IsNullOrEmpty(asset.DisplayName) ? "title=\"" + asset.DisplayName + "\"" : ""; 202 203 RatioSettings ratioSettings = GetRatioSettings(size); 204 205 <div class="d-block @(ratioSettings.CssClass)@(ratioSettings.Fill)" style="@(ratioSettings.CssVariable); cursor: pointer" data-bs-toggle="modal" data-bs-target="#modal_@Model.ID"> 206 <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"> 207 <div class="icon-5 position-absolute" style="z-index: 1">@ReadFile(iconPath + "play-circle.svg")</div> 208 @if (videoScreendumpPath.IndexOf(".mp4", StringComparison.OrdinalIgnoreCase) < 0) 209 { 210 <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)"> 211 } 212 else 213 { 214 string videoType = Path.GetExtension(asset.Value).ToLower(); 215 216 <video preload="auto" class="h-100 w-100" style="object-fit: contain;"> 217 <source src="@asset.Value" type="video/@videoType.Replace(".", "")"> 218 </video> 219 } 220 </div> 221 </div> 222 223 <script> 224 function CheckIfVideoThumbnailExist(image) { 225 if (image.width == 120) { 226 const lowQualityImage = "https://img.youtube.com/vi/@(videoId)/hqdefault.jpg" 227 image.src = lowQualityImage; 228 } 229 } 230 </script> 231 } 232 } else { 233 if (product is object) 234 { 235 string assetName = !string.IsNullOrEmpty(asset.DisplayName) ? asset.DisplayName : asset.Name; 236 string videoId = asset.Value.Substring(asset.Value.LastIndexOf('/') + 1); 237 string type = assetValue.IndexOf("youtu.be", StringComparison.OrdinalIgnoreCase) >= 0 || assetValue.IndexOf("youtube", StringComparison.OrdinalIgnoreCase) >= 0 ? "youtube" : ""; 238 type = assetValue.IndexOf("vimeo", StringComparison.OrdinalIgnoreCase) >= 0 ? "vimeo" : type; 239 type = assetValue.IndexOf(".mp4", StringComparison.OrdinalIgnoreCase) >= 0 || assetValue.IndexOf(".webm", StringComparison.OrdinalIgnoreCase) >= 0 ? "selfhosted" : type; 240 241 string openInModal = Model.Item.GetString("OpenVideoInModal"); 242 bool autoPlay = Model.Item.GetBoolean("VideoAutoPlay"); 243 244 <div class="h-100" itemscope itemtype="https://schema.org/VideoObject"> 245 <span class="visually-hidden" itemprop="name">@assetName</span> 246 <span class="visually-hidden" itemprop="contentUrl">@asset.Value</span> 247 <span class="visually-hidden" itemprop="thumbnailUrl">@asset.Value</span> 248 249 @if (type != "selfhosted") 250 { 251 <div 252 id="player_@(Pageview.CurrentParagraph.ID)_@(videoId)_@size" 253 class="plyr__video-embed" 254 data-plyr-provider="@(type)" 255 data-plyr-embed-id="@videoId" 256 style="--plyr-color-main: var(--swift-foreground-color); height: 100%"> 257 </div> 258 259 <script type="module" src="/Files/Templates/Designs/Swift/Assets/js/plyr.js"></script> 260 261 <script type="module"> 262 var player = new Plyr('#player_@(Pageview.CurrentParagraph.ID)_@(videoId)_@size', { 263 type: 'video', 264 youtube: { 265 noCookie: true, 266 showinfo: 0 267 }, 268 fullscreen: { 269 enabled: true, 270 iosNative: true, 271 } 272 }); 273 274 @if (autoPlay && openInModal == "false") 275 { 276 <text> 277 player.config.autoplay = true; 278 player.config.muted = true; 279 player.config.volume = 0; 280 player.media.loop = true; 281 282 player.on('ready', function() { 283 if (player.config.autoplay === true) { 284 player.media.play(); 285 } 286 }); 287 </text> 288 } 289 290 @if (openInModal == "true") 291 { 292 <text> 293 var productDetailsGalleryModal = document.querySelector('#modal_@Model.ID') 294 productDetailsGalleryModal.addEventListener('hidden.bs.modal', function (event) { 295 player.media.pause(); 296 }) 297 </text> 298 } 299 </script> 300 } 301 else 302 { 303 string autoPlayAttributes = (autoPlay && openInModal == "false") ? "loop autoplay muted playsinline" : ""; 304 string videoType = Path.GetExtension(assetValue).ToLower(); 305 306 <video preload="auto" @autoPlayAttributes class="h-100 w-100" style="object-fit: cover;" controls> 307 <source src="@assetValue" type="video/@videoType.Replace(".", "")"> 308 </video> 309 } 310 </div> 311 } 312 } 313 } 314 } 315 @foreach (string imageFormat in supportedDocumentFormats) { //Documents 316 if (assetValue.IndexOf(imageFormat, StringComparison.OrdinalIgnoreCase) >= 0) { 317 if (product is object) 318 { 319 string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/"; 320 321 string productName = product.Name; 322 string imagePath = !string.IsNullOrEmpty(asset.Value) ? asset.Value : product.DefaultImage.Value; 323 string imageLinkPath = imagePath; 324 325 RatioSettings ratioSettings = GetRatioSettings(size); 326 327 var parms = new Dictionary<string, object>(); 328 parms.Add("alt", productName + asset.Keywords); 329 parms.Add("itemprop", "image"); 330 parms.Add("fullwidth", true); 331 parms.Add("columns", Model.GridRowColumnCount); 332 if (!string.IsNullOrEmpty(asset.DisplayName)) { 333 parms.Add("title", asset.DisplayName); 334 } 335 336 if (ratioSettings.Ratio == "fill" && galleryLayout != "grid") { 337 parms.Add("cssClass", "w-100 h-100 image-zoom-lg-l-hover"); 338 } else { 339 parms.Add("cssClass", "mw-100 mh-100"); 340 } 341 342 <a href="@imageLinkPath" class="d-block @(ratioSettings.CssClass)@(ratioSettings.Fill)" style="@(ratioSettings.CssVariable)" download alt="@Translate("Download")"> 343 <div class="d-flex align-items-center justify-content-center overflow-hidden h-100"> 344 <div class="icon-5 position-absolute" style="z-index: 1">@ReadFile(iconPath + "download.svg")</div> 345 @if (asset.Value.IndexOf(".pdf", StringComparison.OrdinalIgnoreCase) >= 0) { 346 @RenderPartial("Components/Image.cshtml", new FileViewModel { Path = imagePath }, parms) 347 } 348 </div> 349 </a> 350 } 351 } 352 } 353 </div> 354 } 355 356 357 </div> 358 assetNumber++; 359 } 360 } 361 } 362 </div> 363 </div> 364 365 @if (totalAssets > 1) { 366 <div id="SmallScreenImagesThumbnails_@Model.ID" class="grid grid-10 gap-2 overflow-x-auto my-3"> 367 @foreach (MediaViewModel asset in assetsListUnique) { 368 var assetValue = asset.Value; 369 foreach (string format in allSupportedFormats) { 370 if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) { 371 string imagePath = Dynamicweb.Context.Current.Server.UrlEncode(assetValue); 372 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; 373 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; 374 string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/"; 375 376 string videoId = assetValue.Substring(assetValue.LastIndexOf('/') + 1); 377 string vimeoJsClass = assetValue.IndexOf("vimeo", StringComparison.OrdinalIgnoreCase) >= 0 ? "js-vimeo-video-thumbnail" : ""; 378 379 bool isDocument = false; 380 foreach (string documentFormat in supportedDocumentFormats) { 381 if (assetValue.IndexOf(documentFormat, StringComparison.OrdinalIgnoreCase) >= 0) { 382 isDocument = true; 383 } 384 } 385 386 string assetName = asset.Name; 387 assetName += !string.IsNullOrEmpty(asset.Keywords) ? " " + asset.Keywords : ""; 388 string assetTitle = !string.IsNullOrEmpty(asset.DisplayName) ? "title=\"" + asset.DisplayName + "\"" : ""; 389 390 if (!isDocument) { 391 RatioSettings ratioSettings = GetRatioSettings("desktop"); 392 393 <div class="border outline-none @(ratioSettings.CssClass)" style="@(ratioSettings.CssVariable); cursor: pointer" data-bs-target="#SmallScreenImages_@Model.ID" data-bs-slide-to="@thumbnailNumber"> 394 <div class="d-flex align-items-center justify-content-center overflow-hidden position-absolute h-100"> 395 @foreach (string videoFormat in supportedVideoFormats) { //Videos 396 if (assetValue.IndexOf(videoFormat, StringComparison.OrdinalIgnoreCase) >= 0) { 397 <div class="icon-3 position-absolute text-light" style="z-index: 1">@ReadFile(iconPath + "play-circle.svg")</div> 398 } 399 } 400 </div> 401 @if (imagePathThumb.IndexOf(".mp4", StringComparison.OrdinalIgnoreCase) < 0) { 402 <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"> 403 } else { 404 string videoType = Path.GetExtension(asset.Value).ToLower(); 405 406 <video preload="auto" class="h-100 w-100" style="object-fit: contain;"> 407 <source src="@imagePathThumb" type="video/@videoType.Replace(".", "")"> 408 </video> 409 } 410 </div> 411 } else { 412 <a href="@assetValue" class="ratio ratio-4x3 border outline-none" style="cursor: pointer" download title="@asset.Value"> 413 @if (asset.Value.IndexOf(".pdf", StringComparison.OrdinalIgnoreCase) >= 0) { 414 <div class="d-flex align-items-center justify-content-center overflow-hidden h-100"> 415 <div class="icon-3 position-absolute text-light" style="z-index: 1">@ReadFile(iconPath + "download.svg")</div> 416 </div> 417 <img src="@imagePathThumb" alt="@assetName" @assetTitle class="p-0 p-lg-1 mw-100 mh-100" style="object-fit: cover;"> 418 } else { 419 <div class="d-flex align-items-center justify-content-center overflow-hidden h-100"> 420 <div class="icon-3 position-absolute" style="z-index: 1">@ReadFile(iconPath + "file-text.svg")</div> 421 </div> 422 } 423 </a> 424 } 425 426 thumbnailNumber++; 427 } 428 } 429 } 430 </div> 431 } 432 433 @if (showBadges) { 434 <div class="position-absolute top-0 left-0 p-2 p-lg-3"> 435 @RenderPartial("Components/EcommerceBadge.cshtml", product, badgeParms) 436 </div> 437 } 438 </div> 439 440 @* Modal with slides *@ 441 <div class="modal fade swift_products-details-images-modal" id="modal_@Model.ID" tabindex="-1" aria-labelledby="productDetailsGalleryModalTitle_@Model.ID" aria-hidden="true"> 442 <div class="modal-dialog modal-dialog-centered modal-xl"> 443 <div class="modal-content"> 444 <div class="modal-header visually-hidden"> 445 <strong class="modal-title" id="productDetailsGalleryModalTitle_@Model.ID">@product.Title</strong> 446 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> 447 </div> 448 <div class="modal-body p-2 p-lg-3 h-100"> 449 <div id="ModalCarousel_@Model.ID" class="carousel@(GetArrowsColor()) h-100" data-bs-ride="carousel"> 450 <div class="carousel-inner h-100"> 451 @foreach (MediaViewModel asset in assetsList) { 452 var assetValue = !string.IsNullOrEmpty(asset.Value) ? asset.Value : product.DefaultImage.Value; 453 foreach (string format in supportedImageFormats.Concat(supportedVideoFormats).ToArray()) { 454 if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) { 455 string imagePath = assetValue; 456 string activeSlide = modalAssetNumber == 0 ? "active" : ""; 457 458 var parms = new Dictionary<string, object>(); 459 parms.Add("cssClass", "d-block mw-100 mh-100 m-auto"); 460 parms.Add("fullwidth", true); 461 parms.Add("columns", Model.GridRowColumnCount); 462 463 <div class="carousel-item @activeSlide h-100" data-bs-interval="99999"> 464 @foreach (string imageFormat in supportedImageFormats) { //Images 465 if (assetValue.IndexOf(imageFormat, StringComparison.OrdinalIgnoreCase) >= 0) { 466 @RenderPartial("Components/Image.cshtml", new FileViewModel { Path = imagePath }, parms) 467 } 468 } 469 470 @foreach (string videoFormat in supportedVideoFormats) { //Videos 471 if (assetValue.IndexOf(videoFormat, StringComparison.OrdinalIgnoreCase) >= 0) { 472 if (product is object) 473 { 474 string size = "modal"; 475 string assetName = !string.IsNullOrEmpty(asset.DisplayName) ? asset.DisplayName : asset.Name; 476 string videoId = asset.Value.Substring(asset.Value.LastIndexOf('/') + 1); 477 string type = assetValue.IndexOf("youtu.be", StringComparison.OrdinalIgnoreCase) >= 0 || assetValue.IndexOf("youtube", StringComparison.OrdinalIgnoreCase) >= 0 ? "youtube" : ""; 478 type = assetValue.IndexOf("vimeo", StringComparison.OrdinalIgnoreCase) >= 0 ? "vimeo" : type; 479 type = assetValue.IndexOf(".mp4", StringComparison.OrdinalIgnoreCase) >= 0 || assetValue.IndexOf(".webm", StringComparison.OrdinalIgnoreCase) >= 0 ? "selfhosted" : type; 480 481 string openInModal = Model.Item.GetString("OpenVideoInModal"); 482 bool autoPlay = Model.Item.GetBoolean("VideoAutoPlay"); 483 484 <div class="h-100" itemscope itemtype="https://schema.org/VideoObject"> 485 <span class="visually-hidden" itemprop="name">@assetName</span> 486 <span class="visually-hidden" itemprop="contentUrl">@asset.Value</span> 487 <span class="visually-hidden" itemprop="thumbnailUrl">@asset.Value</span> 488 489 @if (type != "selfhosted") 490 { 491 <div 492 id="player_@(Pageview.CurrentParagraph.ID)_@(videoId)_@size" 493 class="plyr__video-embed" 494 data-plyr-provider="@(type)" 495 data-plyr-embed-id="@videoId" 496 style="--plyr-color-main: var(--swift-foreground-color); height: 100%"> 497 </div> 498 499 <script type="module" src="/Files/Templates/Designs/Swift/Assets/js/plyr.js"></script> 500 501 <script type="module"> 502 var player = new Plyr('#player_@(Pageview.CurrentParagraph.ID)_@(videoId)_@size', { 503 type: 'video', 504 youtube: { 505 noCookie: true, 506 showinfo: 0 507 }, 508 fullscreen: { 509 enabled: true, 510 iosNative: true, 511 } 512 }); 513 514 @if (autoPlay && openInModal == "false") 515 { 516 <text> 517 player.config.autoplay = true; 518 player.config.muted = true; 519 player.config.volume = 0; 520 player.media.loop = true; 521 522 player.on('ready', function() { 523 if (player.config.autoplay === true) { 524 player.media.play(); 525 } 526 }); 527 </text> 528 } 529 530 @if (openInModal == "true") 531 { 532 <text> 533 var productDetailsGalleryModal = document.querySelector('#modal_@Model.ID') 534 productDetailsGalleryModal.addEventListener('hidden.bs.modal', function (event) { 535 player.media.pause(); 536 }) 537 </text> 538 } 539 </script> 540 } 541 else 542 { 543 string autoPlayAttributes = (autoPlay && openInModal == "false") ? "loop autoplay muted playsinline" : ""; 544 string videoType = Path.GetExtension(assetValue).ToLower(); 545 546 <video preload="auto" @autoPlayAttributes class="h-100 w-100" style="object-fit: cover;" controls> 547 <source src="@assetValue" type="video/@videoType.Replace(".", "")"> 548 </video> 549 } 550 </div> 551 } 552 } 553 } 554 </div> 555 556 modalAssetNumber++; 557 } 558 } 559 } 560 <button class="carousel-control-prev" type="button" data-bs-target="#ModalCarousel_@Model.ID" data-bs-slide="prev"> 561 <span class="carousel-control-prev-icon" aria-hidden="true"></span> 562 <span class="visually-hidden">@Translate("Previous")</span> 563 </button> 564 <button class="carousel-control-next" type="button" data-bs-target="#ModalCarousel_@Model.ID" data-bs-slide="next"> 565 <span class="carousel-control-next-icon" aria-hidden="true"></span> 566 <span class="visually-hidden">@Translate("Next")</span> 567 </button> 568 </div> 569 </div> 570 </div> 571 </div> 572 </div> 573 </div> 574 } else if (Pageview.IsVisualEditorMode) { 575 RatioSettings ratioSettings = GetRatioSettings("desktop"); 576 577 <div class="h-100 @theme"> 578 <div class="d-block @(ratioSettings.CssClass)@(ratioSettings.Fill)" style="@(ratioSettings.CssVariable)"> 579 <img src="/Files/Images/missing_image.jpg" loading="lazy" decoding="async" class="mh-100 mw-100" style="object-fit: cover;"> 580 </div> 581 </div> 582 } 583 } else if (Pageview.IsVisualEditorMode) { 584 <div class="alert alert-dark m-0">@Translate("No products available")</div> 585 } 586 587 588 589 590 591
Festool Borrning av hålrader LR 32-SYS
för OF 900, OF 1000, OF 1010, OF 1400
Hål i serie
Hål i serie
Error executing template "Designs/Swift/Paragraph/Swift_ProductPriceTable.cshtml" System.Data.SqlClient.SqlException (0x80131904): A connection was successfully established with the server, but then an error occurred during the pre-login handshake. (provider: SSL Provider, error: 0 - The handle specified is invalid) ---> System.ComponentModel.Win32Exception (0x80004005): The handle specified is invalid at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection) at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection) at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection) at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions) at System.Data.SqlClient.SqlConnection.TryOpenInner(TaskCompletionSource`1 retry) at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry) at System.Data.SqlClient.SqlConnection.Open() at Dynamicweb.Data.DatabaseConnectionProvider.CreateConnection(Boolean open) at Dynamicweb.Data.Database.CreateConnection() at Dynamicweb.Data.Database.CreateDataReader(String sql, IDbConnection connection, IDbTransaction transaction, Int32 commandTimeout, Dictionary`2 sqlParams) at Dynamicweb.Ecommerce.Prices.PriceDataBaseDependecy.GetPrices(String ids) at Dynamicweb.Ecommerce.Prices.Price.LoadPricesOnProducts(IEnumerable`1 products) at Dynamicweb.Ecommerce.Prices.PriceManager.PreparePrices(PriceContext context, IEnumerable`1 selections) at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.PreparePrices(PriceContext context, Boolean& pricesHasBeenPrepared, Object lock, IList`1 products, Int64 stockLocationId) at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.GetPrices(PriceViewModelSettings settings, IList`1 products, Boolean& pricesHasBeenPrepared, Object lock, Product product) at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.<>c__DisplayClass3_1.<BulkCreateView>b__53() at System.Lazy`1.CreateValue() at System.Lazy`1.LazyInitValue() at CompiledRazorTemplates.Dynamic.RazorEngine_f4e494d0217341c2973f932a56a75fd4.Execute() in D:\dynamicweb.net\Solutions\Flex Media\danzafe.cloud.dynamicweb-cms.com\files\Templates\Designs\Swift\Paragraph\Swift_ProductPriceTable.cshtml:line 39 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:1b12ce29-ad47-4859-afb1-e524b2ca4ae2 Error Number:-2146893055,State:0,Class:20
1 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.ParagraphViewModel> 2 @using Dynamicweb.Ecommerce.ProductCatalog 3 4 @{ 5 ProductViewModel product = null; 6 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails")) 7 { 8 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"]; 9 } 10 else if (Pageview.Page.Item["DummyProduct"] != null && Pageview.IsVisualEditorMode) 11 { 12 var pageViewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(Pageview.Page); 13 ProductListViewModel productList = pageViewModel.Item.GetValue("DummyProduct") != null ? pageViewModel.Item.GetValue("DummyProduct") as ProductListViewModel : new ProductListViewModel(); 14 15 if (productList?.Products is object) 16 { 17 product = productList.Products[0]; 18 } 19 } 20 21 string anonymousUsersLimitations = Pageview.AreaSettings.GetRawValueString("AnonymousUsers", ""); 22 bool anonymousUser = Pageview.User == null; 23 bool hidePrice = anonymousUsersLimitations.Contains("price") && anonymousUser; 24 hidePrice = Pageview.IsVisualEditorMode ? false : hidePrice; 25 } 26 27 @if (product is object && !hidePrice) 28 { 29 bool isLazyLoadingForProductInfoEnabled = Dynamicweb.Core.Converter.ToBoolean(Dynamicweb.Context.Current.Items["IsLazyLoadingForProductInfoEnabled"]); 30 31 if (Pageview.IsVisualEditorMode && product.Prices.Count == 0) 32 { 33 product.Prices.Add(new PriceListViewModel { Price = new PriceViewModel { Price = 95, PriceFormatted = "€95" }, Quantity = 1 }); 34 product.Prices.Add(new PriceListViewModel { Price = new PriceViewModel { Price = 85, PriceFormatted = "€85" }, Quantity = 2 }); 35 } 36 37 string layout = Model.Item.GetRawValueString("Layout", "list"); 38 39 if (product.Prices.Count > 0) 40 { 41 if (isLazyLoadingForProductInfoEnabled) 42 { 43 <div class="product-prices-container d-none" data-show-if="LiveProductInfo.product.Prices.length > 0"> 44 @if (layout == "list") 45 { 46 <div class="product-prices item_@Model.Item.SystemName.ToLower() list"> 47 <small class="d-block opacity-75 product-prices-template"><span><span class="js-text-price-quantity"></span> @Translate("PCS")</span> - <span class="fw-bold"><span class="js-text-price-price"></span> <span class="d-none" data-show-if="LiveProductInfo.productPrice.Quantity > 1">@Translate("pr. PCS")</span></span></small> 48 </div> 49 } 50 else if (layout == "table") 51 { 52 <div class="item_@Model.Item.SystemName.ToLower() grid"> 53 <table class="table table-sm mt-3 g-col-12 g-col-lg-6"> 54 <thead> 55 <tr> 56 <td>@Translate("QTY")</td> 57 <td>@Translate("pr. PCS")</td> 58 </tr> 59 </thead> 60 <tbody class="product-prices"> 61 <tr class="product-prices-template"> 62 <td class="js-text-price-quantity"></td> 63 <td class="js-text-price-price"></td> 64 </tr> 65 </tbody> 66 </table> 67 </div> 68 } 69 </div> 70 } 71 else 72 { 73 if (layout == "list") 74 { 75 <div class="item_@Model.Item.SystemName.ToLower() list"> 76 @foreach (PriceListViewModel quantityPrice in product.Prices) 77 { 78 string quantityLabel = Translate("PCS"); 79 string quantityPriceSuffix = quantityPrice.Quantity > 1 ? Translate("pr. PCS") : ""; 80 81 <small class="d-block opacity-75"><span>@quantityPrice.Quantity @quantityLabel</span> - <span class="fw-bold">@quantityPrice.Price.PriceFormatted @quantityPriceSuffix</span></small> 82 } 83 </div> 84 } 85 else if (layout == "table") 86 { 87 <div class="item_@Model.Item.SystemName.ToLower() grid"> 88 <table class="table table-sm mt-3 g-col-12 g-col-lg-6"> 89 <thead> 90 <tr> 91 <td>@Translate("QTY")</td> 92 <td>@Translate("pr. PCS")</td> 93 </tr> 94 </thead> 95 <tbody> 96 @foreach (PriceListViewModel quantityPrice in product.Prices) 97 { 98 <tr> 99 <td>@quantityPrice.Quantity</td> 100 <td>@quantityPrice.Price.PriceFormatted</td> 101 </tr> 102 } 103 </tbody> 104 </table> 105 </div> 106 } 107 } 108 } 109 else if (Pageview.IsVisualEditorMode) 110 { 111 <div class="alert alert-dark m-0" role="alert"> 112 <span>@Translate("No products available")</span> 113 </div> 114 } 115 } 116 else if (Pageview.IsVisualEditorMode) 117 { 118 <div class="alert alert-dark m-0" role="alert"> 119 <span>@Translate("No products available")</span> 120 </div> 121 } 122
Error executing template "Designs/Swift/Paragraph/Swift_ProductPrice.cshtml" System.Data.SqlClient.SqlException (0x80131904): A connection was successfully established with the server, but then an error occurred during the pre-login handshake. (provider: SSL Provider, error: 0 - The handle specified is invalid) ---> System.ComponentModel.Win32Exception (0x80004005): The handle specified is invalid at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection) at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection) at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection) at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions) at System.Data.SqlClient.SqlConnection.TryOpenInner(TaskCompletionSource`1 retry) at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry) at System.Data.SqlClient.SqlConnection.Open() at Dynamicweb.Data.DatabaseConnectionProvider.CreateConnection(Boolean open) at Dynamicweb.Data.Database.CreateConnection() at Dynamicweb.Data.Database.CreateDataReader(String sql, IDbConnection connection, IDbTransaction transaction, Int32 commandTimeout, Dictionary`2 sqlParams) at Dynamicweb.Ecommerce.Prices.PriceDataBaseDependecy.GetPrices(String ids) at Dynamicweb.Ecommerce.Prices.Price.LoadPricesOnProducts(IEnumerable`1 products) at Dynamicweb.Ecommerce.Prices.PriceManager.PreparePrices(PriceContext context, IEnumerable`1 selections) at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.PreparePrices(PriceContext context, Boolean& pricesHasBeenPrepared, Object lock, IList`1 products, Int64 stockLocationId) 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_bd5977aff71f42fcb1224e2f38255085.Execute() in D:\dynamicweb.net\Solutions\Flex Media\danzafe.cloud.dynamicweb-cms.com\files\Templates\Designs\Swift\Paragraph\Swift_ProductPrice.cshtml:line 31 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:1b12ce29-ad47-4859-afb1-e524b2ca4ae2 Error Number:-2146893055,State:0,Class:20
1 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.ParagraphViewModel> 2 @using Dynamicweb.Ecommerce.ProductCatalog 3 @using Dynamicweb.Ecommerce.Prices 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 anonymousUsersLimitations = Pageview.AreaSettings.GetRawValueString("AnonymousUsers", ""); 23 bool anonymousUser = Pageview.User == null; 24 bool isErpConnectionDown = !Dynamicweb.Core.Converter.ToBoolean(Dynamicweb.Context.Current.Items["IsWebServiceConnectionAvailable"]); 25 bool hidePrice = anonymousUsersLimitations.Contains("price") && anonymousUser || Pageview.AreaSettings.GetBoolean("ErpDownHidePrices") && isErpConnectionDown; 26 27 bool productIsDiscontinued = product is object && product.Discontinued; 28 bool doNotShowPriceIfProductIsDiscontinued = Model.Item.GetBoolean("DoNotShowPriceIfProductIsDiscontinued"); 29 var isDiscontinued = productIsDiscontinued && doNotShowPriceIfProductIsDiscontinued; 30 31 string CurrencyTag = "<span class=\"CurrencyCode\">" + product.Price.CurrencyCode + "</span> "; 32 33 } 34 35 @if (product is object && !hidePrice && !isDiscontinued) { 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 string horizontalAlign = Model.Item.GetRawValueString("HorizontalAlignment", ""); 41 string layout = Model.Item.GetRawValueString("Layout", "horizontal"); 42 string textAlign = horizontalAlign == "center" ? "text-center" : string.Empty; 43 textAlign = horizontalAlign == "end" ? "text-end" : textAlign; 44 45 horizontalAlign = horizontalAlign == "center" && layout == "horizontal" ? "justify-content-center" : horizontalAlign; 46 horizontalAlign = horizontalAlign == "end" && layout == "horizontal" ? "justify-content-end" : horizontalAlign; 47 horizontalAlign = horizontalAlign == "center" && layout == "vertical" ? "align-items-center" : horizontalAlign; 48 horizontalAlign = horizontalAlign == "end" && layout == "vertical" ? "align-items-end" : horizontalAlign; 49 50 string flexDirection = layout == "horizontal" ? string.Empty : "flex-column"; 51 string flexGap = layout == "horizontal" ? "gap-3" : string.Empty; 52 string order = layout == "horizontal" ? string.Empty : "order-2"; 53 string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("Theme")) ? "theme " + Model.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : ""; 54 theme = GetViewParameter("theme") != null ? GetViewParameterString("theme") : theme; 55 56 string contentPadding = Model.Item.GetRawValueString("ContentPadding", ""); 57 contentPadding = contentPadding == "none" ? "p-0" : contentPadding; 58 contentPadding = contentPadding == "small" ? "p-1 px-md-2 py-md-1" : contentPadding; 59 contentPadding = contentPadding == "large" ? "p-2 px-md-3 py-md-2" : contentPadding; 60 61 string showPricesWithVat = Pageview.Area.EcomPricesWithVat.ToLower(); 62 bool neverShowVat = string.IsNullOrEmpty(showPricesWithVat); 63 64 string priceMin = ""; 65 string priceMax = ""; 66 67 string liveInfoClass = ""; 68 string productInfoFeed = ""; 69 bool isLazyLoadingForProductInfoEnabled = Dynamicweb.Core.Converter.ToBoolean(Dynamicweb.Context.Current.Items["IsLazyLoadingForProductInfoEnabled"]); 70 if (isLazyLoadingForProductInfoEnabled) 71 { 72 if (Dynamicweb.Context.Current.Items.Contains("ProductInfoFeed")) 73 { 74 productInfoFeed = Dynamicweb.Context.Current.Items["ProductInfoFeed"]?.ToString(); 75 if (!string.IsNullOrEmpty(productInfoFeed)) 76 { 77 productInfoFeed = $"data-product-info-feed=\"{productInfoFeed}\""; 78 } 79 } 80 liveInfoClass = "js-live-info"; 81 } 82 83 84 // var priceContext = new PriceContext(Dynamicweb.Ecommerce.Services.Currencies.GetDefaultCurrency(), Dynamicweb.Ecommerce.Services.Countries.GetCountries().FirstOrDefault(), Dynamicweb.Ecommerce.Services.Shops.GetDefaultShop(), null, false, DateTime.Now); 85 86 87 double discountPriceMinD = 0; 88 double discountPriceMaxD = 0; 89 string discountPriceMin = ""; 90 string discountPriceMax = ""; 91 92 // var productCombinationList = new List<ProductViewModel>(); 93 var productVariants = product.VariantCombinations(); 94 var priceContext = new PriceContext(Dynamicweb.Ecommerce.Services.Currencies.GetDefaultCurrency(), Dynamicweb.Ecommerce.Services.Countries.GetCountries().FirstOrDefault(), Dynamicweb.Ecommerce.Services.Shops.GetDefaultShop(), Dynamicweb.Security.UserManagement.User.GetCurrentFrontendUser(), false, DateTime.Now); 95 96 foreach (var variant in productVariants){ 97 var productVariant = Dynamicweb.Ecommerce.Services.Products.GetProductById(product.Id, variant, true); 98 double VariantDiscountD = productVariant.GetDiscountMatrix(priceContext, product.DefaultUnitId, 1).Price.Price; 99 // string VariantDiscount = productVariant.GetDiscountMatrix(priceContext, product.DefaultUnitId, 1).Price.ToString(); 100 string VariantDiscount = CurrencyTag + productVariant.GetDiscountMatrix(priceContext, product.DefaultUnitId, 1).Price.Price.ToString("#.00"); 101 102 if(VariantDiscountD>0){ 103 if(discountPriceMinD==0 || discountPriceMinD>VariantDiscountD){discountPriceMinD=VariantDiscountD;discountPriceMin=VariantDiscount;} 104 if(discountPriceMaxD==0 || VariantDiscountD>discountPriceMaxD){discountPriceMaxD=VariantDiscountD;discountPriceMax=VariantDiscount;} 105 } 106 } 107 108 109 110 111 112 <div class="@textAlign @liveInfoClass item_@Model.Item.SystemName.ToLower()" data-product-id="@product.Id" data-variant-id="@product.VariantId" @productInfoFeed> 113 @if (showInformativePrice && product.PriceInformative.Price != 0) 114 { 115 <div class="opacity-50"> 116 <span>@Translate("RRP") </span> 117 <span class="text-decoration-line-through text-price">@product.PriceInformative.Price.ToString("#.00")</span> 118 </div> 119 } 120 <div class="@priceFontSize m-0 d-flex flex-wrap @flexDirection @flexGap @horizontalAlign" style="row-gap: 0 !important" itemprop="offers" itemscope itemtype="https://schema.org/Offer"> 121 <span itemprop="priceCurrency" content="@product.Price.CurrencyCode" class="d-none"></span> 122 123 124 @if (showPricesWithVat == "false" && !neverShowVat) 125 { 126 if (isLazyLoadingForProductInfoEnabled && !Pageview.IsVisualEditorMode) 127 { 128 <span itemprop="price" content="" class="d-none"></span> 129 <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> 130 } 131 else 132 { 133 string beforePrice = !string.IsNullOrEmpty(unitId) ? CurrencyTag + product.GetPrice(unitId).PriceBeforeDiscount.PriceWithoutVat.ToString("#.00") : CurrencyTag + product.PriceBeforeDiscount.PriceWithoutVat.ToString("#.00"); 134 135 <span itemprop="price" content="@product.Price.PriceWithoutVat.ToString().Replace(',','.')" class="d-none"></span> 136 if (product.Price.Price != product.PriceBeforeDiscount.Price) 137 { 138 <span class="text-decoration-line-through opacity-75 @order">@beforePrice</span> 139 } 140 } 141 } 142 else 143 { 144 if (isLazyLoadingForProductInfoEnabled && !Pageview.IsVisualEditorMode) 145 { 146 <span itemprop="price" content="" class="d-none"></span> 147 <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> 148 } 149 else 150 { 151 string beforePrice = !string.IsNullOrEmpty(unitId) ? CurrencyTag + product.GetPrice(unitId).PriceBeforeDiscount.Price.ToString("#.00") : CurrencyTag + product.PriceBeforeDiscount.Price.ToString("#.00"); 152 153 <span itemprop="price" content="@product.Price.Price.ToString().Replace(',','.')" class="d-none"></span> 154 155 if (product.Price.Price != product.PriceBeforeDiscount.Price) 156 { 157 <span class="text-decoration-line-through opacity-75 @order"> 158 <span class="text-price" t=a>@beforePrice</span> 159 </span> 160 } 161 } 162 } 163 164 @if (showPricesWithVat == "false" && !neverShowVat) 165 { 166 if (isLazyLoadingForProductInfoEnabled && !Pageview.IsVisualEditorMode) 167 { 168 <span class="text-price js-text-price"> 169 <span class="spinner-border" role="status"></span> 170 </span> 171 } 172 else 173 { 174 string price = !string.IsNullOrEmpty(unitId) ? product.GetPrice(unitId).Price.PriceWithoutVat.ToString("#.00") : product.Price.PriceWithoutVat.ToString("#.00"); 175 176 if (product?.VariantInfo?.VariantInfo != null) 177 { 178 priceMin = product?.VariantInfo?.PriceMin?.PriceWithoutVatFormatted != null ? product.VariantInfo.PriceMin.PriceWithoutVat.ToString("#.00") : ""; 179 priceMax = product?.VariantInfo?.PriceMax?.PriceWithoutVatFormatted != null ? product.VariantInfo.PriceMax.PriceWithoutVat.ToString("#.00") : ""; 180 } 181 if (priceMin != priceMax) 182 { 183 price = priceMin + " - " + priceMax; 184 } 185 <span class="@theme @contentPadding"> 186 <span class="text-price" t=b>@price</span> 187 </span> 188 } 189 } 190 else 191 { 192 if (isLazyLoadingForProductInfoEnabled && !Pageview.IsVisualEditorMode) 193 { 194 <span class="text-price js-text-price"> 195 <span class="spinner-border" role="status"></span> 196 </span> 197 } 198 else 199 { 200 // string price = !string.IsNullOrEmpty(unitId) ? product.GetPrice(unitId).Price.PriceFormatted : product.Price.PriceFormatted; 201 string price = !string.IsNullOrEmpty(unitId) ? CurrencyTag + product.GetPrice(unitId).Price.Price.ToString("#.00") : CurrencyTag + product.Price.Price.ToString("#.00"); 202 203 double priceD = !string.IsNullOrEmpty(unitId) ? product.GetPrice(unitId).Price.Price : product.Price.Price; 204 double priceMinD= 0; 205 double priceMaxD = 0; 206 if (product?.VariantInfo?.VariantInfo != null) 207 { 208 209 // priceMin = product?.VariantInfo?.PriceMin?.PriceFormatted != null ? product.VariantInfo.PriceMin.PriceFormatted : ""; 210 priceMin = product?.VariantInfo?.PriceMin?.PriceFormatted != null ? CurrencyTag + product.VariantInfo.PriceMin.Price.ToString("#.00") : ""; 211 212 priceMinD = product?.VariantInfo?.PriceMin?.Price != null ? product.VariantInfo.PriceMin.Price : 0; 213 214 // priceMax = product?.VariantInfo?.PriceMax?.PriceFormatted != null ? product.VariantInfo.PriceMax.PriceFormatted : ""; 215 priceMax = product?.VariantInfo?.PriceMin?.PriceFormatted != null ? CurrencyTag + product.VariantInfo.PriceMax.Price.ToString("#.00") : ""; 216 217 priceMaxD = product?.VariantInfo?.PriceMax?.Price != null ? product.VariantInfo.PriceMax.Price : 0; 218 } 219 220 if (priceMin != priceMax){ 221 price = priceMin + " - " + priceMax; 222 223 if(priceMinD>discountPriceMinD && priceMaxD>discountPriceMaxD){ 224 price = discountPriceMin + " - " + discountPriceMax; 225 } 226 } 227 if(priceD == 0 && priceMinD > 0 && priceMinD == priceMaxD){ 228 price = priceMin; 229 } 230 231 232 233 <span class="@theme @contentPadding"> 234 <span class="text-price" t=c>@price</span> 235 </span> 236 } 237 } 238 239 @* Stock state for Schema.org, start *@ 240 @{ 241 Uri url = Dynamicweb.Context.Current.Request.Url; 242 } 243 244 <link itemprop="url" href="@url"> 245 246 @{ 247 bool IsNeverOutOfStock = product.NeverOutOfstock; 248 } 249 250 @if (IsNeverOutOfStock) 251 { 252 <span itemprop="availability" class="d-none">InStock</span> 253 <span class="d-none">@Translate("Available in stock")</span> 254 } 255 else 256 { 257 if (product.StockLevel > 0) 258 { 259 <span itemprop="availability" class="d-none">InStock</span> 260 } 261 else 262 { 263 <span itemprop="availability" class="d-none">OutOfStock</span> 264 } 265 } 266 @* Stock state for Schema.org, stop *@ 267 268 </div> 269 270 @if (showPricesWithVat == "false" && !neverShowVat) 271 { 272 if (isLazyLoadingForProductInfoEnabled && !Pageview.IsVisualEditorMode) 273 { 274 <small class="opacity-85 fst-normal js-text-price-with-vat d-none" data-suffix="@Translate("Incl. VAT")"></small> 275 } 276 else 277 { 278 string price = !string.IsNullOrEmpty(unitId) ? product.GetPrice(unitId).Price.PriceWithVat.ToString("#.00") : product.Price.PriceWithVat.ToString("#.00"); 279 280 if (product?.VariantInfo?.VariantInfo != null) 281 { 282 priceMin = product?.VariantInfo?.PriceMin?.PriceWithVatFormatted != null ? product.VariantInfo.PriceMin.PriceWithVat.ToString("#.00") : ""; 283 priceMax = product?.VariantInfo?.PriceMax?.PriceWithVatFormatted != null ? product.VariantInfo.PriceMax.PriceWithVat.ToString("#.00") : ""; 284 } 285 if (priceMin != priceMax) 286 { 287 price = priceMin + " - " + priceMax; 288 } 289 <small class="opacity-85 fst-normal">@price @Translate("Incl. VAT")</small> 290 } 291 } 292 </div> 293 } 294 else if (Pageview.IsVisualEditorMode) 295 { 296 <div class="alert alert-dark m-0" role="alert"> 297 <span>@Translate("No products available")</span> 298 </div> 299 } 300
Error executing template "Designs/Swift/Paragraph/Swift_ProductVariantSelector.cshtml" System.Data.SqlClient.SqlException (0x80131904): A connection was successfully established with the server, but then an error occurred during the pre-login handshake. (provider: SSL Provider, error: 0 - The handle specified is invalid) ---> System.ComponentModel.Win32Exception (0x80004005): The handle specified is invalid at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection) at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection) at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection) at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions) at System.Data.SqlClient.SqlConnection.TryOpenInner(TaskCompletionSource`1 retry) at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry) at System.Data.SqlClient.SqlConnection.Open() at Dynamicweb.Data.DatabaseConnectionProvider.CreateConnection(Boolean open) at Dynamicweb.Data.Database.CreateConnection() at Dynamicweb.Data.Database.CreateDataReader(CommandBuilder commandBuilder, IDbConnection connection, IDbTransaction transaction, Int32 commandTimeout) at Dynamicweb.Ecommerce.Products.ProductRepository.GetProductsBySql(CommandBuilder query, Boolean doRefactoring, Boolean bulkFill, Boolean useAssortments) at Dynamicweb.Ecommerce.Products.ProductRepository.GetAllVariantProducts(IEnumerable`1 productIds, String productLanguageId) at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.GetBulkVariants(IEnumerable`1 productIds, String languageId) at System.Lazy`1.CreateValue() at System.Lazy`1.LazyInitValue() at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.<>c__DisplayClass3_1.<BulkCreateView>b__6() at System.Lazy`1.CreateValue() at System.Lazy`1.LazyInitValue() at Dynamicweb.Ecommerce.ProductCatalog.ProductViewModelExtensionMethods.VariantGroups(ProductViewModel productViewModel) at CompiledRazorTemplates.Dynamic.RazorEngine_793bc487a2b046b2ba45bda3df388c1f.Execute() in D:\dynamicweb.net\Solutions\Flex Media\danzafe.cloud.dynamicweb-cms.com\files\Templates\Designs\Swift\Paragraph\Swift_ProductVariantSelector.cshtml:line 132 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:1b12ce29-ad47-4859-afb1-e524b2ca4ae2 Error Number:-2146893055,State:0,Class:20
1 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.ParagraphViewModel> 2 @using System.Collections.Generic 3 @using System.Linq 4 @using Dynamicweb.Ecommerce.ProductCatalog 5 @using Dynamicweb.Ecommerce.Variants 6 @using System.Text.RegularExpressions 7 8 @functions { 9 10 11 //Find contrast color (white, black) 12 public static string GetContrastColor(string hexString) 13 { 14 System.Drawing.Color bg = System.Drawing.ColorTranslator.FromHtml(hexString); 15 16 int nThreshold = 105; 17 int bgDelta = Convert.ToInt32((bg.R * 0.299) + (bg.G * 0.587) + 18 (bg.B * 0.114)); 19 20 string foreColor = (255 - bgDelta < nThreshold) ? "#333" : "#fff"; 21 return foreColor; 22 } 23 24 public string GetLayoutForVariantGroup(string variantGroupId) 25 { 26 string showVariantGroups = !string.IsNullOrEmpty(Model.Item.GetString("ShowVariantGroupOptions")) ? Model.Item.GetString("ShowVariantGroupOptions") : "all"; 27 string defaultVariantGroupLayout = Model.Item.GetRawValueString("DefaultVariantGroupLayout", "button"); 28 var selectedVariantGroupsList = !string.IsNullOrEmpty(Model.Item.GetRawValueString("VariantGroups")) ? Model.Item.GetItems("VariantGroups") : new List<Dynamicweb.Frontend.ItemViewModel>(); 29 30 if (showVariantGroups == "all" || selectedVariantGroupsList == null || !selectedVariantGroupsList.Any()) return defaultVariantGroupLayout; 31 32 foreach (var selectedVariantGroupListItem in selectedVariantGroupsList) 33 { 34 var variantGroups = selectedVariantGroupListItem.GetRawValueString("VariantGroups").Split(','); 35 if (variantGroups.Any(s => s.Equals(variantGroupId))) return selectedVariantGroupListItem.GetRawValueString("VariantGroupLayout"); 36 } 37 38 return defaultVariantGroupLayout; 39 } 40 41 //Collect all variant images 42 public static Dictionary<string, string> GetVariantImages(List<VariantInfoViewModel> variantInfo, Dictionary<string, string> list) 43 { 44 foreach (var variantGroup in variantInfo) 45 { 46 if (variantGroup.Image?.Value != null && !list.ContainsKey(variantGroup.OptionID)) 47 { 48 list.Add(variantGroup.OptionID, variantGroup.Image.Value); 49 } 50 51 if (variantGroup.VariantInfo != null) 52 { 53 GetVariantImages(variantGroup.VariantInfo, list); 54 } 55 } 56 57 return list; 58 } 59 60 private string GetDefaultOrVariantGroupValue(string variantGroupId, string itemField, string itemFieldDefaultValue, Dictionary<string, string> fieldValueMapping) 61 { 62 string itemFieldValue = Model.Item.GetRawValueString(itemField, itemFieldDefaultValue); 63 itemFieldValue = fieldValueMapping.ContainsKey(itemFieldValue) ? fieldValueMapping[itemFieldValue] : itemFieldValue; 64 65 // If no variantGroup (i.e. Visual Editor), return default value 66 if (string.IsNullOrEmpty(variantGroupId)) return itemFieldValue; 67 68 string showVariantGroups = Model.Item.GetString("ShowVariantGroupOptions", "all"); 69 var selectedVariantGroupsList = !string.IsNullOrEmpty(Model.Item.GetRawValueString("VariantGroups")) ? Model.Item.GetItems("VariantGroups") : new List<Dynamicweb.Frontend.ItemViewModel>(); 70 // If no exceptions or settings are all the same, return default value 71 if (showVariantGroups == "all" || selectedVariantGroupsList == null || !selectedVariantGroupsList.Any()) return itemFieldValue; 72 73 // Get specific value for variant group 74 foreach (var selectedVariantGroupListItem in selectedVariantGroupsList) 75 { 76 var variantGroups = selectedVariantGroupListItem.GetRawValueString("VariantGroups").Split(','); 77 if (!variantGroups.Any(s => s.Equals(variantGroupId))) continue; 78 79 itemFieldValue = selectedVariantGroupListItem.GetRawValueString(itemField, itemFieldDefaultValue); 80 itemFieldValue = fieldValueMapping.ContainsKey(itemFieldValue) ? fieldValueMapping[itemFieldValue] : itemFieldValue; 81 } 82 83 return itemFieldValue; 84 } 85 86 private bool GetDefaultOrVariantGroupValue(string variantGroupId, string itemField) 87 { 88 bool itemFieldValue = Model.Item.GetBoolean(itemField); 89 90 // If no variantGroup (i.e. Visual Editor), return default value 91 if (string.IsNullOrEmpty(variantGroupId)) return itemFieldValue; 92 93 string showVariantGroups = Model.Item.GetString("ShowVariantGroupOptions", "all"); 94 var selectedVariantGroupsList = !string.IsNullOrEmpty(Model.Item.GetRawValueString("VariantGroups")) ? Model.Item.GetItems("VariantGroups") : new List<Dynamicweb.Frontend.ItemViewModel>(); 95 // If no exceptions or settings are all the same, return default value 96 if (showVariantGroups == "all" || selectedVariantGroupsList == null || !selectedVariantGroupsList.Any()) return itemFieldValue; 97 98 // Get specific value for variant group 99 foreach (var selectedVariantGroupListItem in selectedVariantGroupsList) 100 { 101 var variantGroups = selectedVariantGroupListItem.GetRawValueString("VariantGroups").Split(','); 102 if (!variantGroups.Any(s => s.Equals(variantGroupId))) continue; 103 104 itemFieldValue = selectedVariantGroupListItem.GetBoolean(itemField); 105 } 106 107 return itemFieldValue; 108 } 109 } 110 111 @{ 112 ProductViewModel product = null; 113 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails")) 114 { 115 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"]; 116 } 117 else if (Pageview.Page.Item["DummyProduct"] != null && Pageview.IsVisualEditorMode) 118 { 119 var pageViewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(Pageview.Page); 120 ProductListViewModel productList = pageViewModel.Item.GetValue("DummyProduct") != null ? pageViewModel.Item.GetValue("DummyProduct") as ProductListViewModel : new ProductListViewModel(); 121 122 if (productList?.Products is object) 123 { 124 product = productList.Products[0]; 125 } 126 } 127 } 128 129 @if ((product is object)) 130 { 131 bool hideGroupHeaders = Model.Item.GetBoolean("HideGroupHeaders"); 132 var productVariantGroups = product.VariantGroups(); 133 134 if (productVariantGroups.Any()) 135 { 136 string[] variantId = product.VariantId.Split('.'); 137 int groupNumber = 1; 138 139 string baseUrl = $"Default.aspx?ID={GetPageIdByNavigationTag("Shop")}&GroupID={product.PrimaryOrDefaultGroup.Id}&ProductID={product.Id}"; 140 string variantUrl = ""; 141 if (!string.IsNullOrEmpty(product.VariantId)) 142 { 143 variantUrl = Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl($"Default.aspx?ID={GetPageIdByNavigationTag("Shop")}&GroupID={product.PrimaryOrDefaultGroup.Id}&ProductID={product.Id}&VariantID={product.VariantId}"); 144 } 145 146 Dictionary<string, string> variantImages = new Dictionary<string, string>(); 147 variantImages = GetVariantImages(product.VariantInfo.VariantInfo, variantImages); 148 149 <form class="d-flex flex-column gap-2 js-variant-selector item_@Model.Item.SystemName.ToLower()" data-combinations="@string.Join(",", product.VariantCombinations())" data-base-url="@baseUrl" data-friendly-url="@variantUrl"> 150 @foreach (var variantGroup in productVariantGroups) 151 { 152 VariantGroupViewModel group = variantGroup; 153 string variantGroupLayout = GetLayoutForVariantGroup(variantGroup.Id); 154 string horizontalAlign = GetDefaultOrVariantGroupValue(variantGroup.Id, "HorizontalAlignment", "", new Dictionary<string, string> { { "center", "justify-content-center" }, { "end", "justify-content-end" } }); 155 string horizontalTextAlign = GetDefaultOrVariantGroupValue(variantGroup.Id, "HorizontalAlignment", "", new Dictionary<string, string> { { "center", "text-center" }, { "end", "text-end" } }); 156 bool showSelectedOptionName = GetDefaultOrVariantGroupValue(variantGroup.Id, "ShowSelectedOptionName"); 157 158 <div> 159 @if (!hideGroupHeaders) 160 { 161 <h3 class="h6 @horizontalTextAlign"> 162 @group.Name 163 164 @if (showSelectedOptionName) 165 { 166 string selectedOptionName = group.Options.FirstOrDefault(opt => variantId.Contains(opt.Id))?.Name ?? string.Empty; 167 <span class="fw-light px-1 swift-selected-option-name">@selectedOptionName</span> 168 } 169 </h3> 170 } 171 <div class="d-flex gap-2 @horizontalAlign flex-wrap js-variant-group" data-group-id="@groupNumber"> 172 @if (variantGroupLayout == "button") 173 { 174 // foreach (var option in group.Options) 175 // foreach (var option in group.Options.OrderBy(x => x.Name)) 176 // test for new sort 177 // string r1 = "0000000"+Regex.Match(option.Name,@"\d+").ToString(); 178 // string r2 = Regex.Replace(option.Name,@"\d+",r1.Substring(r1.Length-8)); 179 180 181 foreach (var option in group.Options.OrderBy(x => Regex.Replace(x.Name, @"\d+", i => i.Value.PadLeft(7,'0')))){ 182 183 184 185 186 string active = variantId != null && variantId.Contains(option.Id) ? "active" : ""; 187 string buttonId = $"{product.Id}_{option.Id}_{Pageview.CurrentParagraph.ID}"; 188 string contrastColor = string.Empty; 189 string optionLayout = optionLayout = GetDefaultOrVariantGroupValue(variantGroup.Id, "ButtonLayout", "rounded-circle", new Dictionary<string, string> { { "round", "rounded-circle" }, { "square", "" } }); 190 var displayType = group.DisplayType; 191 192 switch (displayType) 193 { 194 case VariantGroupDisplayType.VariantColor: 195 contrastColor = GetContrastColor(option.Color); 196 <button type="button" class="btn colorbox @optionLayout d-inline-block variant-option border js-variant-option @active" style="background-color: @option.Color; --variantoption-check-color: @contrastColor" onclick="swift.VariantSelector.OptionClick(event)" data-variant-id="@option.Id" id="@buttonId"> 197 <span class="visually-hidden">@option.Color</span> 198 </button> 199 break; 200 case VariantGroupDisplayType.VariantImage: 201 string variantImage = string.Empty; 202 if (variantImages.TryGetValue(option.Id, out variantImage)) 203 { 204 <button type="button" class="btn p-0 d-inline-block @optionLayout variant-option js-variant-option @active" onclick="swift.VariantSelector.OptionClick(event)" data-variant-id="@option.Id" id="@(product.Id)_@(option.Id)_@Pageview.CurrentParagraph.ID"> 205 <img class="@optionLayout" src="/Admin/Public/GetImage.ashx?image=@(variantImage)&width=42&format=webp"> 206 </button> 207 } 208 else 209 { 210 <button type="button" class="btn btn-secondary d-inline-block variant-option js-variant-option @active" onclick="swift.VariantSelector.OptionClick(event)" data-variant-id="@option.Id" id="@(product.Id)_@(option.Id)_@Pageview.CurrentParagraph.ID"> 211 @option.Name 212 </button> 213 } 214 215 break; 216 case VariantGroupDisplayType.VariantName: 217 <button type="button" class="btn btn-secondary d-inline-block variant-option js-variant-option @active" onclick="swift.VariantSelector.OptionClick(event)" data-variant-id="@option.Id" id="@buttonId"> 218 @option.Name 219 </button> 220 break; 221 case VariantGroupDisplayType.VariantOptionImage: 222 <button type="button" class="btn p-0 d-inline-block @optionLayout variant-option js-variant-option @active" onclick="swift.VariantSelector.OptionClick(event)" data-variant-id="@option.Id" id="@(product.Id)_@(option.Id)_@Pageview.CurrentParagraph.ID"> 223 <img class="@optionLayout" src="/Admin/Public/GetImage.ashx?image=@(option.OptionImage.Value)&width=42&format=webp"> 224 </button> 225 break; 226 default: 227 if (!string.IsNullOrEmpty(option.Color)) 228 { 229 contrastColor = GetContrastColor(option.Color); 230 <button type="button" class="btn colorbox @optionLayout d-inline-block variant-option border js-variant-option @active" style="background-color: @option.Color; --variantoption-check-color: @contrastColor" onclick="swift.VariantSelector.OptionClick(event)" data-variant-id="@option.Id" id="@buttonId"> 231 <span class="visually-hidden">@option.Color</span> 232 </button> 233 } 234 else if (!string.IsNullOrEmpty(option.Color) && !string.IsNullOrEmpty(option.Image.Value)) 235 { 236 <button type="button" class="btn p-0 d-inline-block @optionLayout variant-option js-variant-option @active" onclick="swift.VariantSelector.OptionClick(event)" data-variant-id="@option.Id" id="@buttonId"> 237 <img src="/Admin/Public/GetImage.ashx?image=@(option.Image.Value)&width=42&format=webp"> 238 </button> 239 } 240 else 241 { 242 <button type="button" class="btn btn-secondary d-inline-block variant-option js-variant-option @active" onclick="swift.VariantSelector.OptionClick(event)" data-variant-id="@option.Id" id="@buttonId"> 243 @option.Name 244 </button> 245 } 246 break; 247 } 248 } 249 } 250 else 251 { 252 <select class="form-select" id="VariantDropdown_@variantGroup.Id" aria-label="@variantGroup.Name" onchange="swift.VariantSelector.OptionClick(event)"> 253 @if (string.IsNullOrEmpty(product.VariantId)) 254 { 255 <option value="" class="variant-option js-variant-option" data-variant-id="">@Translate("Nothing selected")</option> 256 } 257 258 @foreach (var option in variantGroup.Options) 259 { 260 string active = variantId != null && variantId.Contains(option.Id) ? "active" : ""; 261 var selected = variantId != null && variantId.Contains(option.Id) ? "selected" : ""; 262 var value = $"{product.Id}_{option.Id}"; 263 264 <option value="@(value)" class="variant-option js-variant-option @active" data-variant-id="@option.Id" id="@(value)_@(Pageview.CurrentParagraph.ID)" @selected>@option.Name</option> 265 } 266 </select> 267 } 268 </div> 269 </div> 270 271 272 groupNumber++; 273 } 274 </form> 275 276 <script type="module"> 277 swift.VariantSelector.init(); 278 </script> 279 } 280 else if (Pageview.IsVisualEditorMode) 281 { 282 string horizontalAlign = GetDefaultOrVariantGroupValue("", "HorizontalAlignment", "", new Dictionary<string, string> { { "center", "justify-content-center" }, { "end", "justify-content-end" } }); 283 string horizontalTextAlign = GetDefaultOrVariantGroupValue("", "HorizontalAlignment", "", new Dictionary<string, string> { { "center", "text-center" }, { "end", "text-end" } }); 284 285 <form class="d-flex flex-column js-variant-selector item_@Model.Item.SystemName.ToLower()" data-combinations="VO1,VO2,VO3,VO4"> 286 <div> 287 @if (!hideGroupHeaders) 288 { 289 <h3 class="h6 @horizontalTextAlign">@Translate("Sizes")</h3> 290 } 291 <div class="mb-3 @horizontalAlign js-variant-group" data-group-id="0"> 292 <button type="button" class="btn btn-secondary d-inline-block mb-2 variant-option js-variant-option" onclick="swift.VariantSelector.OptionClick(event)" data-variant-id="VO1" id="@(product.Id)_VO1_@Pageview.CurrentParagraph.ID">S</button> 293 <button type="button" class="btn btn-secondary d-inline-block mb-2 variant-option js-variant-option" onclick="swift.VariantSelector.OptionClick(event)" data-variant-id="VO2" id="@(product.Id)_VO2_@Pageview.CurrentParagraph.ID">M</button> 294 <button type="button" class="btn btn-secondary d-inline-block mb-2 variant-option js-variant-option" onclick="swift.VariantSelector.OptionClick(event)" data-variant-id="VO3" id="@(product.Id)_VO3_@Pageview.CurrentParagraph.ID">L</button> 295 <button type="button" class="btn btn-secondary d-inline-block mb-2 variant-option js-variant-option" onclick="swift.VariantSelector.OptionClick(event)" data-variant-id="VO4" id="@(product.Id)_VO4_@Pageview.CurrentParagraph.ID">XL</button> 296 </div> 297 </div> 298 </form> 299 300 <script type="module"> 301 swift.VariantSelector.init(); 302 </script> 303 } 304 } 305 else if (Pageview.IsVisualEditorMode) 306 { 307 <div class="alert alert-dark m-0" role="alert"> 308 <span>@Translate("No products available")</span> 309 </div> 310 } 311
Error executing template "Designs/Swift/Paragraph/Swift_ProductStock.cshtml" System.Data.SqlClient.SqlException (0x80131904): A connection was successfully established with the server, but then an error occurred during the pre-login handshake. (provider: SSL Provider, error: 0 - The handle specified is invalid) ---> System.ComponentModel.Win32Exception (0x80004005): The handle specified is invalid at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection) at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection) at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection) at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions) at System.Data.SqlClient.SqlConnection.TryOpenInner(TaskCompletionSource`1 retry) at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry) at System.Data.SqlClient.SqlConnection.Open() at Dynamicweb.Data.DatabaseConnectionProvider.CreateConnection(Boolean open) at Dynamicweb.Data.Database.CreateConnection() at Dynamicweb.Data.Database.CreateDataReader(CommandBuilder commandBuilder, IDbConnection connection, IDbTransaction transaction, Int32 commandTimeout) at Dynamicweb.Ecommerce.Products.ProductRepository.GetProductsBySql(CommandBuilder query, Boolean doRefactoring, Boolean bulkFill, Boolean useAssortments) at Dynamicweb.Ecommerce.Products.ProductRepository.GetAllVariantProducts(IEnumerable`1 productIds, String productLanguageId) at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.GetBulkVariants(IEnumerable`1 productIds, String languageId) at System.Lazy`1.CreateValue() at System.Lazy`1.LazyInitValue() at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.<>c__DisplayClass3_1.<BulkCreateView>b__6() 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_13f25aac779b47c7aab5cefd987a0732.Execute() in D:\dynamicweb.net\Solutions\Flex Media\danzafe.cloud.dynamicweb-cms.com\files\Templates\Designs\Swift\Paragraph\Swift_ProductStock.cshtml:line 188 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:1b12ce29-ad47-4859-afb1-e524b2ca4ae2 Error Number:-2146893055,State:0,Class:20
1 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.ParagraphViewModel> 2 @using Dynamicweb.Ecommerce.ProductCatalog 3 @using Dynamicweb.Ecommerce.Stocks 4 @using Dynamicweb.Ecommerce.Products 5 @using Dynamicweb.Ecommerce 6 @using System 7 8 9 @{ 10 ProductViewModel product = null; 11 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails")) 12 { 13 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"]; 14 } 15 else if (Pageview.Page.Item["DummyProduct"] != null && Pageview.IsVisualEditorMode) 16 { 17 var pageViewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(Pageview.Page); 18 ProductListViewModel productList = pageViewModel.Item.GetValue("DummyProduct") != null ? pageViewModel.Item.GetValue("DummyProduct") as ProductListViewModel : new ProductListViewModel(); 19 20 if (productList?.Products is object) 21 { 22 product = productList.Products[0]; 23 } 24 } 25 26 bool isErpConnectionDown = !Dynamicweb.Core.Converter.ToBoolean(Dynamicweb.Context.Current.Items["IsWebServiceConnectionAvailable"]); 27 bool hideStock = Model.Item.GetBoolean("HideStockState") || (Pageview.AreaSettings.GetBoolean("ErpDownHideStock") && isErpConnectionDown); 28 } 29 30 @if (product is object && !hideStock) 31 { 32 //bool IsNeverOutOfStock = product.NeverOutOfstock; 33 bool IsNeverOutOfStock = false; 34 35 string horizontalAlign = Model.Item.GetRawValueString("HorizontalAlignment", ""); 36 horizontalAlign = horizontalAlign == "center" ? "text-center" : horizontalAlign; 37 horizontalAlign = horizontalAlign == "end" ? "text-end" : horizontalAlign; 38 bool hasExpectedDelivery = product.ExpectedDelivery != null && product.ExpectedDelivery > DateTime.Now; 39 string expectedDeliveryDate = product.ExpectedDelivery?.ToShortDateString() ?? ""; 40 41 string liveInfoClass = ""; 42 string productInfoFeed = ""; 43 bool isLazyLoadingForProductInfoEnabled = Dynamicweb.Core.Converter.ToBoolean(Dynamicweb.Context.Current.Items["IsLazyLoadingForProductInfoEnabled"]); 44 45 46 if (!IsNeverOutOfStock) 47 { 48 string deliveryLabel = !string.IsNullOrEmpty(product.StockDeliveryText) ? $"{product.StockDeliveryText}" : ""; 49 deliveryLabel += !string.IsNullOrEmpty(product.StockDeliveryValue) ? $" {product.StockDeliveryValue}" : ""; 50 51 52 string firstUnitId = product?.UnitOptions?.FirstOrDefault() != null ? product.UnitOptions.FirstOrDefault().Id : ""; 53 string defaultUnitId = !string.IsNullOrEmpty(product.DefaultUnitId) ? product.DefaultUnitId : firstUnitId; 54 string unitId = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.Form.Get("UnitId")) ? Dynamicweb.Context.Current.Request.Form.Get("UnitId") : defaultUnitId; 55 56 var reserveMode = Dynamicweb.Ecommerce.Frontend.Cart.ProductReserve.Mode; 57 double? reservedAmount = 0; 58 if (reserveMode == Dynamicweb.Ecommerce.Frontend.Cart.ProductReserveMode.AddToCart) 59 { 60 reservedAmount = Dynamicweb.Ecommerce.Frontend.Cart.ProductReserve.GetReservedAmount(product.Id, product.VariantId, 0, unitId); 61 } 62 double? currentStockLevel = product.StockLevel - reservedAmount; 63 64 string stockStateLabel = currentStockLevel > 0 ? Translate("In stock") : Translate("Out of stock"); 65 stockStateLabel = !string.IsNullOrEmpty(product.StockStatus) ? product.StockStatus : stockStateLabel; 66 67 string stockStateCss = currentStockLevel > 0 ? "text-success" : "text-danger"; 68 string stockStateIconCss = currentStockLevel > 0 ? "bg-success" : "bg-danger"; 69 70 string stockLabel = ""; 71 string stockLabelWebshop = Translate("In local stock"); 72 string stockLabelSupplier = Translate("In remote stock"); 73 string deliveryLabelSupplier = Translate("1-2 days delivery time from remote warehouse"); 74 75 var todaysDate = DateTime.Today; 76 // var todaysDate = DateTime.Now.AddDays(+1); 77 var parameterDate = product.ExpectedDelivery; 78 string ExpDelivery = ""; 79 80 if(parameterDate >= todaysDate){ 81 ExpDelivery = string.Format("{0:dd/MM/yyyy}", product.ExpectedDelivery); 82 } 83 // PRODUCTEXPECTEDDELIVERY "Forventes på lager den" 84 85 double StockWebshop = 0; 86 double StockSupplier = 0; 87 88 89 Dictionary<string, FieldValueViewModel> fields = product.ProductFields; 90 91 string supplierDeliveryTime = ""; 92 93 foreach (var field in fields) { 94 95 96 if (field.Value.SystemName == "CDLevLtid"){ 97 supplierDeliveryTime = field.Value?.Value != null ? field.Value.Value.ToString() : ""; 98 99 } 100 101 } 102 103 104 105 //Product productObject = Services.Products.GetProductById(product.Id, product.VariantId, Pageview.Area.EcomLanguageId); 106 //var stockLocations = Dynamicweb.Ecommerce.Stocks.StockService.GetStockLocation(1); 107 //Product productObject = Services.Products.GetProductById(product.Id, product.VariantId, product.LanguageId); 108 IEnumerable<StockLocation> stockLocations = Services.StockService.GetStockLocations(); 109 //double unitStock = productObject.GetUnitStock(stockLocation, unitId); 110 //if (stockLocations.Any() && !string.IsNullOrEmpty(product.VariantId)) 111 //{ 112 // foreach (var stockLocation in stockLocations) 113 // { 114 115 // if (stockLocation.ID == 1) 116 // { 117 // StockWebshop = productObject.GetUnitStock(stockLocation); 118 119 // } 120 // if (stockLocation.ID == 2) 121 // { 122 // StockSupplier = productObject.GetUnitStock(stockLocation); 123 124 // } 125 // } 126 //} 127 //else 128 //{ 129 // foreach (var unit in product.StockUnits) 130 // { 131 // if (unit.StockLocationId == 1) { StockWebshop = unit.StockLevel; } 132 // if (unit.StockLocationId == 2) { StockSupplier = unit.StockLevel; } 133 // } 134 //} 135 136 137 var stockUnits = Dynamicweb.Ecommerce.Services.StockService.GetStockUnits(product.Id, product.VariantId).ToList(); 138 if (stockUnits.Any()) 139 { 140 var webShopStockUnit = stockUnits.FirstOrDefault(su => su.StockLocationId == 1); 141 if (webShopStockUnit != null) 142 { 143 StockWebshop = webShopStockUnit.StockQuantity; 144 145 } 146 var supplierStockUnit = stockUnits.FirstOrDefault(su => su.StockLocationId == 2); 147 if (supplierStockUnit != null) 148 { 149 StockSupplier = supplierStockUnit.StockQuantity; 150 } 151 } 152 153 154 155 if (StockWebshop > 0){ 156 157 currentStockLevel = StockWebshop; 158 stockLabel = Translate("In stock"); 159 deliveryLabel = ""; 160 stockStateCss = "text-success"; 161 162 } else if (StockSupplier > 0){ 163 164 currentStockLevel = StockSupplier; 165 stockLabel = Translate("In stock"); 166 deliveryLabel = Translate("1-2 days delivery time from remote warehouse"); 167 stockStateCss = "text-success"; 168 169 } else{ 170 171 currentStockLevel = 0; 172 stockLabel = Translate("Out of stock"); 173 deliveryLabel = supplierDeliveryTime + Translate(" days delivery time"); 174 stockStateCss = "text-danger"; 175 176 177 } 178 179 180 181 182 <div class="js-stock-state @horizontalAlign item_@Model.Item.SystemName.ToLower()"> 183 <div class="small"> 184 185 @{ 186 bool disableShowStock = false; 187 188 if (product.VariantInfo.VariantInfo != null && string.IsNullOrEmpty(product.VariantId)){ 189 disableShowStock = true; 190 } 191 } 192 193 194 195 196 @if (!Model.Item.GetBoolean("HideInventory") && !disableShowStock) 197 { 198 199 @* 200 if (currentStockLevel > 0){ 201 <span class="@stockStateCss js-text-stock">@currentStockLevel</span> 202 <span class="@stockStateCss">@stockLabel</span> 203 <div class="opacity-75">@deliveryLabel</div> 204 } else { 205 <div class="opacity-75">@deliveryLabel</div> 206 } 207 208 <hr> 209 *@ 210 211 if(StockWebshop>0){ 212 <span class="@stockStateCss js-text-stock">@StockWebshop</span> 213 <span class="@stockStateCss">@stockLabelWebshop</span> 214 } 215 if(StockWebshop>0 && StockSupplier>0){ 216 <span class="@stockStateCss">@Translate("and")</span> 217 } 218 if(StockSupplier>0){ 219 <span class="@stockStateCss js-text-stock">@StockSupplier</span> 220 <span class="@stockStateCss">@stockLabelSupplier</span> 221 if(StockWebshop<=0){ 222 <div class="opacity-75">@deliveryLabelSupplier</div> 223 } 224 } 225 if(StockWebshop<=0 && StockSupplier<=0){ 226 <div class="opacity-75">@deliveryLabel</div> 227 } 228 229 230 } 231 @if(!string.IsNullOrEmpty(ExpDelivery)){ 232 <div class="fs-6 fw-bold"><br>@Translate("Expected delivery day", "Forventes på lager den") @ExpDelivery</div> 233 } 234 235 236 237 </div> 238 239 240 </div> 241 242 } 243 else if (Pageview.IsVisualEditorMode) 244 { 245 <div class="alert alert-info">@Translate("No products available")</div> 246 } 247 } 248
Error executing template "Designs/Swift/Paragraph/Swift_ProductAddToCart.cshtml" System.Data.SqlClient.SqlException (0x80131904): A connection was successfully established with the server, but then an error occurred during the pre-login handshake. (provider: SSL Provider, error: 0 - The handle specified is invalid) ---> System.ComponentModel.Win32Exception (0x80004005): The handle specified is invalid at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection) at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection) at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection) at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions) at System.Data.SqlClient.SqlConnection.TryOpenInner(TaskCompletionSource`1 retry) at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry) at System.Data.SqlClient.SqlConnection.Open() at Dynamicweb.Data.DatabaseConnectionProvider.CreateConnection(Boolean open) at Dynamicweb.Data.Database.CreateConnection() at Dynamicweb.Data.Database.CreateDataReader(CommandBuilder commandBuilder, IDbConnection connection, IDbTransaction transaction, Int32 commandTimeout) at Dynamicweb.Ecommerce.Products.ProductRepository.GetProductsBySql(CommandBuilder query, Boolean doRefactoring, Boolean bulkFill, Boolean useAssortments) at Dynamicweb.Ecommerce.Products.ProductRepository.GetAllVariantProducts(IEnumerable`1 productIds, String productLanguageId) at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.GetBulkVariants(IEnumerable`1 productIds, String languageId) at System.Lazy`1.CreateValue() at System.Lazy`1.LazyInitValue() at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.<>c__DisplayClass3_1.<BulkCreateView>b__6() 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_22a35ceffe5842628a3e5af0c4ab14eb.Execute() in D:\dynamicweb.net\Solutions\Flex Media\danzafe.cloud.dynamicweb-cms.com\files\Templates\Designs\Swift\Paragraph\Swift_ProductAddToCart.cshtml:line 125 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:1b12ce29-ad47-4859-afb1-e524b2ca4ae2 Error Number:-2146893055,State:0,Class:20
1 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.ParagraphViewModel> 2 @using Dynamicweb.Ecommerce.ProductCatalog 3 4 @* 5 @using Dynamicweb.Ecommerce.Stocks 6 @using Dynamicweb.Ecommerce.Products 7 @using Dynamicweb.Ecommerce 8 *@ 9 10 @using Dynamicweb.Core.Encoders 11 @using Dynamicweb.Ecommerce.CustomerExperienceCenter.Favorites 12 13 @using System.Linq 14 @using Dynamicweb.Core 15 @using Dynamicweb.Environment 16 17 18 19 @{ 20 bool isDetailPage = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("ProductID")); 21 ProductViewModel product = null; 22 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails")) 23 { 24 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"]; 25 } 26 else if (Pageview.Page.Item["DummyProduct"] != null && Pageview.IsVisualEditorMode) 27 { 28 var pageViewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(Pageview.Page); 29 ProductListViewModel productList = pageViewModel.Item.GetValue("DummyProduct") != null ? pageViewModel.Item.GetValue("DummyProduct") as ProductListViewModel : new ProductListViewModel(); 30 31 if (productList?.Products is object) 32 { 33 product = productList.Products[0]; 34 } 35 } 36 37 string anonymousUsersLimitations = Pageview.AreaSettings.GetRawValueString("AnonymousUsers", ""); 38 bool anonymousUser = Pageview.User == null; 39 bool isErpConnectionDown = !Dynamicweb.Core.Converter.ToBoolean(Dynamicweb.Context.Current.Items["IsWebServiceConnectionAvailable"]); 40 bool hideAddToCart = anonymousUsersLimitations.Contains("cart") && anonymousUser || Pageview.AreaSettings.GetBoolean("ErpDownHideAddToCart") && isErpConnectionDown; 41 hideAddToCart = Pageview.IsVisualEditorMode ? false : hideAddToCart; 42 } 43 44 45 46 @if (product is object && !hideAddToCart) { 47 string horizontalAlign = Model.Item.GetRawValueString("HorizontalAlignment", ""); 48 horizontalAlign = horizontalAlign == "center" ? "justify-content-center" : horizontalAlign; 49 horizontalAlign = horizontalAlign == "end" ? "justify-content-end" : horizontalAlign; 50 horizontalAlign = horizontalAlign == "full" ? "" : horizontalAlign; 51 52 bool favoritesSelector = !string.IsNullOrEmpty(Model.Item.GetString("ShowAddToFavorites")) ? Model.Item.GetBoolean("ShowAddToFavorites") : false; 53 bool quantitySelector = !string.IsNullOrEmpty(Model.Item.GetString("ShowQuantitySelector")) ? Model.Item.GetBoolean("ShowQuantitySelector") : false; 54 bool unitsSelector = !string.IsNullOrEmpty(Model.Item.GetString("ShowUnitsSelector")) ? Model.Item.GetBoolean("ShowUnitsSelector") : false; 55 bool hideInventory = !string.IsNullOrEmpty(Model.Item.GetString("HideInventory")) ? Model.Item.GetBoolean("HideInventory") : false; 56 bool hideStockState = !string.IsNullOrEmpty(Model.Item.GetString("HideStockState")) ? Model.Item.GetBoolean("HideStockState") : false; 57 58 string buttonSize = Model.Item.GetRawValueString("ButtonSize", "regular"); 59 string inputSize = string.Empty; 60 61 Dictionary<string, FieldValueViewModel> fields = product.ProductFields; 62 63 64 switch (buttonSize) 65 { 66 case "small": 67 inputSize = " input-group-sm"; 68 buttonSize = " btn-sm"; 69 break; 70 case "regular": 71 buttonSize = string.Empty; 72 break; 73 case "large": 74 inputSize = " input-group-lg"; 75 buttonSize = " btn-lg"; 76 break; 77 } 78 79 80 81 string iconPath = "/Files/icons/"; 82 string url = "/Default.aspx?ID=" + (GetPageIdByNavigationTag("CartService")); 83 if (!url.Contains("LayoutTemplate")) 84 { 85 url += url.Contains("?") ? "&LayoutTemplate=Swift_MiniCart.cshtml" : "?LayoutTemplate=Swift_MiniCart.cshtml"; 86 } 87 88 bool isLazyLoadingForProductInfoEnabled = Dynamicweb.Core.Converter.ToBoolean(Dynamicweb.Context.Current.Items["IsLazyLoadingForProductInfoEnabled"]); 89 string disableAddToCart = (product.StockLevel <= 0) ? "disabled" : ""; 90 bool isNeverOutOfStock = product.NeverOutOfstock; 91 disableAddToCart = isNeverOutOfStock && !isLazyLoadingForProductInfoEnabled ? "" : disableAddToCart; 92 93 string whenVariantsExist = Model.Item.GetRawValueString("WhenVariantsExist", "hide"); 94 95 string flexFill = Model.Item.GetRawValueString("HorizontalAlignment", "") == "full" ? "flex-fill" : ""; 96 string fullWidth = Model.Item.GetRawValueString("HorizontalAlignment", "") == "full" ? "w-100" : ""; 97 string addToCartIcon = Model.Item.GetRawValueString("Icon", iconPath + "shopping-cart.svg"); 98 string addToCartLabel = !addToCartIcon.Contains("_none") ? $"<span class=\"icon-2\">{ReadFile(addToCartIcon)}</span>" : ""; 99 addToCartLabel += !addToCartIcon.Contains("_none") && !Model.Item.GetBoolean("HideButtonText") ? " " : ""; 100 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>" : ""; 101 102 103 string Surface = ""; 104 string hasLockKeyCode = ""; 105 int CylinderCount = 1; 106 bool KeyCutField = false; 107 foreach (var field in fields) { 108 if (field.Value.SystemName == "HasLockKeyCode"){ 109 hasLockKeyCode = field.Value?.Value != null ? field.Value.Value.ToString() : ""; 110 } 111 if (field.Value.SystemName == "CylinderCount"){ 112 CylinderCount = Convert.ToInt32(field.Value?.Value != null ? field.Value.Value : 1); 113 } 114 if (field.Value.SystemName == "KeyCutField"){ 115 string KeyCutField_string = field.Value?.Value != null ? field.Value.Value.ToString() : ""; 116 if(KeyCutField_string=="True"){KeyCutField = true;} 117 } 118 if (field.Value.SystemName == "Surface"){ 119 Surface = field.Value?.Value != null ? field.Value.Value.ToString() : ""; 120 } 121 } 122 if(CylinderCount<1){CylinderCount=1;} 123 <span style="display:none" id="cylindercountvalue" value="@CylinderCount"></span> 124 125 if ((product.VariantInfo.VariantInfo == null || whenVariantsExist == "disable") && isDetailPage) { 126 string unitId = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.Form.Get("UnitId")) ? Dynamicweb.Context.Current.Request.Form.Get("UnitId") : product.DefaultUnitId; 127 if (string.IsNullOrEmpty(unitId) && product?.UnitOptions != null) { 128 if (product.UnitOptions.FirstOrDefault<UnitOptionViewModel>() != null) { 129 unitId = product.UnitOptions.FirstOrDefault<UnitOptionViewModel>().Id; 130 } 131 } 132 133 134 135 // Flex 136 137 138 // IEnumerable<StockLocation> stockLocations = Services.StockService.GetStockLocations(); 139 140 double StockWebshop = 0; 141 double StockSupplier = 0; 142 var stockUnits = Dynamicweb.Ecommerce.Services.StockService.GetStockUnits(product.Id, product.VariantId).ToList(); 143 if (stockUnits.Any()) 144 { 145 var webShopStockUnit = stockUnits.FirstOrDefault(su => su.StockLocationId == 1); 146 if (webShopStockUnit != null) 147 { 148 StockWebshop = webShopStockUnit.StockQuantity; 149 150 } 151 var supplierStockUnit = stockUnits.FirstOrDefault(su => su.StockLocationId == 2); 152 if (supplierStockUnit != null) 153 { 154 StockSupplier = supplierStockUnit.StockQuantity; 155 } 156 } 157 158 double? unitStockLevel = 0; 159 160 bool HasStock = false; 161 foreach (var unitOption in product.UnitOptions){ 162 if (unitOption.StockLevel > 0){ 163 unitStockLevel = unitOption.StockLevel; 164 HasStock = true; 165 } 166 } 167 168 if (StockWebshop > 0){ 169 HasStock = true; 170 } else if (StockSupplier > 0){ 171 HasStock = true; 172 } 173 174 175 disableAddToCart = HasStock && !isLazyLoadingForProductInfoEnabled ? "" : disableAddToCart; 176 177 string minQty = product.PurchaseMinimumQuantity != 1 ? $"min=\"{product.PurchaseMinimumQuantity.ToString()}\"" : "min=\"1\""; 178 string stepQty = product.PurchaseQuantityStep > 1 ? product.PurchaseQuantityStep.ToString() : "1"; 179 string valueQty = product.PurchaseMinimumQuantity > product.PurchaseQuantityStep ? product.PurchaseMinimumQuantity.ToString() : stepQty; 180 disableAddToCart = product.VariantInfo.VariantInfo != null && string.IsNullOrEmpty(product.VariantId) ? "disabled" : disableAddToCart; 181 disableAddToCart = product.Discontinued && !product.NeverOutOfstock && !HasStock ? "disabled" : disableAddToCart; 182 183 184 185 <small style="display: none;">CylinderCount:@CylinderCount</small> 186 187 <small style="display: none;">product.Id:@product.Id product.VariantId:@product.VariantId StockWebshop:@StockWebshop HasStock:@HasStock disableAddToCart:@disableAddToCart product.StockLevel:@product.StockLevel unitStockLevel:@unitStockLevel</small> 188 189 190 // <small>@product.StockLevel</small> 191 // <small>@HasStock . @product.Discontinued . @product.NeverOutOfstock = @disableAddToCart </small> 192 // <small>@product.VariantInfo.VariantInfo</small> 193 // <small>@isDetailPage</small> 194 195 bool needKey = false; 196 string KeyGroupID = ""; 197 string KeyList = ""; 198 string DefaultKey = ""; 199 string ReCodeList = ""; 200 string DefaultReCode = ""; 201 string KeyId = ""; 202 string KeyName = ""; 203 string KeyPrice = ""; 204 string keyCode = ""; 205 string KeyWay = ""; 206 string KeyWayType = ""; 207 bool hasKeyWayNew = false; 208 // bool hasKeyWayInCart = false; //.. 209 bool hasKeyInCart = false; 210 bool hasKeyWithCodeInCart = false; 211 212 213 214 foreach (var Groups in product.Groups){ 215 // <small>@Groups.Id</small> 216 if(string.IsNullOrEmpty(KeyGroupID)){ 217 string HasKeyId = Dynamicweb.Ecommerce.Services.ProductGroups.GetGroup(Groups.Id)?.ProductGroupFieldValues.FirstOrDefault(f => f.ProductGroupField.SystemName == "KeyProductIds")?.Value.ToString(); 218 string HasReCodeId = Dynamicweb.Ecommerce.Services.ProductGroups.GetGroup(Groups.Id)?.ProductGroupFieldValues.FirstOrDefault(f => f.ProductGroupField.SystemName == "ReCodeProductIds")?.Value.ToString(); 219 if(!string.IsNullOrEmpty(HasKeyId) || !string.IsNullOrEmpty(HasReCodeId)){ 220 KeyGroupID = Groups.Id; 221 } 222 } 223 } 224 225 226 if(!string.IsNullOrEmpty(KeyGroupID)){ 227 KeyList = Dynamicweb.Ecommerce.Services.ProductGroups.GetGroup(KeyGroupID)?.ProductGroupFieldValues.FirstOrDefault(f => f.ProductGroupField.SystemName == "KeyProductIds")?.Value.ToString(); 228 ReCodeList = Dynamicweb.Ecommerce.Services.ProductGroups.GetGroup(KeyGroupID)?.ProductGroupFieldValues.FirstOrDefault(f => f.ProductGroupField.SystemName == "ReCodeProductIds")?.Value.ToString(); 229 KeyWayType = Dynamicweb.Ecommerce.Services.ProductGroups.GetGroup(KeyGroupID)?.ProductGroupFieldValues.FirstOrDefault(f => f.ProductGroupField.SystemName == "KeyWayType")?.Value.ToString(); 230 } 231 List<string> KeyCodes = new List<string>(); 232 string[] Keys = KeyList.Split(','); 233 DefaultKey = Keys[0]; 234 List<string> ReCodes = new List<string> 235 (); 236 string[] ReCode = ReCodeList.Split(','); 237 DefaultReCode = ReCode[0]; 238 239 if((KeyList.Length>0 || ReCodeList.Length>0) && isDetailPage && !KeyCutField){needKey = true;} 240 241 // else{hasLockKeyCode="";} 242 243 244 // <small>bob @needKey</small> 245 // <small>@KeyList.Length @ReCodeList.Length @KeyWayType.Length</small> 246 // <small><strong>@DefaultKey</strong></small> 247 248 // finding keycode in cart 249 if(needKey || KeyCutField){ 250 if (Dynamicweb.Ecommerce.Common.Context.Cart != null) { 251 var CartList = Dynamicweb.Ecommerce.Common.Context.Cart.OrderLines; 252 foreach (var Orderline in CartList){ 253 bool matchKey = false; 254 if(Orderline.OrderLineFieldValues.Count>0){ 255 var KeyWayObj = Orderline.OrderLineFieldValues.FirstOrDefault(fv => fv.OrderLineFieldSystemName == "KeyWayType"); 256 if(!string.IsNullOrEmpty(KeyWayObj?.Value)){KeyWay = KeyWayObj.Value;}else{KeyWay="";} 257 var keyCodeObj = Orderline.OrderLineFieldValues.FirstOrDefault(fv => fv.OrderLineFieldSystemName == "LockKeyCode"); 258 if(!string.IsNullOrEmpty(keyCodeObj?.Value)){keyCode = keyCodeObj.Value;}else{keyCode="";} 259 260 if(KeyWayType==KeyWay){ 261 matchKey = true; 262 } 263 264 } 265 foreach (var Fields in Orderline.Product.OrderLineFields){ 266 if(Fields.SystemName=="LockKeyCode" && matchKey){ 267 bool isNew = true; 268 foreach(string K in KeyCodes){if(K==keyCode){isNew=false;}} 269 if(!string.IsNullOrEmpty(keyCode) && isNew){KeyCodes.Add(keyCode);} 270 if(string.IsNullOrEmpty(keyCode)){hasKeyWayNew=true;} 271 } 272 } 273 // finding keycode in cart - end 274 275 foreach (var Key in Keys){ 276 if(Key == Orderline.ProductId && matchKey){ 277 hasKeyInCart = true; 278 if(!string.IsNullOrEmpty(keyCode)){ 279 hasKeyWithCodeInCart = true; 280 } 281 } 282 } 283 284 285 286 287 // foreach (var Fields in Orderline.Product.OrderLineFields){ 288 // if(Fields.SystemName == "KeyWayType" && matchKey){ 289 // <small style="font-size:.6em;">@Orderline.Id @Fields.Name @KeyWayType @keyCode<br/></small> 290 // } 291 // } 292 293 } 294 } 295 } 296 297 298 299 if(needKey || KeyCutField){ // options from cart 300 <datalist id="knowenkeys"> 301 @if(hasKeyWayNew){<option value="">Leave blank to match one in cart</option>} 302 @foreach(string c in KeyCodes){<option value="@c">@c</option>} 303 </datalist> 304 } 305 306 307 if(needKey && 1==2){ // test 308 <div style="position:relative; z-index:10;"> 309 <div style="font-size:.7em;color:#aaa;"> 310 <small>KeyCutField: @KeyCutField<br /></small> 311 <small>hasLockKeyCode: @hasLockKeyCode<br /></small> 312 <small>CylinderCount: @CylinderCount<br /></small> 313 <small>need key: @needKey <br/></small> 314 <small>key in cart: @hasKeyInCart <br/></small> 315 <small>key w code in cart: @hasKeyWithCodeInCart</small> 316 </div> 317 </div> 318 } 319 320 321 322 323 if(needKey && 1==2){ // select options 324 <div class="mt-1 mb-1" style="position:relative; z-index:10;"> 325 @* <label>temp: for adding to cart if recode</label>*@ 326 <select style="font-size: 0.66em;"> 327 328 329 @foreach (var Key in Keys){ 330 var KeyProduct = Dynamicweb.Ecommerce.Services.Products.GetProductById(Key,"", product.LanguageId); 331 332 if(KeyProduct != null){ 333 KeyId = KeyProduct.Id.ToString(); 334 KeyName = KeyProduct.Name.ToString(); 335 KeyPrice = KeyProduct.Price.ToString(); 336 // something = KeyProduct.ProductFieldValues.GetProductFieldValue("Width").Value.ToString(); 337 } 338 <option value="@KeyId" @if(KeyId==DefaultKey){<text>selected="selected" </text>}>@KeyName @KeyPrice</option> 339 340 // <small><br/>@KeyId @KeyName @KeyPrice </small> 341 342 } 343 344 </select> 345 </div> 346 } 347 348 if(needKey && 1==2){ 349 if (hasLockKeyCode == "True" && whenVariantsExist != "disable"){ 350 <div class="js-stock-state text-center"> 351 <div class="small">@Translate("hasLockKeyCode_text")</div> 352 </div> 353 } 354 } 355 356 357 358 359 var reserveMode = Dynamicweb.Ecommerce.Frontend.Cart.ProductReserve.Mode; 360 361 if (unitsSelector && product.UnitOptions.Count > 0) { 362 <form f=a method="post" action="/Default.aspx?ID=@(Pageview.Page.ID)&ProductId=@product.Id" id="UnitSelectorForm_@(product.Id)_@(product.VariantId)_@Model.ID"> 363 <input type="hidden" name="redirect" value="false"> 364 <input type="hidden" name="VariantID" value="@product.VariantId"> 365 <input type="hidden" name="UnitID" class="js-unit-id" value="@unitId"> 366 </form> 367 } 368 369 <div class="d-flex @horizontalAlign @fullWidth js-input-group item_@Model.Item.SystemName.ToLower()"> 370 <form f=b method="post" action="@url" class="@fullWidth" style="z-index: 1"> 371 <input type="hidden" name="redirect" value="false"> 372 <input type="hidden" name="ProductCurrency" value="@Dynamicweb.Ecommerce.Common.Context.Currency.Code"> 373 <input type="hidden" name="ProductPrice" value="@PriceViewModelExtensions.ToStringInvariant(product.Price)"> 374 <input type="hidden" name="ProductReferer" value="component_ProductAddToCart"> 375 376 @if(!needKey){ 377 <input type="hidden" name="cartcmd" value="add"> 378 <input type="hidden" name="ProductId" value="@product.Id"> 379 <input type="hidden" name="ProductName" value="@HtmlEncoder.HtmlEncode(product.Name)"> 380 <input type="hidden" name="VariantID" value="@product.VariantId"> 381 <input type="hidden" name="ProductVariantName" value="@product.VariantName"> 382 <input id="@(product.Id)_StockLocationId" type="hidden" name="StockLocationId" value=""> 383 if (quantitySelector || (!anonymousUser && product.VariantInfo.VariantInfo != null) || (!anonymousUser && favoritesSelector)) 384 { 385 <input type="hidden" id="Unit_@(product.Id)_@product.VariantId" name="UnitID" value="@unitId" /> 386 } 387 <input type="hidden" name="EcomOrderLineFieldInput_Surface" value="@Surface" /> 388 389 } 390 @if(needKey){ 391 <input name="cartcmd" value="addmulti" type="hidden" /> 392 <input type="hidden" name="ProductLoopCounter1" value="1" /> 393 <input type="hidden" name="ProductId1" value="@product.Id" /> 394 <input type="hidden" name="ProductName1" value="@product.Name" /> 395 <input type="hidden" name="VariantID1" value="@product.VariantId"> 396 <input type="hidden" name="ProductVariantName1" value="@product.VariantName" /> 397 <input id="@(product.Id)_StockLocationId" type="hidden" name="StockLocationId1" value="" /> 398 399 if (!string.IsNullOrEmpty(KeyWayType)){ 400 <input type="hidden" name="EcomOrderLineFieldInput_KeyWayType1" value="@KeyWayType" /> 401 } 402 if (quantitySelector || (!anonymousUser && product.VariantInfo.VariantInfo != null) || (!anonymousUser && favoritesSelector)) 403 { 404 <input type="hidden" id="Unit_@(product.Id)_@product.VariantId" name="UnitID1" value="@unitId" /> 405 } 406 <input type="hidden" name="EcomOrderLineFieldInput_Surface1" value="@Surface" /> 407 <input type="hidden" name="EcomOrderLineFieldInput_QuantityPrItem1" value="@CylinderCount" /> 408 409 410 411 <input type="hidden" name="ProductLoopCounter2" value="2" /> 412 <input type="hidden" name="ProductId2" value="@DefaultReCode" /> 413 <input id="Quantity2" type="hidden" name="Quantity2" value="1" disabled="" /> 414 <input type="hidden" name="EcomOrderLineFieldInput_ForProductId2" value="@product.Id" /> 415 <input type="hidden" name="EcomOrderLineFieldInput_ForProductVariantId2" value="@product.VariantId" /> 416 <input type="hidden" name="EcomOrderLineFieldInput_KeyWayType2" value="@KeyWayType" /> 417 <input type="hidden" name="EcomOrderLineFieldInput_LockKeyCode2" id="EcomOrderLineFieldInput_LockKeyCode2" value="" /> 418 419 <input type="hidden" name="ProductLoopCounter3" value="3" /> 420 <input type="hidden" name="ProductId3" value="@DefaultKey" /> 421 <input id="Quantity3" type="hidden" name="Quantity3" value="1" disabled="" /> 422 <input type="hidden" name="EcomOrderLineFieldInput_IsCodeKey3" value="True" /> 423 <input type="hidden" name="EcomOrderLineFieldInput_ForProductId3" value="@product.Id" /> 424 <input type="hidden" name="EcomOrderLineFieldInput_ForProductVariantId3" value="@product.VariantId" /> 425 <input type="hidden" name="EcomOrderLineFieldInput_KeyWayType3" value="@KeyWayType" /> 426 <input type="hidden" name="EcomOrderLineFieldInput_LockKeyCode3" id="EcomOrderLineFieldInput_LockKeyCode3" value="" /> 427 428 } 429 430 431 432 433 @if (reserveMode == Dynamicweb.Ecommerce.Frontend.Cart.ProductReserveMode.AddToCart) 434 { 435 <input type="hidden" name="GetReservedAmount" value="true"> 436 } 437 438 @if (!string.IsNullOrEmpty(product.VariantId)) 439 { 440 // <input type="hidden" name="VariantId" value="@product.VariantId"> 441 } 442 443 444 445 446 447 448 @if (!product.NeverOutOfstock) 449 { 450 <input type="hidden" name="Stock" value="@unitStockLevel" u="@unitStockLevel" p="@product.StockLevel" sw="@StockWebshop" > 451 452 <template class="js-out-of-stock-notice"> 453 <div class="modal-header"> 454 <h1 class="modal-title fs-5">@Translate("Stock limit")</h1> 455 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> 456 </div> 457 <div class="modal-body"> 458 @Translate("There are not enough products in stock. The product might be sold out or discontinued. Please adjust the quantity.") 459 </div> 460 </template> 461 } 462 463 464 465 466 467 468 469 470 @if (stepQty != "1") 471 { 472 <template class="js-step-quantity-warning"> 473 <div class="modal-header"> 474 <h1 class="modal-title fs-5">@Translate("The quantity is not valid")</h1> 475 </div> 476 <div class="modal-body"> 477 @Translate("Please select a quantity that is dividable by") @stepQty 478 </div> 479 </template> 480 } 481 @if (product.PurchaseMinimumQuantity != 1) 482 { 483 <template class="js-min-quantity-warning"> 484 <div class="modal-header"> 485 <h1 class="modal-title fs-5">@Translate("The product could not be added to the cart")</h1> 486 </div> 487 <div class="modal-body"> 488 @Translate("The quantity is not valid. You must buy at least") @product.PurchaseMinimumQuantity 489 </div> 490 </template> 491 } 492 493 494 <div class="d-flex flex-row w-100"> 495 @if (!quantitySelector) 496 { 497 if(!needKey){ 498 <input id="Quantity_@(product.Id)_@product.VariantId" class="swift_quantity_field" name="Quantity" value="@valueQty" type="hidden" @disableAddToCart> 499 } 500 if(needKey){ 501 <input id="Quantity_@(product.Id)_@product.VariantId" class="swift_quantity_field" name="Quantity1" value="@valueQty" type="hidden" @disableAddToCart> 502 } 503 } 504 505 @if (unitsSelector && product.UnitOptions.Count > 0) 506 { 507 string selectedUnitName = !string.IsNullOrEmpty(unitId) && product?.UnitOptions != null ? unitId : product.UnitOptions.FirstOrDefault<UnitOptionViewModel>().Name; 508 509 foreach (var unitOption in product.UnitOptions) 510 { 511 if (unitOption.Id == unitId) 512 { 513 selectedUnitName = unitOption.Name; 514 } 515 } 516 517 <div class="d-flex flex-column gap-2 w-100"> 518 <div class="input-group input-primary-button-group flex-nowrap@(inputSize)"> 519 @if (!anonymousUser && favoritesSelector) 520 { 521 @RenderPartial("Components/ToggleFavorite.cshtml", product) 522 } 523 524 @if (quantitySelector) 525 { 526 if(!needKey){ 527 <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> 528 } 529 if(needKey){ 530 <input id="Quantity_@(product.Id)_@product.VariantId" name="Quantity1" 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> 531 } 532 } 533 534 <button class="btn btn-secondary @flexFill dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false"> 535 @selectedUnitName 536 </button> 537 538 <ul class="dropdown-menu swift_unit-field"> 539 @foreach (var unitOption in product.UnitOptions) 540 { 541 var selectedUnit = unitOption.Id == unitId ? "selected" : ""; 542 543 <li> 544 <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'); 545 document.querySelector('#Unit_@(product.Id)_@product.VariantId').value = this.getAttribute('data-value'); 546 swift.PageUpdater.Update(document.querySelector('#UnitSelectorForm_@(product.Id)_@(product.VariantId)_@Model.ID'))"> 547 <span>@unitOption.Name</span> 548 <span> 549 @if (unitOption.StockLevel > 0) 550 { 551 if (!Model.Item.GetBoolean("HideInventory")) 552 { 553 <span class="small text-success" u=a>@unitOption.StockLevel @Translate("In stock")</span> 554 } 555 else 556 { 557 <span class="small text-success" u=b>@Translate("In stock")</span> 558 } 559 } 560 else 561 { 562 <span class="small text-danger" u=c>@Translate("Out of Stock")</span> 563 } 564 </span> 565 </button> 566 </li> 567 } 568 </ul> 569 </div> 570 <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"> 571 @if (!Model.Item.GetBoolean("HideButtonText")) 572 { 573 <span class="text-nowrap d-flex align-items-center justify-content-center gap-2"> 574 @addToCartLabel 575 </span> 576 } 577 else 578 { 579 @addToCartLabel 580 } 581 </button> 582 </div> 583 } 584 else 585 { 586 if (!anonymousUser && favoritesSelector) 587 { 588 @RenderPartial("Components/ToggleFavorite.cshtml", product) 589 } 590 591 592 <div class="input-group input-primary-button-group flex-nowrap@(inputSize)"> 593 @if (quantitySelector) 594 { 595 if(!needKey){ 596 <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> 597 } 598 if(needKey){ 599 <input id="Quantity1" name="Quantity1" value="@valueQty" step="@stepQty" @minQty class="form-control swift_quantity-field" style="min-width: 60px; max-width: 100px; z-index: 1" type="number" onchange="ReCodeQuantity();swift.Cart.UpdateOnEnterKey(event)" onkeyup="ReCodeQuantity();swift.Cart.UpdateOnEnterKey(event)" @disableAddToCart> 600 } 601 } 602 603 <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"> 604 @if (!Model.Item.GetBoolean("HideButtonText")) 605 { 606 <span class="text-nowrap d-flex align-items-center justify-content-center gap-2"> 607 @addToCartLabel 608 </span> 609 } 610 else 611 { 612 @addToCartLabel 613 } 614 </button> 615 </div> 616 } 617 </div> 618 619 620 621 @if (hasLockKeyCode == "True" && whenVariantsExist == "disable"){ 622 623 <p> </p> 624 <p><input id="LockKeyCode" name="EcomOrderLineFieldInput_ReCoding1" type="checkbox" value="true" onChange="checkboxElement(this,'KeyCodeSection');" /> <label for="LockKeyCode">@Translate("Ønsker den omkodet")</label></p> 625 626 <div id="KeyCodeSection" class="hide"> 627 @* <small style="font-size: .7em;color: #999;">@DefaultKey @DefaultReCode</small>*@ 628 629 <div class="mt-4 input-group"> 630 <label for="EcomOrderLineFieldInput_LockKeyCode1">@Translate("Ønsker du låsen/låsene kodet til eksisterende system") 631 <br /> 632 <input list="knowenkeys" style="max-width: 26rem;" class="form-control" type="text" name="EcomOrderLineFieldInput_LockKeyCode1" id="EcomOrderLineFieldInput_LockKeyCode1" onchange="matchCartOption(this)" onkeyup="matchCartOption(this)"> 633 </label> 634 635 </div> 636 637 </div> 638 639 <script> 640 641 // var CylinderCount = @CylinderCount; 642 var CylinderCount = document.getElementById("cylindercountvalue").getAttribute("value"); 643 // alert(document.getElementById("cylindercountvalue").getAttribute("value")) 644 645 function checkboxElement(a,b){ 646 c=document.getElementById(b).classList; 647 if(a.checked){c.remove("hide");}else{c.add("hide");} 648 wantReCode(); 649 } 650 651 function wantReCode(){ 652 a=document.getElementById("LockKeyCode").checked; 653 if(a){ 654 document.getElementById("Quantity2").disabled=false; 655 document.getElementById("EcomOrderLineFieldInput_LockKeyCode1").disabled=false; 656 657 }else{ 658 document.getElementById("Quantity2").disabled=true; 659 document.getElementById("EcomOrderLineFieldInput_LockKeyCode1").disabled=true; 660 } 661 ReCodeQuantity(); 662 matchCartOption(document.getElementById('EcomOrderLineFieldInput_LockKeyCode1')); 663 } 664 665 function matchCartOption(a){ 666 m=false;l=a.getAttribute("list");v=a.value; 667 b=document.getElementById(l).getElementsByTagName("option"); 668 c=document.getElementById("LockKeyCode").checked; 669 document.getElementById("EcomOrderLineFieldInput_LockKeyCode2").value=v; 670 document.getElementById("EcomOrderLineFieldInput_LockKeyCode3").value=v; 671 for(i=0;i<b.length;i++){if(b[i].value==v){m=true;}} 672 if(c && !m){ 673 // if wants recode and no match in cart 674 // enable "add key to cart" 675 document.getElementById("Quantity3").disabled=false; 676 }else{ 677 // disable "add key to cart" 678 document.getElementById("Quantity3").disabled=true; 679 } 680 ReCodeQuantity(); 681 } 682 683 function ReCodeQuantity(){ 684 var Qcount = document.getElementById("Quantity1").value * document.getElementById("cylindercountvalue").getAttribute("value"); 685 // alert(Qcount) 686 687 // document.getElementById("Quantity2").value=document.getElementById("Quantity1").value; 688 document.getElementById("Quantity2").value=Qcount; 689 690 } 691 692 document.addEventListener("DOMContentLoaded", function(){ 693 checkboxElement(document.getElementById('LockKeyCode'),'KeyCodeSection'); 694 }); 695 696 ReCodeQuantity(); 697 698 699 // checkboxElement(document.getElementById('LockKeyCode'),'KeyCodeSection'); 700 // wantReCode(); 701 // ReCodeQuantity(); 702 // matchCartOption(document.getElementById('EcomOrderLineFieldInput_LockKeyCode1')); 703 // alert("bob") 704 705 </script> 706 <style>.hide{display: none;}</style> 707 708 709 } 710 711 712 713 @if (KeyCutField && whenVariantsExist == "disable"){ 714 <div id="KeyCodeSection"> 715 716 <div class="mt-4 input-group"> 717 <label for="EcomOrderLineFieldInput_LockKeyCode">@Translate("Ønsker du nøglen/nøglernerne kodet til eksisterende system") 718 <br /> 719 <input list="knowenkeys" style="max-width: 26rem;" class="form-control" type="text" name="EcomOrderLineFieldInput_LockKeyCode" id="EcomOrderLineFieldInput_LockKeyCode"> 720 <input type="hidden" name="EcomOrderLineFieldInput_KeyWayType" value="@KeyWayType" /> 721 </label> 722 </div> 723 724 </div> 725 726 727 } 728 729 730 731 </form> 732 </div> 733 } else if (whenVariantsExist == "modal") { 734 string buttonText = Translate("Select"); 735 string variantId = !string.IsNullOrWhiteSpace(product.VariantId) ? product.VariantId : product.DefaultVariantId; 736 737 string variantSelectorServicePageId = !string.IsNullOrEmpty(Model.Item.GetString("VariantSelectorServicePageId")) ? Model.Item.GetLink("VariantSelectorServicePageId").PageId.ToString() : ""; 738 variantSelectorServicePageId = variantSelectorServicePageId != "" ? variantSelectorServicePageId : GetPageIdByNavigationTag("VariantSelectorService").ToString(); 739 740 // Flex 741 if (hasLockKeyCode == "True"){ 742 <div class="js-stock-state text-center"> 743 <div class="small">@Translate("hasLockKeyCode_text")</div> 744 </div> 745 } 746 747 748 <div class="d-flex @horizontalAlign w-100 item_@Model.Item.SystemName.ToLower()"> 749 750 751 752 @if (!anonymousUser && favoritesSelector) 753 { 754 @RenderPartial("Components/ToggleFavorite.cshtml", product) 755 } 756 <form f=c action="/Default.aspx?ID=@variantSelectorServicePageId" data-response-target-element="DynamicModalContent" data-preloader="inline" style="z-index: 1" class="@fullWidth"> 757 <input type="hidden" name="ProductID" value="@product.Id"> 758 <input type="hidden" name="VariantID" value="@variantId"> 759 <input type="hidden" name="QuantitySelector" value="@quantitySelector.ToString()"> 760 <input type="hidden" name="HideInventory" value="@hideInventory.ToString()"> 761 <input type="hidden" name="HideStockState" value="@hideStockState.ToString()"> 762 <input type="hidden" name="VariantSelectorServicePage" value="@variantSelectorServicePageId"> 763 <input type="hidden" name="ViewType" value="ModalContent"> 764 @if (isLazyLoadingForProductInfoEnabled) 765 { 766 @* If lazy loading is enabled, bypass it because we're loading a modal window, so render everything as if it was server-side *@ 767 <input type="hidden" name="getproductinfo" value="true"> 768 } 769 770 @{ 771 string link = product.GetProductLink(GetPageIdByNavigationTag("Shop"), false); 772 string googleTagManagerID = Pageview.AreaSettings.GetString("GoogleTagManagerID"); 773 string googleAnalyticsMeasurementID = Pageview.AreaSettings.GetString("GoogleAnalyticsMeasurementID"); 774 bool allowTracking = true; 775 if (CookieManager.IsCookieManagementActive) 776 { 777 var cookieOptInLevel = CookieManager.GetCookieOptInLevel(); 778 allowTracking = cookieOptInLevel == CookieOptInLevel.All || (cookieOptInLevel == CookieOptInLevel.Functional && CookieManager.GetCookieOptInCategories().Contains("Statistical")); 779 } 780 allowTracking = true; 781 782 string clickProductLink = string.Empty; 783 if ((!string.IsNullOrWhiteSpace(googleAnalyticsMeasurementID) || !string.IsNullOrWhiteSpace(googleTagManagerID)) && allowTracking) 784 { 785 clickProductLink = "onclick=\"return clickProductLink('" + @product.Id + "', '" + @product.Name + "', '" + @product.VariantName + "', '" + @product.Price.CurrencyCode + "', '" + @product.Price.Price + "')\""; 786 } 787 788 789 790 791 } 792 793 <a type="button" href="@(link)" class="btn btn-primary@(buttonSize) @fullWidth" title="@Translate("Select")" id="OpenVariantSelectorModal@(product.Id)_@Pageview.CurrentParagraph.ID">@buttonText</a> 794 795 796 @*<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> 797 *@ 798 799 800 801 802 </form> 803 </div> 804 } 805 } else if (Pageview.IsVisualEditorMode) { 806 <div class="alert alert-dark m-0">@Translate("No products available")</div> 807 } 808
Snabb leverans på lagervaror Leverans med DPD och Postnord Över 120 000 nöjda kunder |
8-5767990001
- EAN
- 4014549381335
- Tillverkarens artikelnummer
- 584100
Error executing template "Designs/Swift/Paragraph/Swift_ProductDetailsMediaTable.cshtml" System.Data.SqlClient.SqlException (0x80131904): A connection was successfully established with the server, but then an error occurred during the pre-login handshake. (provider: SSL Provider, error: 0 - The handle specified is invalid) ---> System.ComponentModel.Win32Exception (0x80004005): The handle specified is invalid at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection) at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection) at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection) at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions) at System.Data.SqlClient.SqlConnection.TryOpenInner(TaskCompletionSource`1 retry) at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry) at System.Data.SqlClient.SqlConnection.Open() at Dynamicweb.Data.DatabaseConnectionProvider.CreateConnection(Boolean open) at Dynamicweb.Data.Database.CreateConnection() at Dynamicweb.Data.Database.CreateDataReader(CommandBuilder commandBuilder, IDbConnection connection, IDbTransaction transaction, Int32 commandTimeout) at Dynamicweb.Ecommerce.Products.DetailRepository.GetInheritedDetailsBulk(List`1 productIds, String detailType, Boolean onlyDefault) at Dynamicweb.Ecommerce.Products.DetailService.GetDetailsBulk(IEnumerable`1 productKeys, String detailType, Boolean excludeDefaultImage) at System.Lazy`1.CreateValue() at System.Lazy`1.LazyInitValue() at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.GetDetailsByGroupId(Product product, Lazy`1 details) at System.Lazy`1.CreateValue() at System.Lazy`1.LazyInitValue() at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.CreateView(AssetCategoryViewModelSettings settings, Product product, Lazy`1 details) 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_457d921174194192b3cdcf0c568215d1.Execute() in D:\dynamicweb.net\Solutions\Flex Media\danzafe.cloud.dynamicweb-cms.com\files\Templates\Designs\Swift\Paragraph\Swift_ProductDetailsMediaTable.cshtml:line 71 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:1b12ce29-ad47-4859-afb1-e524b2ca4ae2 Error Number:-2146893055,State:0,Class:20
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[] supportedImageFormats { get; set; } 9 public string[] supportedVideoFormats { get; set; } 10 public string[] supportedDocumentFormats { get; set; } 11 public string[] allSupportedFormats { get; set; } 12 13 public class RatioSettings 14 { 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() 22 { 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 30 ratioSettings.Ratio = ratio; 31 ratioSettings.CssClass = cssClass; 32 ratioSettings.CssVariable = cssVariable; 33 ratioSettings.Fill = ratio == "fill" ? " h-100" : ""; 34 35 return ratioSettings; 36 } 37 } 38 39 @{ 40 @* Get the product data *@ 41 ProductViewModel product = null; 42 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails")) 43 { 44 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"]; 45 } 46 else if (Pageview.Page.Item["DummyProduct"] != null && Pageview.IsVisualEditorMode) 47 { 48 var pageViewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(Pageview.Page); 49 ProductListViewModel productList = pageViewModel.Item.GetValue("DummyProduct") != null ? pageViewModel.Item.GetValue("DummyProduct") as ProductListViewModel : new ProductListViewModel(); 50 51 if (productList?.Products is object) 52 { 53 product = productList.Products[0]; 54 } 55 } 56 } 57 58 @if (product is object) { 59 @* Supported formats *@ 60 supportedImageFormats = new string[] { ".jpg", ".jpeg", ".webp", ".png", ".gif", ".bmp", ".tiff" }; 61 supportedVideoFormats = new string[] { "youtu.be", "youtube", "vimeo", ".mp4", ".webm" }; 62 supportedDocumentFormats = new string[] { ".pdf", ".docx", ".xlsx", ".ppt", "pptx" }; 63 allSupportedFormats = supportedImageFormats.Concat(supportedVideoFormats).Concat(supportedDocumentFormats).ToArray(); 64 65 @* Collect the assets *@ 66 var selectedAssetCategories = Model.Item.GetRawValueString("ImageAssets").Split(',').ToList(); 67 bool includeImagePatternImages = Model.Item.GetBoolean("ImagePatternImages"); 68 69 @* Needed image data collection to support both DefaultImage, ImagePatterns and Image Assets *@ 70 string defaultImage = product.DefaultImage != null ? product.DefaultImage.Value : ""; 71 IEnumerable<MediaViewModel> assetsImages = product.AssetCategories.Where(x => selectedAssetCategories.Contains(x.SystemName)).SelectMany(x => x.Assets); 72 assetsImages = assetsImages.OrderByDescending(x => x.Value.Equals(defaultImage)); 73 IEnumerable<MediaViewModel> assetsList = new MediaViewModel[]{}; 74 75 assetsList = assetsList.Union(assetsImages); 76 assetsList = includeImagePatternImages ? assetsList.Union(product.ImagePatternImages) : assetsList; 77 assetsList = includeImagePatternImages && assetsList.Count() == 0 ? assetsList.Append(product.DefaultImage) : assetsList; 78 79 bool defaultImageFallback = Model.Item.GetBoolean("DefaultImageFallback"); 80 bool showOnlyPrimaryImage = Model.Item.GetBoolean("ShowOnlyPrimaryImage"); 81 82 int totalAssets = 0; 83 if (showOnlyPrimaryImage == false) { 84 foreach (MediaViewModel asset in assetsList) { 85 var assetValue = asset.Value; 86 foreach (string format in allSupportedFormats) { 87 if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) { 88 totalAssets++; 89 } 90 } 91 } 92 } 93 94 if((totalAssets == 0 && product.DefaultImage != null && selectedAssetCategories.Count() == 0) || (showOnlyPrimaryImage == true && product.DefaultImage != null)) 95 { 96 assetsList = new List<MediaViewModel>(){ product.DefaultImage }; 97 totalAssets = 1; 98 } 99 100 int videoNumber = 0; 101 102 @* Layout settings *@ 103 string spacing = Model.Item.GetRawValueString("Spacing", "p-0"); 104 spacing = spacing == "none" ? "p-0" : spacing; 105 spacing = spacing == "small" ? "p-3" : spacing; 106 spacing = spacing == "large" ? "p-5" : spacing; 107 108 string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("Theme")) ? " theme " + Model.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : ""; 109 110 bool hideThumbnails = Model.Item.GetBoolean("HideThumbnails"); 111 112 string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/"; 113 int modalVideoNumber = 0; 114 115 @* Get assets from selected categories or get all assets *@ 116 117 if (totalAssets != 0 && assetsList.Any()) 118 { 119 <div class="@spacing@(theme) item_@Model.Item.SystemName.ToLower()"> 120 @if (!string.IsNullOrEmpty(Model.Item.GetString("Title")) && !Model.Item.GetBoolean("HideTitle")) 121 { 122 string titleFontSize = Model.Item.GetRawValueString("TitleFontSize", "h3"); 123 124 <h3 class="@titleFontSize mb-3"> 125 @Model.Item.GetString("Title") 126 </h3> 127 } 128 129 <div class="table-responsive"> 130 <table class="table table-hover align-middle mb-0" style="table-layout: fixed;"> 131 <thead> 132 <tr> 133 @if (!hideThumbnails) 134 { 135 <th style="width:60px"> </th> 136 } 137 <th>@Translate("Name")</th> 138 <th class="text-end d-none d-lg-table-cell">@Translate("Download")</th> 139 <th class="text-end" style="width:100px">@Translate("File type")</th> 140 </tr> 141 </thead> 142 <tbody class="border-top-0"> 143 @foreach (MediaViewModel asset in assetsList) 144 { 145 var assetValue = asset.Value; 146 string assetName = !string.IsNullOrEmpty(asset.DisplayName) ? asset.DisplayName : asset.Value.Substring( asset.Value.LastIndexOf('/') + 1); 147 148 bool isVideo = false; 149 foreach (string format in supportedVideoFormats) 150 { //Videos 151 if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) 152 { 153 isVideo = true; 154 } 155 } 156 157 if (!isVideo) 158 { 159 string filePath = Dynamicweb.Context.Current.Server.MapPath(assetValue); 160 long fileSize = 0; 161 162 if (File.Exists(filePath)) { 163 fileSize = new System.IO.FileInfo(filePath) != null ? new System.IO.FileInfo(filePath).Length / 1024 : 0; 164 165 foreach (string format in allSupportedFormats) 166 { 167 if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) 168 { 169 <tr> 170 @if (!hideThumbnails) 171 { 172 @RenderAsset(asset) 173 } 174 <td> 175 <a href="@assetValue" class="text-decoration-none text-break" download="@assetName" title="@assetName"> 176 @assetName 177 </a> 178 </td> 179 <td class="text-end d-none d-lg-table-cell"> 180 <a href="@assetValue" class="text-decoration-none" download="@assetName" title="@assetName"> 181 @fileSize KB <div class="icon-2" style="z-index: 1">@ReadFile(iconPath + "download.svg")</div> 182 </a> 183 </td> 184 <td class="text-end">@format</td> 185 </tr> 186 } 187 } 188 } 189 } 190 else 191 { 192 string videoType = asset.Value.IndexOf("youtu.be", StringComparison.OrdinalIgnoreCase) >= 0 || asset.Value.IndexOf("youtube", StringComparison.OrdinalIgnoreCase) >= 0 ? "Youtube" : ""; 193 videoType = asset.Value.IndexOf("vimeo", StringComparison.OrdinalIgnoreCase) >= 0 ? "Vimeo" : videoType; 194 195 <tr data-bs-toggle="modal" data-bs-target="#modal_@(Model.ID)_@videoNumber" style="cursor: pointer"> 196 @if (!hideThumbnails) 197 { 198 @RenderAsset(asset) 199 } 200 <td> 201 @assetName 202 </td> 203 <td class="d-none d-lg-table-cell"> </td> 204 <td align="right">@videoType</td> 205 </tr> 206 207 videoNumber++; 208 } 209 } 210 </tbody> 211 </table> 212 </div> 213 214 @foreach (MediaViewModel asset in assetsList) 215 { 216 var assetName = asset.Value.ToLower(); 217 218 foreach (string format in supportedVideoFormats) 219 { //Videos 220 if (assetName.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) 221 { 222 <div class="modal fade js-video-modal" id="modal_@(Model.ID)_@modalVideoNumber" tabindex="-1" aria-labelledby="productDetailsTableModalTitle_@(Model.ID)_@modalVideoNumber" aria-hidden="true"> 223 <div class="modal-dialog modal-dialog-centered modal-xl"> 224 <div class="modal-content"> 225 <div class="modal-header visually-hidden"> 226 <h5 class="modal-title" id="productDetailsTableModalTitle_@(Model.ID)_@modalVideoNumber">@product.Title</h5> 227 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> 228 </div> 229 <div class="modal-body p-2 p-lg-3 h-100"> 230 @{ @RenderVideoPlayer(asset) } 231 </div> 232 </div> 233 </div> 234 </div> 235 236 modalVideoNumber++; 237 } 238 } 239 } 240 </div> 241 } 242 else if (Pageview.IsVisualEditorMode) 243 { 244 <div class="h-100 @theme"> 245 <div class="alert alert-dark m-0"> 246 @Translate("No assets are available") 247 </div> 248 </div> 249 } 250 } 251 252 @helper RenderAsset(MediaViewModel asset) 253 { 254 string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("ImageTheme")) ? " theme " + Model.Item.GetRawValueString("ImageTheme").Replace(" ", "").Trim().ToLower() : ""; 255 string assetValue = asset.Value; 256 257 <td class="@(theme) px-0"> 258 @foreach (string format in supportedImageFormats) 259 { //Images 260 if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) 261 { 262 @RenderImage(asset) 263 } 264 } 265 @foreach (string format in supportedVideoFormats) 266 { //Videos 267 if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) 268 { 269 @RenderVideoScreendump(asset) 270 } 271 } 272 @foreach (string format in supportedDocumentFormats) 273 { //Documents 274 if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) 275 { 276 @RenderDocument(asset) 277 } 278 } 279 </td> 280 } 281 282 @helper RenderImage(MediaViewModel asset) 283 { 284 string productName = product.Name; 285 productName += !string.IsNullOrEmpty(asset.Keywords) ? " " + asset.Keywords : ""; 286 string imagePath = !string.IsNullOrEmpty(asset.Value) ? asset.Value : product.DefaultImage.Value; 287 string imageLinkPath = imagePath; 288 imagePath = $"/Admin/Public/GetImage.ashx?image={imagePath}&width=60&format=webp"; 289 290 string assetTitle = !string.IsNullOrEmpty(asset.DisplayName) ? "title=\"" + asset.DisplayName + "\"" : ""; 291 292 RatioSettings ratioSettings = GetRatioSettings(); 293 294 <a href="@imageLinkPath" class="d-block @(ratioSettings.CssClass)@(ratioSettings.Fill)" style="@(ratioSettings.CssVariable)" download> 295 <div class="d-flex align-items-center justify-content-center overflow-hidden h-100"> 296 <img loading="lazy" src="@imagePath" class="mw-100 mh-100" alt="@productName" @assetTitle itemprop="image"> 297 </div> 298 </a> 299 } 300 301 @helper RenderVideoScreendump(MediaViewModel asset) 302 { 303 string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/"; 304 305 string videoScreendumpPath = !string.IsNullOrEmpty(asset.Value) ? asset.Value : ""; 306 string videoId = videoScreendumpPath.Substring(videoScreendumpPath.LastIndexOf('/') + 1); 307 videoScreendumpPath = videoScreendumpPath.IndexOf("youtu.be", StringComparison.OrdinalIgnoreCase) >= 0 || videoScreendumpPath.IndexOf("youtube", StringComparison.OrdinalIgnoreCase) >= 0 ? "https://img.youtube.com/vi/" + videoId + "/mqdefault.jpg" : videoScreendumpPath; 308 309 string vimeoJsClass = videoScreendumpPath.IndexOf("vimeo", StringComparison.OrdinalIgnoreCase) >= 0 ? "js-vimeo-video-thumbnail" : ""; 310 videoScreendumpPath = videoScreendumpPath.IndexOf("vimeo", StringComparison.OrdinalIgnoreCase) >= 0 ? "" : videoScreendumpPath; 311 312 string productName = product.Name; 313 productName += !string.IsNullOrEmpty(asset.Keywords) ? " " + asset.Keywords : ""; 314 string assetTitle = !string.IsNullOrEmpty(asset.DisplayName) ? "title=\"" + asset.DisplayName + "\"" : ""; 315 316 RatioSettings ratioSettings = GetRatioSettings(); 317 318 <div class="d-block @(ratioSettings.CssClass)@(ratioSettings.Fill)" style="@(ratioSettings.CssVariable)"> 319 <div class="d-flex align-items-center justify-content-center overflow-hidden h-100"> 320 <div class="icon-2 position-absolute" style="z-index: 1">@ReadFile(iconPath + "play-circle.svg")</div> 321 @if (videoScreendumpPath.IndexOf(".mp4", StringComparison.OrdinalIgnoreCase) < 0) { 322 <img src="@videoScreendumpPath" loading="lazy" decoding="async" alt="@productName" @assetTitle class="@vimeoJsClass mw-100 mh-100" data-video-id="@videoId" style="object-fit: cover;"> 323 } else { 324 string videoType = Path.GetExtension(asset.Value).ToLower(); 325 326 <video preload="auto" class="h-100 w-100" style="object-fit: contain;"> 327 <source src="@asset.Value" type="video/@videoType.Replace(".", "")"> 328 </video> 329 } 330 </div> 331 </div> 332 } 333 334 @helper RenderDocument(MediaViewModel asset) 335 { 336 string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/"; 337 string productName = product.Name; 338 productName += !string.IsNullOrEmpty(asset.Keywords) ? " " + asset.Keywords : ""; 339 string imagePath = !string.IsNullOrEmpty(asset.Value) ? asset.Value : product.DefaultImage.Value; 340 string imageLinkPath = imagePath; 341 imagePath = $"/Admin/Public/GetImage.ashx?image={imagePath}&width=60&format=webp"; 342 string assetTitle = !string.IsNullOrEmpty(asset.DisplayName) ? "title=\"" + asset.DisplayName + "\"" : ""; 343 344 RatioSettings ratioSettings = GetRatioSettings(); 345 346 <a href="@imageLinkPath" class="d-block @(ratioSettings.CssClass)@(ratioSettings.Fill)" style="@(ratioSettings.CssVariable)" download alt="@productName"> 347 @if (asset.Value.IndexOf(".pdf", StringComparison.OrdinalIgnoreCase) >= 0) { 348 <div class="d-flex align-items-center justify-content-center overflow-hidden h-100"> 349 <img loading="lazy" src="@imagePath" class="mw-100 mh-100" alt="@productName" @assetTitle /> 350 </div> 351 } else { 352 <div class="d-flex align-items-center justify-content-center overflow-hidden h-100"> 353 <div class="icon-3 position-absolute" style="z-index: 1">@ReadFile(iconPath + "file-text.svg")</div> 354 </div> 355 } 356 </a> 357 } 358 359 @helper RenderVideoPlayer(MediaViewModel asset) 360 { 361 string assetName = !string.IsNullOrEmpty(asset.DisplayName) ? asset.DisplayName : asset.Name; 362 string assetValue = asset.Value; 363 string videoId = asset.Value.Substring(asset.Value.LastIndexOf('/') + 1); 364 string type = assetValue.IndexOf("youtu.be", StringComparison.OrdinalIgnoreCase) >= 0 || assetValue.IndexOf("youtube", StringComparison.OrdinalIgnoreCase) >= 0 ? "youtube" : ""; 365 type = assetValue.IndexOf("vimeo", StringComparison.OrdinalIgnoreCase) >= 0 ? "vimeo" : type; 366 type = assetValue.IndexOf(".mp4", StringComparison.OrdinalIgnoreCase) >= 0 || assetValue.IndexOf(".webm", StringComparison.OrdinalIgnoreCase) >= 0 ? "selfhosted" : type; 367 368 <div class="h-100" itemscope itemtype="https://schema.org/VideoObject"> 369 <span class="visually-hidden" itemprop="name">@assetName</span> 370 <span class="visually-hidden" itemprop="contentUrl">@asset.Value</span> 371 <span class="visually-hidden" itemprop="thumbnailUrl">@asset.Value</span> 372 @if (type != "selfhosted") 373 { 374 <div id="player_@(Pageview.CurrentParagraph.ID)_@(videoId)" 375 class="plyr__video-embed" 376 data-plyr-provider="@(type)" 377 data-plyr-embed-id="@videoId" 378 style="--plyr-color-main: var(--swift-foreground-color); height: 100%"> 379 </div> 380 381 <script type="module" src="/Files/Templates/Designs/Swift/Assets/js/plyr.js"></script> 382 <script type="module"> 383 var player = new Plyr('#player_@(Pageview.CurrentParagraph.ID)_@(videoId)', { 384 type: 'video', 385 youtube: { 386 noCookie: true, 387 showinfo: 0 388 }, 389 fullscreen: { 390 enabled: true, 391 iosNative: true, 392 } 393 }); 394 395 document.querySelectorAll('.js-video-modal').forEach(function (modal) { 396 modal.addEventListener('hidden.bs.modal', function (event) { 397 player.media.pause(); 398 }) 399 }); 400 </script> 401 } 402 else 403 { 404 string videoType = Path.GetExtension(assetValue).ToLower(); 405 406 <video preload="auto" class="h-100 w-100" style="object-fit: cover;" controls> 407 <source src="@assetValue" type="video/@videoType.Replace(".", "")"> 408 </video> 409 } 410 </div> 411 } 412
Error executing template "Designs/Swift/Paragraph/Swift_ProductDetailsMediaTable.cshtml" System.Data.SqlClient.SqlException (0x80131904): A connection was successfully established with the server, but then an error occurred during the pre-login handshake. (provider: SSL Provider, error: 0 - The handle specified is invalid) ---> System.ComponentModel.Win32Exception (0x80004005): The handle specified is invalid at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection) at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection) at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection) at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions) at System.Data.SqlClient.SqlConnection.TryOpenInner(TaskCompletionSource`1 retry) at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry) at System.Data.SqlClient.SqlConnection.Open() at Dynamicweb.Data.DatabaseConnectionProvider.CreateConnection(Boolean open) at Dynamicweb.Data.Database.CreateConnection() at Dynamicweb.Data.Database.CreateDataReader(CommandBuilder commandBuilder, IDbConnection connection, IDbTransaction transaction, Int32 commandTimeout) at Dynamicweb.Ecommerce.Products.DetailRepository.GetInheritedDetailsBulk(List`1 productIds, String detailType, Boolean onlyDefault) at Dynamicweb.Ecommerce.Products.DetailService.GetDetailsBulk(IEnumerable`1 productKeys, String detailType, Boolean excludeDefaultImage) at System.Lazy`1.CreateValue() at System.Lazy`1.LazyInitValue() at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.GetDetailsByGroupId(Product product, Lazy`1 details) at System.Lazy`1.CreateValue() at System.Lazy`1.LazyInitValue() at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.CreateView(AssetCategoryViewModelSettings settings, Product product, Lazy`1 details) 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_457d921174194192b3cdcf0c568215d1.Execute() in D:\dynamicweb.net\Solutions\Flex Media\danzafe.cloud.dynamicweb-cms.com\files\Templates\Designs\Swift\Paragraph\Swift_ProductDetailsMediaTable.cshtml:line 71 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:1b12ce29-ad47-4859-afb1-e524b2ca4ae2 Error Number:-2146893055,State:0,Class:20
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[] supportedImageFormats { get; set; } 9 public string[] supportedVideoFormats { get; set; } 10 public string[] supportedDocumentFormats { get; set; } 11 public string[] allSupportedFormats { get; set; } 12 13 public class RatioSettings 14 { 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() 22 { 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 30 ratioSettings.Ratio = ratio; 31 ratioSettings.CssClass = cssClass; 32 ratioSettings.CssVariable = cssVariable; 33 ratioSettings.Fill = ratio == "fill" ? " h-100" : ""; 34 35 return ratioSettings; 36 } 37 } 38 39 @{ 40 @* Get the product data *@ 41 ProductViewModel product = null; 42 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails")) 43 { 44 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"]; 45 } 46 else if (Pageview.Page.Item["DummyProduct"] != null && Pageview.IsVisualEditorMode) 47 { 48 var pageViewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(Pageview.Page); 49 ProductListViewModel productList = pageViewModel.Item.GetValue("DummyProduct") != null ? pageViewModel.Item.GetValue("DummyProduct") as ProductListViewModel : new ProductListViewModel(); 50 51 if (productList?.Products is object) 52 { 53 product = productList.Products[0]; 54 } 55 } 56 } 57 58 @if (product is object) { 59 @* Supported formats *@ 60 supportedImageFormats = new string[] { ".jpg", ".jpeg", ".webp", ".png", ".gif", ".bmp", ".tiff" }; 61 supportedVideoFormats = new string[] { "youtu.be", "youtube", "vimeo", ".mp4", ".webm" }; 62 supportedDocumentFormats = new string[] { ".pdf", ".docx", ".xlsx", ".ppt", "pptx" }; 63 allSupportedFormats = supportedImageFormats.Concat(supportedVideoFormats).Concat(supportedDocumentFormats).ToArray(); 64 65 @* Collect the assets *@ 66 var selectedAssetCategories = Model.Item.GetRawValueString("ImageAssets").Split(',').ToList(); 67 bool includeImagePatternImages = Model.Item.GetBoolean("ImagePatternImages"); 68 69 @* Needed image data collection to support both DefaultImage, ImagePatterns and Image Assets *@ 70 string defaultImage = product.DefaultImage != null ? product.DefaultImage.Value : ""; 71 IEnumerable<MediaViewModel> assetsImages = product.AssetCategories.Where(x => selectedAssetCategories.Contains(x.SystemName)).SelectMany(x => x.Assets); 72 assetsImages = assetsImages.OrderByDescending(x => x.Value.Equals(defaultImage)); 73 IEnumerable<MediaViewModel> assetsList = new MediaViewModel[]{}; 74 75 assetsList = assetsList.Union(assetsImages); 76 assetsList = includeImagePatternImages ? assetsList.Union(product.ImagePatternImages) : assetsList; 77 assetsList = includeImagePatternImages && assetsList.Count() == 0 ? assetsList.Append(product.DefaultImage) : assetsList; 78 79 bool defaultImageFallback = Model.Item.GetBoolean("DefaultImageFallback"); 80 bool showOnlyPrimaryImage = Model.Item.GetBoolean("ShowOnlyPrimaryImage"); 81 82 int totalAssets = 0; 83 if (showOnlyPrimaryImage == false) { 84 foreach (MediaViewModel asset in assetsList) { 85 var assetValue = asset.Value; 86 foreach (string format in allSupportedFormats) { 87 if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) { 88 totalAssets++; 89 } 90 } 91 } 92 } 93 94 if((totalAssets == 0 && product.DefaultImage != null && selectedAssetCategories.Count() == 0) || (showOnlyPrimaryImage == true && product.DefaultImage != null)) 95 { 96 assetsList = new List<MediaViewModel>(){ product.DefaultImage }; 97 totalAssets = 1; 98 } 99 100 int videoNumber = 0; 101 102 @* Layout settings *@ 103 string spacing = Model.Item.GetRawValueString("Spacing", "p-0"); 104 spacing = spacing == "none" ? "p-0" : spacing; 105 spacing = spacing == "small" ? "p-3" : spacing; 106 spacing = spacing == "large" ? "p-5" : spacing; 107 108 string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("Theme")) ? " theme " + Model.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : ""; 109 110 bool hideThumbnails = Model.Item.GetBoolean("HideThumbnails"); 111 112 string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/"; 113 int modalVideoNumber = 0; 114 115 @* Get assets from selected categories or get all assets *@ 116 117 if (totalAssets != 0 && assetsList.Any()) 118 { 119 <div class="@spacing@(theme) item_@Model.Item.SystemName.ToLower()"> 120 @if (!string.IsNullOrEmpty(Model.Item.GetString("Title")) && !Model.Item.GetBoolean("HideTitle")) 121 { 122 string titleFontSize = Model.Item.GetRawValueString("TitleFontSize", "h3"); 123 124 <h3 class="@titleFontSize mb-3"> 125 @Model.Item.GetString("Title") 126 </h3> 127 } 128 129 <div class="table-responsive"> 130 <table class="table table-hover align-middle mb-0" style="table-layout: fixed;"> 131 <thead> 132 <tr> 133 @if (!hideThumbnails) 134 { 135 <th style="width:60px"> </th> 136 } 137 <th>@Translate("Name")</th> 138 <th class="text-end d-none d-lg-table-cell">@Translate("Download")</th> 139 <th class="text-end" style="width:100px">@Translate("File type")</th> 140 </tr> 141 </thead> 142 <tbody class="border-top-0"> 143 @foreach (MediaViewModel asset in assetsList) 144 { 145 var assetValue = asset.Value; 146 string assetName = !string.IsNullOrEmpty(asset.DisplayName) ? asset.DisplayName : asset.Value.Substring( asset.Value.LastIndexOf('/') + 1); 147 148 bool isVideo = false; 149 foreach (string format in supportedVideoFormats) 150 { //Videos 151 if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) 152 { 153 isVideo = true; 154 } 155 } 156 157 if (!isVideo) 158 { 159 string filePath = Dynamicweb.Context.Current.Server.MapPath(assetValue); 160 long fileSize = 0; 161 162 if (File.Exists(filePath)) { 163 fileSize = new System.IO.FileInfo(filePath) != null ? new System.IO.FileInfo(filePath).Length / 1024 : 0; 164 165 foreach (string format in allSupportedFormats) 166 { 167 if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) 168 { 169 <tr> 170 @if (!hideThumbnails) 171 { 172 @RenderAsset(asset) 173 } 174 <td> 175 <a href="@assetValue" class="text-decoration-none text-break" download="@assetName" title="@assetName"> 176 @assetName 177 </a> 178 </td> 179 <td class="text-end d-none d-lg-table-cell"> 180 <a href="@assetValue" class="text-decoration-none" download="@assetName" title="@assetName"> 181 @fileSize KB <div class="icon-2" style="z-index: 1">@ReadFile(iconPath + "download.svg")</div> 182 </a> 183 </td> 184 <td class="text-end">@format</td> 185 </tr> 186 } 187 } 188 } 189 } 190 else 191 { 192 string videoType = asset.Value.IndexOf("youtu.be", StringComparison.OrdinalIgnoreCase) >= 0 || asset.Value.IndexOf("youtube", StringComparison.OrdinalIgnoreCase) >= 0 ? "Youtube" : ""; 193 videoType = asset.Value.IndexOf("vimeo", StringComparison.OrdinalIgnoreCase) >= 0 ? "Vimeo" : videoType; 194 195 <tr data-bs-toggle="modal" data-bs-target="#modal_@(Model.ID)_@videoNumber" style="cursor: pointer"> 196 @if (!hideThumbnails) 197 { 198 @RenderAsset(asset) 199 } 200 <td> 201 @assetName 202 </td> 203 <td class="d-none d-lg-table-cell"> </td> 204 <td align="right">@videoType</td> 205 </tr> 206 207 videoNumber++; 208 } 209 } 210 </tbody> 211 </table> 212 </div> 213 214 @foreach (MediaViewModel asset in assetsList) 215 { 216 var assetName = asset.Value.ToLower(); 217 218 foreach (string format in supportedVideoFormats) 219 { //Videos 220 if (assetName.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) 221 { 222 <div class="modal fade js-video-modal" id="modal_@(Model.ID)_@modalVideoNumber" tabindex="-1" aria-labelledby="productDetailsTableModalTitle_@(Model.ID)_@modalVideoNumber" aria-hidden="true"> 223 <div class="modal-dialog modal-dialog-centered modal-xl"> 224 <div class="modal-content"> 225 <div class="modal-header visually-hidden"> 226 <h5 class="modal-title" id="productDetailsTableModalTitle_@(Model.ID)_@modalVideoNumber">@product.Title</h5> 227 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> 228 </div> 229 <div class="modal-body p-2 p-lg-3 h-100"> 230 @{ @RenderVideoPlayer(asset) } 231 </div> 232 </div> 233 </div> 234 </div> 235 236 modalVideoNumber++; 237 } 238 } 239 } 240 </div> 241 } 242 else if (Pageview.IsVisualEditorMode) 243 { 244 <div class="h-100 @theme"> 245 <div class="alert alert-dark m-0"> 246 @Translate("No assets are available") 247 </div> 248 </div> 249 } 250 } 251 252 @helper RenderAsset(MediaViewModel asset) 253 { 254 string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("ImageTheme")) ? " theme " + Model.Item.GetRawValueString("ImageTheme").Replace(" ", "").Trim().ToLower() : ""; 255 string assetValue = asset.Value; 256 257 <td class="@(theme) px-0"> 258 @foreach (string format in supportedImageFormats) 259 { //Images 260 if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) 261 { 262 @RenderImage(asset) 263 } 264 } 265 @foreach (string format in supportedVideoFormats) 266 { //Videos 267 if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) 268 { 269 @RenderVideoScreendump(asset) 270 } 271 } 272 @foreach (string format in supportedDocumentFormats) 273 { //Documents 274 if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) 275 { 276 @RenderDocument(asset) 277 } 278 } 279 </td> 280 } 281 282 @helper RenderImage(MediaViewModel asset) 283 { 284 string productName = product.Name; 285 productName += !string.IsNullOrEmpty(asset.Keywords) ? " " + asset.Keywords : ""; 286 string imagePath = !string.IsNullOrEmpty(asset.Value) ? asset.Value : product.DefaultImage.Value; 287 string imageLinkPath = imagePath; 288 imagePath = $"/Admin/Public/GetImage.ashx?image={imagePath}&width=60&format=webp"; 289 290 string assetTitle = !string.IsNullOrEmpty(asset.DisplayName) ? "title=\"" + asset.DisplayName + "\"" : ""; 291 292 RatioSettings ratioSettings = GetRatioSettings(); 293 294 <a href="@imageLinkPath" class="d-block @(ratioSettings.CssClass)@(ratioSettings.Fill)" style="@(ratioSettings.CssVariable)" download> 295 <div class="d-flex align-items-center justify-content-center overflow-hidden h-100"> 296 <img loading="lazy" src="@imagePath" class="mw-100 mh-100" alt="@productName" @assetTitle itemprop="image"> 297 </div> 298 </a> 299 } 300 301 @helper RenderVideoScreendump(MediaViewModel asset) 302 { 303 string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/"; 304 305 string videoScreendumpPath = !string.IsNullOrEmpty(asset.Value) ? asset.Value : ""; 306 string videoId = videoScreendumpPath.Substring(videoScreendumpPath.LastIndexOf('/') + 1); 307 videoScreendumpPath = videoScreendumpPath.IndexOf("youtu.be", StringComparison.OrdinalIgnoreCase) >= 0 || videoScreendumpPath.IndexOf("youtube", StringComparison.OrdinalIgnoreCase) >= 0 ? "https://img.youtube.com/vi/" + videoId + "/mqdefault.jpg" : videoScreendumpPath; 308 309 string vimeoJsClass = videoScreendumpPath.IndexOf("vimeo", StringComparison.OrdinalIgnoreCase) >= 0 ? "js-vimeo-video-thumbnail" : ""; 310 videoScreendumpPath = videoScreendumpPath.IndexOf("vimeo", StringComparison.OrdinalIgnoreCase) >= 0 ? "" : videoScreendumpPath; 311 312 string productName = product.Name; 313 productName += !string.IsNullOrEmpty(asset.Keywords) ? " " + asset.Keywords : ""; 314 string assetTitle = !string.IsNullOrEmpty(asset.DisplayName) ? "title=\"" + asset.DisplayName + "\"" : ""; 315 316 RatioSettings ratioSettings = GetRatioSettings(); 317 318 <div class="d-block @(ratioSettings.CssClass)@(ratioSettings.Fill)" style="@(ratioSettings.CssVariable)"> 319 <div class="d-flex align-items-center justify-content-center overflow-hidden h-100"> 320 <div class="icon-2 position-absolute" style="z-index: 1">@ReadFile(iconPath + "play-circle.svg")</div> 321 @if (videoScreendumpPath.IndexOf(".mp4", StringComparison.OrdinalIgnoreCase) < 0) { 322 <img src="@videoScreendumpPath" loading="lazy" decoding="async" alt="@productName" @assetTitle class="@vimeoJsClass mw-100 mh-100" data-video-id="@videoId" style="object-fit: cover;"> 323 } else { 324 string videoType = Path.GetExtension(asset.Value).ToLower(); 325 326 <video preload="auto" class="h-100 w-100" style="object-fit: contain;"> 327 <source src="@asset.Value" type="video/@videoType.Replace(".", "")"> 328 </video> 329 } 330 </div> 331 </div> 332 } 333 334 @helper RenderDocument(MediaViewModel asset) 335 { 336 string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/"; 337 string productName = product.Name; 338 productName += !string.IsNullOrEmpty(asset.Keywords) ? " " + asset.Keywords : ""; 339 string imagePath = !string.IsNullOrEmpty(asset.Value) ? asset.Value : product.DefaultImage.Value; 340 string imageLinkPath = imagePath; 341 imagePath = $"/Admin/Public/GetImage.ashx?image={imagePath}&width=60&format=webp"; 342 string assetTitle = !string.IsNullOrEmpty(asset.DisplayName) ? "title=\"" + asset.DisplayName + "\"" : ""; 343 344 RatioSettings ratioSettings = GetRatioSettings(); 345 346 <a href="@imageLinkPath" class="d-block @(ratioSettings.CssClass)@(ratioSettings.Fill)" style="@(ratioSettings.CssVariable)" download alt="@productName"> 347 @if (asset.Value.IndexOf(".pdf", StringComparison.OrdinalIgnoreCase) >= 0) { 348 <div class="d-flex align-items-center justify-content-center overflow-hidden h-100"> 349 <img loading="lazy" src="@imagePath" class="mw-100 mh-100" alt="@productName" @assetTitle /> 350 </div> 351 } else { 352 <div class="d-flex align-items-center justify-content-center overflow-hidden h-100"> 353 <div class="icon-3 position-absolute" style="z-index: 1">@ReadFile(iconPath + "file-text.svg")</div> 354 </div> 355 } 356 </a> 357 } 358 359 @helper RenderVideoPlayer(MediaViewModel asset) 360 { 361 string assetName = !string.IsNullOrEmpty(asset.DisplayName) ? asset.DisplayName : asset.Name; 362 string assetValue = asset.Value; 363 string videoId = asset.Value.Substring(asset.Value.LastIndexOf('/') + 1); 364 string type = assetValue.IndexOf("youtu.be", StringComparison.OrdinalIgnoreCase) >= 0 || assetValue.IndexOf("youtube", StringComparison.OrdinalIgnoreCase) >= 0 ? "youtube" : ""; 365 type = assetValue.IndexOf("vimeo", StringComparison.OrdinalIgnoreCase) >= 0 ? "vimeo" : type; 366 type = assetValue.IndexOf(".mp4", StringComparison.OrdinalIgnoreCase) >= 0 || assetValue.IndexOf(".webm", StringComparison.OrdinalIgnoreCase) >= 0 ? "selfhosted" : type; 367 368 <div class="h-100" itemscope itemtype="https://schema.org/VideoObject"> 369 <span class="visually-hidden" itemprop="name">@assetName</span> 370 <span class="visually-hidden" itemprop="contentUrl">@asset.Value</span> 371 <span class="visually-hidden" itemprop="thumbnailUrl">@asset.Value</span> 372 @if (type != "selfhosted") 373 { 374 <div id="player_@(Pageview.CurrentParagraph.ID)_@(videoId)" 375 class="plyr__video-embed" 376 data-plyr-provider="@(type)" 377 data-plyr-embed-id="@videoId" 378 style="--plyr-color-main: var(--swift-foreground-color); height: 100%"> 379 </div> 380 381 <script type="module" src="/Files/Templates/Designs/Swift/Assets/js/plyr.js"></script> 382 <script type="module"> 383 var player = new Plyr('#player_@(Pageview.CurrentParagraph.ID)_@(videoId)', { 384 type: 'video', 385 youtube: { 386 noCookie: true, 387 showinfo: 0 388 }, 389 fullscreen: { 390 enabled: true, 391 iosNative: true, 392 } 393 }); 394 395 document.querySelectorAll('.js-video-modal').forEach(function (modal) { 396 modal.addEventListener('hidden.bs.modal', function (event) { 397 player.media.pause(); 398 }) 399 }); 400 </script> 401 } 402 else 403 { 404 string videoType = Path.GetExtension(assetValue).ToLower(); 405 406 <video preload="auto" class="h-100 w-100" style="object-fit: cover;" controls> 407 <source src="@assetValue" type="video/@videoType.Replace(".", "")"> 408 </video> 409 } 410 </div> 411 } 412
Error executing template "Designs/Swift/Paragraph/Swift_ProductDetailsMediaTable.cshtml" System.Data.SqlClient.SqlException (0x80131904): A connection was successfully established with the server, but then an error occurred during the pre-login handshake. (provider: SSL Provider, error: 0 - The handle specified is invalid) ---> System.ComponentModel.Win32Exception (0x80004005): The handle specified is invalid at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection) at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection) at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection) at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions) at System.Data.SqlClient.SqlConnection.TryOpenInner(TaskCompletionSource`1 retry) at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry) at System.Data.SqlClient.SqlConnection.Open() at Dynamicweb.Data.DatabaseConnectionProvider.CreateConnection(Boolean open) at Dynamicweb.Data.Database.CreateConnection() at Dynamicweb.Data.Database.CreateDataReader(CommandBuilder commandBuilder, IDbConnection connection, IDbTransaction transaction, Int32 commandTimeout) at Dynamicweb.Ecommerce.Products.DetailRepository.GetInheritedDetailsBulk(List`1 productIds, String detailType, Boolean onlyDefault) at Dynamicweb.Ecommerce.Products.DetailService.GetDetailsBulk(IEnumerable`1 productKeys, String detailType, Boolean excludeDefaultImage) at System.Lazy`1.CreateValue() at System.Lazy`1.LazyInitValue() at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.GetDetailsByGroupId(Product product, Lazy`1 details) at System.Lazy`1.CreateValue() at System.Lazy`1.LazyInitValue() at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.CreateView(AssetCategoryViewModelSettings settings, Product product, Lazy`1 details) 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_457d921174194192b3cdcf0c568215d1.Execute() in D:\dynamicweb.net\Solutions\Flex Media\danzafe.cloud.dynamicweb-cms.com\files\Templates\Designs\Swift\Paragraph\Swift_ProductDetailsMediaTable.cshtml:line 71 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:1b12ce29-ad47-4859-afb1-e524b2ca4ae2 Error Number:-2146893055,State:0,Class:20
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[] supportedImageFormats { get; set; } 9 public string[] supportedVideoFormats { get; set; } 10 public string[] supportedDocumentFormats { get; set; } 11 public string[] allSupportedFormats { get; set; } 12 13 public class RatioSettings 14 { 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() 22 { 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 30 ratioSettings.Ratio = ratio; 31 ratioSettings.CssClass = cssClass; 32 ratioSettings.CssVariable = cssVariable; 33 ratioSettings.Fill = ratio == "fill" ? " h-100" : ""; 34 35 return ratioSettings; 36 } 37 } 38 39 @{ 40 @* Get the product data *@ 41 ProductViewModel product = null; 42 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails")) 43 { 44 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"]; 45 } 46 else if (Pageview.Page.Item["DummyProduct"] != null && Pageview.IsVisualEditorMode) 47 { 48 var pageViewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(Pageview.Page); 49 ProductListViewModel productList = pageViewModel.Item.GetValue("DummyProduct") != null ? pageViewModel.Item.GetValue("DummyProduct") as ProductListViewModel : new ProductListViewModel(); 50 51 if (productList?.Products is object) 52 { 53 product = productList.Products[0]; 54 } 55 } 56 } 57 58 @if (product is object) { 59 @* Supported formats *@ 60 supportedImageFormats = new string[] { ".jpg", ".jpeg", ".webp", ".png", ".gif", ".bmp", ".tiff" }; 61 supportedVideoFormats = new string[] { "youtu.be", "youtube", "vimeo", ".mp4", ".webm" }; 62 supportedDocumentFormats = new string[] { ".pdf", ".docx", ".xlsx", ".ppt", "pptx" }; 63 allSupportedFormats = supportedImageFormats.Concat(supportedVideoFormats).Concat(supportedDocumentFormats).ToArray(); 64 65 @* Collect the assets *@ 66 var selectedAssetCategories = Model.Item.GetRawValueString("ImageAssets").Split(',').ToList(); 67 bool includeImagePatternImages = Model.Item.GetBoolean("ImagePatternImages"); 68 69 @* Needed image data collection to support both DefaultImage, ImagePatterns and Image Assets *@ 70 string defaultImage = product.DefaultImage != null ? product.DefaultImage.Value : ""; 71 IEnumerable<MediaViewModel> assetsImages = product.AssetCategories.Where(x => selectedAssetCategories.Contains(x.SystemName)).SelectMany(x => x.Assets); 72 assetsImages = assetsImages.OrderByDescending(x => x.Value.Equals(defaultImage)); 73 IEnumerable<MediaViewModel> assetsList = new MediaViewModel[]{}; 74 75 assetsList = assetsList.Union(assetsImages); 76 assetsList = includeImagePatternImages ? assetsList.Union(product.ImagePatternImages) : assetsList; 77 assetsList = includeImagePatternImages && assetsList.Count() == 0 ? assetsList.Append(product.DefaultImage) : assetsList; 78 79 bool defaultImageFallback = Model.Item.GetBoolean("DefaultImageFallback"); 80 bool showOnlyPrimaryImage = Model.Item.GetBoolean("ShowOnlyPrimaryImage"); 81 82 int totalAssets = 0; 83 if (showOnlyPrimaryImage == false) { 84 foreach (MediaViewModel asset in assetsList) { 85 var assetValue = asset.Value; 86 foreach (string format in allSupportedFormats) { 87 if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) { 88 totalAssets++; 89 } 90 } 91 } 92 } 93 94 if((totalAssets == 0 && product.DefaultImage != null && selectedAssetCategories.Count() == 0) || (showOnlyPrimaryImage == true && product.DefaultImage != null)) 95 { 96 assetsList = new List<MediaViewModel>(){ product.DefaultImage }; 97 totalAssets = 1; 98 } 99 100 int videoNumber = 0; 101 102 @* Layout settings *@ 103 string spacing = Model.Item.GetRawValueString("Spacing", "p-0"); 104 spacing = spacing == "none" ? "p-0" : spacing; 105 spacing = spacing == "small" ? "p-3" : spacing; 106 spacing = spacing == "large" ? "p-5" : spacing; 107 108 string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("Theme")) ? " theme " + Model.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : ""; 109 110 bool hideThumbnails = Model.Item.GetBoolean("HideThumbnails"); 111 112 string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/"; 113 int modalVideoNumber = 0; 114 115 @* Get assets from selected categories or get all assets *@ 116 117 if (totalAssets != 0 && assetsList.Any()) 118 { 119 <div class="@spacing@(theme) item_@Model.Item.SystemName.ToLower()"> 120 @if (!string.IsNullOrEmpty(Model.Item.GetString("Title")) && !Model.Item.GetBoolean("HideTitle")) 121 { 122 string titleFontSize = Model.Item.GetRawValueString("TitleFontSize", "h3"); 123 124 <h3 class="@titleFontSize mb-3"> 125 @Model.Item.GetString("Title") 126 </h3> 127 } 128 129 <div class="table-responsive"> 130 <table class="table table-hover align-middle mb-0" style="table-layout: fixed;"> 131 <thead> 132 <tr> 133 @if (!hideThumbnails) 134 { 135 <th style="width:60px"> </th> 136 } 137 <th>@Translate("Name")</th> 138 <th class="text-end d-none d-lg-table-cell">@Translate("Download")</th> 139 <th class="text-end" style="width:100px">@Translate("File type")</th> 140 </tr> 141 </thead> 142 <tbody class="border-top-0"> 143 @foreach (MediaViewModel asset in assetsList) 144 { 145 var assetValue = asset.Value; 146 string assetName = !string.IsNullOrEmpty(asset.DisplayName) ? asset.DisplayName : asset.Value.Substring( asset.Value.LastIndexOf('/') + 1); 147 148 bool isVideo = false; 149 foreach (string format in supportedVideoFormats) 150 { //Videos 151 if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) 152 { 153 isVideo = true; 154 } 155 } 156 157 if (!isVideo) 158 { 159 string filePath = Dynamicweb.Context.Current.Server.MapPath(assetValue); 160 long fileSize = 0; 161 162 if (File.Exists(filePath)) { 163 fileSize = new System.IO.FileInfo(filePath) != null ? new System.IO.FileInfo(filePath).Length / 1024 : 0; 164 165 foreach (string format in allSupportedFormats) 166 { 167 if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) 168 { 169 <tr> 170 @if (!hideThumbnails) 171 { 172 @RenderAsset(asset) 173 } 174 <td> 175 <a href="@assetValue" class="text-decoration-none text-break" download="@assetName" title="@assetName"> 176 @assetName 177 </a> 178 </td> 179 <td class="text-end d-none d-lg-table-cell"> 180 <a href="@assetValue" class="text-decoration-none" download="@assetName" title="@assetName"> 181 @fileSize KB <div class="icon-2" style="z-index: 1">@ReadFile(iconPath + "download.svg")</div> 182 </a> 183 </td> 184 <td class="text-end">@format</td> 185 </tr> 186 } 187 } 188 } 189 } 190 else 191 { 192 string videoType = asset.Value.IndexOf("youtu.be", StringComparison.OrdinalIgnoreCase) >= 0 || asset.Value.IndexOf("youtube", StringComparison.OrdinalIgnoreCase) >= 0 ? "Youtube" : ""; 193 videoType = asset.Value.IndexOf("vimeo", StringComparison.OrdinalIgnoreCase) >= 0 ? "Vimeo" : videoType; 194 195 <tr data-bs-toggle="modal" data-bs-target="#modal_@(Model.ID)_@videoNumber" style="cursor: pointer"> 196 @if (!hideThumbnails) 197 { 198 @RenderAsset(asset) 199 } 200 <td> 201 @assetName 202 </td> 203 <td class="d-none d-lg-table-cell"> </td> 204 <td align="right">@videoType</td> 205 </tr> 206 207 videoNumber++; 208 } 209 } 210 </tbody> 211 </table> 212 </div> 213 214 @foreach (MediaViewModel asset in assetsList) 215 { 216 var assetName = asset.Value.ToLower(); 217 218 foreach (string format in supportedVideoFormats) 219 { //Videos 220 if (assetName.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) 221 { 222 <div class="modal fade js-video-modal" id="modal_@(Model.ID)_@modalVideoNumber" tabindex="-1" aria-labelledby="productDetailsTableModalTitle_@(Model.ID)_@modalVideoNumber" aria-hidden="true"> 223 <div class="modal-dialog modal-dialog-centered modal-xl"> 224 <div class="modal-content"> 225 <div class="modal-header visually-hidden"> 226 <h5 class="modal-title" id="productDetailsTableModalTitle_@(Model.ID)_@modalVideoNumber">@product.Title</h5> 227 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> 228 </div> 229 <div class="modal-body p-2 p-lg-3 h-100"> 230 @{ @RenderVideoPlayer(asset) } 231 </div> 232 </div> 233 </div> 234 </div> 235 236 modalVideoNumber++; 237 } 238 } 239 } 240 </div> 241 } 242 else if (Pageview.IsVisualEditorMode) 243 { 244 <div class="h-100 @theme"> 245 <div class="alert alert-dark m-0"> 246 @Translate("No assets are available") 247 </div> 248 </div> 249 } 250 } 251 252 @helper RenderAsset(MediaViewModel asset) 253 { 254 string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("ImageTheme")) ? " theme " + Model.Item.GetRawValueString("ImageTheme").Replace(" ", "").Trim().ToLower() : ""; 255 string assetValue = asset.Value; 256 257 <td class="@(theme) px-0"> 258 @foreach (string format in supportedImageFormats) 259 { //Images 260 if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) 261 { 262 @RenderImage(asset) 263 } 264 } 265 @foreach (string format in supportedVideoFormats) 266 { //Videos 267 if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) 268 { 269 @RenderVideoScreendump(asset) 270 } 271 } 272 @foreach (string format in supportedDocumentFormats) 273 { //Documents 274 if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) 275 { 276 @RenderDocument(asset) 277 } 278 } 279 </td> 280 } 281 282 @helper RenderImage(MediaViewModel asset) 283 { 284 string productName = product.Name; 285 productName += !string.IsNullOrEmpty(asset.Keywords) ? " " + asset.Keywords : ""; 286 string imagePath = !string.IsNullOrEmpty(asset.Value) ? asset.Value : product.DefaultImage.Value; 287 string imageLinkPath = imagePath; 288 imagePath = $"/Admin/Public/GetImage.ashx?image={imagePath}&width=60&format=webp"; 289 290 string assetTitle = !string.IsNullOrEmpty(asset.DisplayName) ? "title=\"" + asset.DisplayName + "\"" : ""; 291 292 RatioSettings ratioSettings = GetRatioSettings(); 293 294 <a href="@imageLinkPath" class="d-block @(ratioSettings.CssClass)@(ratioSettings.Fill)" style="@(ratioSettings.CssVariable)" download> 295 <div class="d-flex align-items-center justify-content-center overflow-hidden h-100"> 296 <img loading="lazy" src="@imagePath" class="mw-100 mh-100" alt="@productName" @assetTitle itemprop="image"> 297 </div> 298 </a> 299 } 300 301 @helper RenderVideoScreendump(MediaViewModel asset) 302 { 303 string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/"; 304 305 string videoScreendumpPath = !string.IsNullOrEmpty(asset.Value) ? asset.Value : ""; 306 string videoId = videoScreendumpPath.Substring(videoScreendumpPath.LastIndexOf('/') + 1); 307 videoScreendumpPath = videoScreendumpPath.IndexOf("youtu.be", StringComparison.OrdinalIgnoreCase) >= 0 || videoScreendumpPath.IndexOf("youtube", StringComparison.OrdinalIgnoreCase) >= 0 ? "https://img.youtube.com/vi/" + videoId + "/mqdefault.jpg" : videoScreendumpPath; 308 309 string vimeoJsClass = videoScreendumpPath.IndexOf("vimeo", StringComparison.OrdinalIgnoreCase) >= 0 ? "js-vimeo-video-thumbnail" : ""; 310 videoScreendumpPath = videoScreendumpPath.IndexOf("vimeo", StringComparison.OrdinalIgnoreCase) >= 0 ? "" : videoScreendumpPath; 311 312 string productName = product.Name; 313 productName += !string.IsNullOrEmpty(asset.Keywords) ? " " + asset.Keywords : ""; 314 string assetTitle = !string.IsNullOrEmpty(asset.DisplayName) ? "title=\"" + asset.DisplayName + "\"" : ""; 315 316 RatioSettings ratioSettings = GetRatioSettings(); 317 318 <div class="d-block @(ratioSettings.CssClass)@(ratioSettings.Fill)" style="@(ratioSettings.CssVariable)"> 319 <div class="d-flex align-items-center justify-content-center overflow-hidden h-100"> 320 <div class="icon-2 position-absolute" style="z-index: 1">@ReadFile(iconPath + "play-circle.svg")</div> 321 @if (videoScreendumpPath.IndexOf(".mp4", StringComparison.OrdinalIgnoreCase) < 0) { 322 <img src="@videoScreendumpPath" loading="lazy" decoding="async" alt="@productName" @assetTitle class="@vimeoJsClass mw-100 mh-100" data-video-id="@videoId" style="object-fit: cover;"> 323 } else { 324 string videoType = Path.GetExtension(asset.Value).ToLower(); 325 326 <video preload="auto" class="h-100 w-100" style="object-fit: contain;"> 327 <source src="@asset.Value" type="video/@videoType.Replace(".", "")"> 328 </video> 329 } 330 </div> 331 </div> 332 } 333 334 @helper RenderDocument(MediaViewModel asset) 335 { 336 string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/"; 337 string productName = product.Name; 338 productName += !string.IsNullOrEmpty(asset.Keywords) ? " " + asset.Keywords : ""; 339 string imagePath = !string.IsNullOrEmpty(asset.Value) ? asset.Value : product.DefaultImage.Value; 340 string imageLinkPath = imagePath; 341 imagePath = $"/Admin/Public/GetImage.ashx?image={imagePath}&width=60&format=webp"; 342 string assetTitle = !string.IsNullOrEmpty(asset.DisplayName) ? "title=\"" + asset.DisplayName + "\"" : ""; 343 344 RatioSettings ratioSettings = GetRatioSettings(); 345 346 <a href="@imageLinkPath" class="d-block @(ratioSettings.CssClass)@(ratioSettings.Fill)" style="@(ratioSettings.CssVariable)" download alt="@productName"> 347 @if (asset.Value.IndexOf(".pdf", StringComparison.OrdinalIgnoreCase) >= 0) { 348 <div class="d-flex align-items-center justify-content-center overflow-hidden h-100"> 349 <img loading="lazy" src="@imagePath" class="mw-100 mh-100" alt="@productName" @assetTitle /> 350 </div> 351 } else { 352 <div class="d-flex align-items-center justify-content-center overflow-hidden h-100"> 353 <div class="icon-3 position-absolute" style="z-index: 1">@ReadFile(iconPath + "file-text.svg")</div> 354 </div> 355 } 356 </a> 357 } 358 359 @helper RenderVideoPlayer(MediaViewModel asset) 360 { 361 string assetName = !string.IsNullOrEmpty(asset.DisplayName) ? asset.DisplayName : asset.Name; 362 string assetValue = asset.Value; 363 string videoId = asset.Value.Substring(asset.Value.LastIndexOf('/') + 1); 364 string type = assetValue.IndexOf("youtu.be", StringComparison.OrdinalIgnoreCase) >= 0 || assetValue.IndexOf("youtube", StringComparison.OrdinalIgnoreCase) >= 0 ? "youtube" : ""; 365 type = assetValue.IndexOf("vimeo", StringComparison.OrdinalIgnoreCase) >= 0 ? "vimeo" : type; 366 type = assetValue.IndexOf(".mp4", StringComparison.OrdinalIgnoreCase) >= 0 || assetValue.IndexOf(".webm", StringComparison.OrdinalIgnoreCase) >= 0 ? "selfhosted" : type; 367 368 <div class="h-100" itemscope itemtype="https://schema.org/VideoObject"> 369 <span class="visually-hidden" itemprop="name">@assetName</span> 370 <span class="visually-hidden" itemprop="contentUrl">@asset.Value</span> 371 <span class="visually-hidden" itemprop="thumbnailUrl">@asset.Value</span> 372 @if (type != "selfhosted") 373 { 374 <div id="player_@(Pageview.CurrentParagraph.ID)_@(videoId)" 375 class="plyr__video-embed" 376 data-plyr-provider="@(type)" 377 data-plyr-embed-id="@videoId" 378 style="--plyr-color-main: var(--swift-foreground-color); height: 100%"> 379 </div> 380 381 <script type="module" src="/Files/Templates/Designs/Swift/Assets/js/plyr.js"></script> 382 <script type="module"> 383 var player = new Plyr('#player_@(Pageview.CurrentParagraph.ID)_@(videoId)', { 384 type: 'video', 385 youtube: { 386 noCookie: true, 387 showinfo: 0 388 }, 389 fullscreen: { 390 enabled: true, 391 iosNative: true, 392 } 393 }); 394 395 document.querySelectorAll('.js-video-modal').forEach(function (modal) { 396 modal.addEventListener('hidden.bs.modal', function (event) { 397 player.media.pause(); 398 }) 399 }); 400 </script> 401 } 402 else 403 { 404 string videoType = Path.GetExtension(assetValue).ToLower(); 405 406 <video preload="auto" class="h-100 w-100" style="object-fit: cover;" controls> 407 <source src="@assetValue" type="video/@videoType.Replace(".", "")"> 408 </video> 409 } 410 </div> 411 } 412
Hål i serie
Huvudapplikationer
- Komplett sortiment för tillverkning av hålrader med 32 mm avstånd
- Inklusive pluggborr Ø 5 mm och skruvklämmor
- för OF 900, OF 1000, OF 1010, OF 1400
- för användning med styrskenor med en rad hål
leveransomfattning
styrplåt, centreringsdorn, HW kopplingsborr Ø 35 mm, HW stiftborr Ø 5 mm (takform), HM stiftborr Ø 5 mm (med mittpunkt och främre skärning), 2 sidoanslag med stoppryttare, skruvklämmor FSZ 120 (2 st), 2 x Längdstopp, skruvmejsel 5 mm, Systainer SYS 1 T-LOC, lev. i kartong
All inclusive-garanti -->
Mer information
Hålavstånd 32,00 mm
Längd på hålraden (utan förlängning) 1400 / 2424
Inställningsområde, sidoanslag 0 - 110 mm