Denne side understøttes ikke optimalt i Internet Explorer. Vi anbefaler derfor, at du benytter en anden browser (fx Google Chrome, Edge, Firefox etc.)

Logo
Exception in template (Designs\StandardWebshop\eCom/Product/Product.cshtml): System.Data.SqlClient.SqlException (0x80131904): Transaction (Process ID 63) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
   at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
   at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
   at System.Data.SqlClient.SqlDataReader.TryHasMoreRows(Boolean& moreRows)
   at System.Data.SqlClient.SqlDataReader.TryReadInternal(Boolean setTimeout, Boolean& more)
   at System.Data.SqlClient.SqlDataReader.Read()
   at Glimpse.Ado.AlternateType.GlimpseDbDataReader.Read()
   at NLWI.Platforms.Dynamicweb8.Specs.Repositories.SpecificationRepository.GetSpecificationObjects(HashSet`1 keys) in D:\VSO Agents\00TFS01-norriq-ip\_work\134\s\NLWI.Platforms.Dynamicweb8.Specs\Repositories\SpecificationRepository.cs:line 267
   at NLWI.Platforms.Dynamicweb8.Specs.Services.CachedSpecificationService.b__12_1(HashSet`1 k) in D:\VSO Agents\00TFS01-norriq-ip\_work\134\s\NLWI.Platforms.Dynamicweb8.Specs\Services\CachedSpecificationService.cs:line 91
   at NLWI.Core.Platform.Caching.DictionaryCaching.GetOrInsert[TKey,TVal](HashSet`1 keys, Func`2 buildCacheKey, Func`2 lookupMethod, CacheOptions cacheOptions) in D:\VSO Agents\00TFS01-norriq-ip\_work\35\s\src\NLWI.Core\Platform\Caching\DictionaryCaching.cs:line 102
   at NLWI.Platforms.Dynamicweb8.Specs.Services.CachedSpecificationService.GetSpecificationObjects(HashSet`1 specificationObjectIdentifiers) in D:\VSO Agents\00TFS01-norriq-ip\_work\134\s\NLWI.Platforms.Dynamicweb8.Specs\Services\CachedSpecificationService.cs:line 88
   at NLWI.Platforms.Dynamicweb8.Specs.Services.ProductSpecificationService.GetProductSpecifications(HashSet`1 productAutoIds) in D:\VSO Agents\00TFS01-norriq-ip\_work\134\s\NLWI.Platforms.Dynamicweb8.Specs\Services\ProductSpecificationService.cs:line 41
   at NLWI.Platforms.Dynamicweb8.Specs.Services.ProductSpecificationService.GetProductSpecifications(Int64 productAutoId) in D:\VSO Agents\00TFS01-norriq-ip\_work\134\s\NLWI.Platforms.Dynamicweb8.Specs\Services\ProductSpecificationService.cs:line 68
   at NLWI.Platforms.Dynamicweb8.Specs.ProductSpecificationExtensionMethods.GetProductSpecifications(Int32 autoId) in D:\VSO Agents\00TFS01-norriq-ip\_work\134\s\NLWI.Platforms.Dynamicweb8.Specs\ProductSpecificationExtensionMethods.cs:line 48
   at NLWI.Platforms.Dynamicweb8.Specs.ProductSpecificationExtensionMethods.GetProductSpecifications[T](RazorTemplateBase`1 page) in D:\VSO Agents\00TFS01-norriq-ip\_work\134\s\NLWI.Platforms.Dynamicweb8.Specs\ProductSpecificationExtensionMethods.cs:line 24
   at CompiledRazorTemplates.Dynamic.ebfaebeeddae.Execute()
   at RazorEngine.Templating.TemplateBase.RazorEngine.Templating.ITemplate.Run(ExecuteContext context)
   at RazorEngine.Razor.Parse[T](String razorTemplate, T model, String cacheName)
   at Dynamicweb.Rendering.Template.Output()
ClientConnectionId:56d56cbc-8b81-44b5-ace0-738e9cbdf814
Error Number:1205,State:51,Class:13
@using System.Web @using NORRIQ.Universal.Extensions @using NORRIQ.Common8.Context @using System.Web.Mvc.Html @using Dynamicweb.NewsLetterV3 @using Newtonsoft.Json @using NORRIQ.Common8.Ecom @using NORRIQ.Common8.Factory @using StandardWebshop.CustomCode.Razor @using NORRIQ.Common8.Razor; @using Dynamicweb.eCommerce.Common; @using Dynamicweb.eCommerce.Products @using NLWI.Platforms.Dynamicweb8.Specs; @using StandardWebshop.CustomCode.Volumenpriser; @using StandardWebshop.CustomCode.ProductFees; @using StandardWebshop.CustomCode.ColorLookup @using StandardWebshop.CustomCode.Units @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> @{ var user = Dynamicweb.Modules.UserManagement.User.GetCurrentUser(); var isPrivate = GetBoolean("Ecom:Product:Field.PRIVATE.Value"); if (user == null && isPrivate) { //Redirect to 404 if product is a private, and you are not logged in, to avoid google from finding the products. HttpContext.Current.Response.Redirect("/admin/public/404.aspx"); } var hidePrices = false; if (user != null) { hidePrices = user.CustomFieldValues.FirstOrDefault(cf => cf.CustomField.SystemName == "AccessUser_HidePrices").Value.ToString().ToLower() == "true" ? true : false; } //GetLoop("Units").Select(u => new //{ // UnitId = u.GetString("Ecom:VariantOption.ID"), // // Change the number format here: // UnitPriceDouble = (u.GetDouble("Ecom:VariantOption.Price.PricePIP") / 100d), // UnitName = u.GetString("Ecom:VariantOption.Name"), // CurrencyCode = u.GetString("Ecom:VariantOption.Price.Currency.Code"), // UnitObj = u //}).OrderBy(x => x.UnitPriceDouble); var tableModeBinding = "default"; // EcomMedia settings var image = NORRIQ.EcomMedia.Frontend.GetProductMedia(this); var docs = NORRIQ.EcomMedia.Frontend.GetProductMedia(this); //XPI var specs = this.GetProductSpecifications(); var SpecImages = specs.GetAllByKey("Image"); var SpecVideos = specs.GetAllByKey("YouTubeLinks"); // Product var ProductCurrency = Context.Currency.Symbol; var Productsheet = Translate("Productsheet", "Datablad"); //var AsyncKey = Pageview.User.LoggedIn ? this.GetJsonPriceKey() : ""; //var AsyncPrices = Pageview.User.LoggedIn ? this.GetJsonRetailPrice() : ""; //var ProductInfo = Pageview.User.LoggedIn || //var ShortDescription = GetString("Ecom:Product.LongDescription").Substring(0, 300) + "..."; //var ProductArea = GetGlobalValue("Global:Area.Lang"); var pricePForGoogle = GetString("NIQ:PriceForGoogle"); // Related products var Columns = "col-xs-12 col-sm-4 col-md-4"; var ListMode = ObjectFactory.GetInstance<AreaItemSettings>().GetCurrentAreaValue<string>("ShowRelateproductsAsSlider"); // List mode var mode = ObjectFactory.GetInstance<TemporarilySettings>().GetAndUpdate("listmode") ?? "" + ObjectFactory.GetInstance<AreaItemSettings>().GetCurrentAreaValue<string>("ProductlistMode") + ""; var volumenpriser = this.GetVolumenpriser(); var productFees = this.GetProductFees(); var productUnitInformation = this.GetUnitInformation(); var units = productUnitInformation.Units; var defaultUnitId = productUnitInformation.ProductDefaultUnitId; var packingSpec = specs.GetByGroup("Specifikationer").FirstOrDefault(x => x.Key == "Pakning"); var isTilbud = GetBoolean("Ecom:Product:Field.Tilbud.Value"); isTilbud = isTilbud || units.Any(x => x.IsInformativePrice); var isNewProduct = GetBoolean("Ecom:Product:Field.Nyhed.Value"); var isOutlet = GetBoolean("Ecom:Product:Field.Outlet.Value"); bool productScope_discountedCompletely = GetBoolean("NIQ:Product.DiscontunedCompletely"); bool productScope_discountedTemporary = GetBoolean("NIQ:Product.DiscontunedTemporary"); bool productScope_isSubstituteProduct = productScope_discountedCompletely || productScope_discountedTemporary; bool isVolumePriceDiscount = volumenpriser.HasPrices() && volumenpriser.IsValid(); var isFavoriteList = (System.Web.HttpContext.Current.Request["favoriteMode"] ?? string.Empty).Equals("true", StringComparison.InvariantCultureIgnoreCase); } <span style="display: none; visibility: hidden" data-product-key-clean='@(GetString("Ecom:Product.ID"))'></span> @using System.CodeDom @using Dynamicweb.Rendering @using NLWI.Platforms.Dynamicweb8.Specs.ViewModels @using NORRIQ.Common8.Context @using NORRIQ.Common8.Factory @using StandardWebshop.CustomCode.ColorLookup @using StandardWebshop.CustomCode.Razor @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> @helper RenderFavoriteListIcon(Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>>.LoopItem product, string renderType = "grid") { var addFav = Translate("label_make_favorite", "Føj til favoritter"); var delFav = Translate("label_remove_favorite", "Fjern fra favoritter"); @RenderFavoriteListIcon(product.GetString("Ecom:Product.ID"), renderType) } @helper RenderFavoriteListIcon(Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> product, string renderType = "grid") { @RenderFavoriteListIcon(product.GetString("Ecom:Product.ID"), renderType) } @helper RenderFavoriteListIcon(string productKey, string renderType) { <ordering-list-item-condition inline-template> <div class="basic_favoriteitem_wrapper"> <customer-agreement-item product-key="@productKey"></customer-agreement-item> <template v-if="isAllowed"> <ordering-list-add-remove-item v-if="isAdvancedAdmin" product-key="@productKey"></ordering-list-add-remove-item> <ordering-list-item product-key="@productKey"></ordering-list-item> </template> <template v-else> <favorite-item product-key="@productKey"></favorite-item> </template> </div> </ordering-list-item-condition> } @using System.Globalization @using NLWI.Platforms.Dynamicweb8.Specs.ViewModels @using NORRIQ.Common8.Factory @using StandardWebshop.CustomCode.ColorLookup @using StandardWebshop.CustomCode.Razor @helper RenderSpecifications(ProductSpecifications specs, string renderType, params string[] excludeSpecKeys) { //Helper function to render specifications //Exclude specfications by providing a parameter string to the function. ex.: RenderSpecifications(specs, "table", "BrandSymbol") //Include all: RenderSpecifications(specs, "table") var colorLookupService = ObjectFactory.GetInstance<ColorLookupService>(); bool firstTh = true; bool firstTd = true; if (renderType.Contains("table")) { <table class="table table-striped spectable"> <tbody> @foreach (var spec in specs.GetByGroup("Specifikationer").GroupBy(a => a.Key)) { if (excludeSpecKeys != null && excludeSpecKeys.Contains(spec.Key)) { continue; } <tr> <th class="@(firstTh ? "th-first" : "")"> @spec.First().Caption </th> <td class="@(firstTd ? "td-first" : "")"> @if (spec.Key == "Vaskeanvisninger") { foreach (var maerkeSpec in spec) { if (spec.Key == "Vaskeanvisninger") { <img src="/Admin/Public/GetImage.ashx?Width=46&amp;Height=30&amp;Compression=80&amp;Image=/Files/Images/Symbol/@maerkeSpec.Value" alt="@maerkeSpec.Value" class="img-responsive" /> } } } else if (spec.Key == "Farve") { var colorList = spec.Select(a => new { value = a, color = colorLookupService.GetColorKey(a.Value) }); if (colorList != null) { int colorIndex = 0; foreach (var colorObj in colorList) { if (renderType.Contains("PDF")) { //use inline style if PDF <span class="spec-color [email protected]" style="background-color:@colorObj.color; border-color:@(colorObj.color.Contains("White") ? "#ccc": colorObj.color)"></span> <span>@(colorIndex > 1 ? ", " : string.Empty)@colorObj.value.Value </span> } else { <span class="spec-color [email protected]"></span> } colorIndex++; } } } else if (spec.Any(s => SpecificationHelper.IsImageFile(s.Value))) { foreach (var s in spec) { if (SpecificationHelper.IsImageFile(s.Value)) { <img src="/Admin/Public/GetImage.ashx?Width=60&amp;Height=60&amp;Compression=80&amp;Crop=5&amp;Image=/Files/Images/XPI/@s.Value" alt="@s.Value" class="img-responsive" /> } else { @s.Value } } } else if (spec.First().Caption.Contains("(kg)")) { var weightString = String.Join(", ", spec.Select(a => a.Value)); double weightDouble = 0; if (double.TryParse(weightString, NumberStyles.AllowDecimalPoint, new CultureInfo("en-US") ,out weightDouble)) { @weightDouble } else { @weightString } } else { @String.Join(", ", spec.Select(a => a.Value)) } </td> </tr> firstTd = false; firstTh = false; } </tbody> </table> } else if (renderType.Equals("Unknown")) { //Replace this renderType if needed. } } @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> @helper RenderStockInformations(Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>>.LoopItem product, bool disableStock = false) { var stock = product.GetDouble("Ecom:Product.Stock"); var isStykliste = product.GetBoolean("Ecom:Product:Field.Stykliste.Value"); var isSkaffevare = product.GetBoolean("Ecom:Product:Field.Skaffevare.Value"); var isOutlet = product.GetBoolean("Ecom:Product:Field.Outlet.Value"); @*<p>disable stock: @disableStock</p>*@ if (isSkaffevare && stock == 0) { <i class="icon-stock icon-blue" title="@Translate("label_skaffevare", "Skaffevare")"></i> <span class="stock-label-text">@Translate("label_skaffevare", "Skaffevare")</span> } else { if (disableStock) { <i class="icon-stock icon-red" title="@Translate("label_out__of_stock", "Udgået")"></i> <span class="stock-label-text">@Translate("label_out__of_stock", "udgået")</span> } else if (stock < 1 && !isStykliste) { <i class="icon-stock icon-yellow" title="@Translate("label_in_stock_in_x_days", "Forventes på lager indenfor 4 dage.")"></i> <span class="stock-label-text">@Translate("label_in_stock_in_x_days_short", "Ikke på lager")</span> } else { <i class="icon-stock icon-green" title="@stock"></i> if (isOutlet) { <span class="stock-label-text" style="display: inline;">@stock @Translate("label_in_stock", "In stock")</span> } else { <span class="stock-label-text">@Translate("label_in_stock", "In stock")</span> } } } } @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> @helper RenderProductLabels(bool isTilbud, bool isVolumePriceDiscount, bool discountedCompletely, bool discountedTemporary, bool isNyhed, bool isOutlet, string renderType = "") { bool isSubstituteProduct = discountedCompletely || discountedTemporary; @*<p>isTilbud: @isTilbud</p> <p>isVolumePriceDiscount: @isVolumePriceDiscount</p> <p>discountedCompletely: @discountedCompletely</p> <p>discountedTemporary: @discountedTemporary</p> <p>isNyhed: @isNyhed</p> <p>isOutlet: @isOutlet</p>*@ if (isNyhed && renderType == "") { <div class="label-wrap label-wrap-bottom"> <span class="labl news">@Translate("Label_Nyhed", "Nyhed")</span> </div> } <div class="label-wrap"> @if (!isSubstituteProduct) { <span class="pricing js-hide-before"> <span class="labl spar"> @Translate("Spar") <span class="async-price-discount"></span> </span> @*<br> //AG but why?*@ </span> if (isVolumePriceDiscount) { <span class="labl tilbud">@Translate("Label_VolumenPrisTilbud", "Volumen rabat")</span> } else if (isTilbud) { <span class="labl tilbud">@Translate("Tilbud")</span> } if (isNyhed && renderType == "PDP") { <span class="labl news">@Translate("Label_Nyhed", "Nyhed")</span> } } else { if (discountedCompletely) { <span class="labl discontinued">@Translate("erstatningsvare_udgaaet", "Udgået vare")</span> } else if (discountedTemporary) { <span class="labl temporarily">@Translate("erstatningsvare_temporarily", "Midlertidigt udgået")</span> } } </div> } @using System.CodeDom @using Dynamicweb.Rendering @using Newtonsoft.Json @using NLWI.Platforms.Dynamicweb8.Specs.ViewModels @using NORRIQ.Common8.Context @using NORRIQ.Common8.Factory @using StandardWebshop.CustomCode.ColorLookup @using StandardWebshop.CustomCode.Razor @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> @helper RenderBuyButton(Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>>.LoopItem product, string renderType = "grid") { //temp track object - remove when converting to clean VUE var loopItemProductJson = new { //NOTE: name not working if dangurous characthers //Name = System.Web.HttpUtility.HtmlEncode(product.GetString("Ecom:Product.Name")).Replace("\"", "'"), Number = string.Format("[{0}]", product.GetString("Ecom:Product.Number")), }; <div v-fbq-track.addtocart='@JsonConvert.SerializeObject(loopItemProductJson)'> @RenderBuyButton(product.GetString("Ecom:Product.ID"), renderType) </div> } @helper RenderBuyButton(Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> product, string renderType = "grid") { //temp track object - remove when converting to clean VUE var templateProductJson = new { //NOTE: name not working if dangurous characthers //Name = System.Web.HttpUtility.HtmlEncode(product.GetString("Ecom:Product.Name")).Replace("\"", "'"), Number = string.Format("[{0}]", product.GetString("Ecom:Product.Number")), }; <div v-fbq-track.addtocart='@JsonConvert.SerializeObject(templateProductJson)'> @RenderBuyButton(product.GetString("Ecom:Product.ID"), renderType) </div> } @helper RenderBuyButton(string productKey, string renderType) { var redirectLinkIsNotAllowed = "?restrict=true"; var btn_addText = Translate("Add to cart", "Add to cart"); //TODO: change to setting under website settings var isInternational = ObjectFactory.GetInstance<ContextService>().GetLanguageId().ToUpper().Equals("LANG2"); <ordering-list-request-product-condition product-key='@productKey' inline-template> <div class=""> <template v-if="loading"> <div class="loading"> <span class="spinner-sm-default"></span> </div> </template> <div v-show="!loading && (!isRestricted || isAvailable)" class="json-buy-btn"> @if (isInternational && !Pageview.User.LoggedIn) { if (renderType.Equals("grid")) { <a href="@redirectLinkIsNotAllowed" class="btn btn-primary btn-block btn-air" title="@btn_addText"> <span class="product-added-text">@btn_addText<i class="pe-is-ec-cart-1-f hide" aria-hidden="true"></i></span> </a> } else if (renderType.Equals("table")) { <a href="@redirectLinkIsNotAllowed" class="btn btn-primary" title="@btn_addText"> <span class="product-added-text"><i class="pe-is-ec-cart-1-f" aria-hidden="true"></i></span> </a> } else if (renderType.Equals("PDP")) { <a href="@redirectLinkIsNotAllowed" class="btn btn-primary btn-block"> <span class="product-added-text">@btn_addText</span> </a> } } else { if (renderType.Equals("grid")) { <button role="button" type="submit" class="btn btn-primary btn-block btn-air" title="@btn_addText"> <span class="product-added-text">@btn_addText<i class="pe-is-ec-cart-1-f hide" aria-hidden="true"></i></span> </button> } else if (renderType.Equals("table")) { <div class="input-group"> <input name="quantity" value="1" type="tel" class="form-control text-center qty-input-manual" autocomplete="off" data-trigger="focus" data-rule-number="true" data-rule-min="1" :disabled="isRestricted && !isAvailable" /> <span class="input-group-btn"> <button role="button" type="submit" class="btn btn-primary ajax-add-to-cart" title="@btn_addText"> <span class="product-added-text"><i class="pe-is-ec-cart-1-f" aria-hidden="true"></i></span> </button> </span> </div> } else if (renderType.Equals("PDP")) { <button class="btn btn-primary btn-block" role="button" type="submit"> <span class="product-added-text">@btn_addText</span> </button> } } </div> <template v-if="!loading && (isRestricted && !isAvailable)"> <ordering-list-request-product :product-key='productKey'></ordering-list-request-product> </template> </div> </ordering-list-request-product-condition> } <script type="text/x-template" id="ordering-list-request-product-template" v-pre> <div> <template v-if="loading"> <div class="loading"> <span class="spinner-sm-default"></span> </div> </template> <template v-if="canRequestProduct && !loading"> <button class="btn btn-primary btn-block" role="button" type="button" v-on:click="requestProduct()" :disabled="isRequested"> <span v-if="!isRequested" class="product-added-text">@Translate("OrderingListRequestProductBtn", "Anmod om vare")</span> <span v-if="isRequested" class="product-added-text">@Translate("OrderingListRequestProductBtn_isRequsted", "Anmoddet")</span> </button> </template> </div> </script> @* ordering list request product - comments modal *@ @using StandardWebshop.CustomCode.Units.Models @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> @helper RazorProductSupplementalPopup(UnitInformationViewModel unitInformation) { <table class="table table-condensed no-margin"> <tr> <th class="text-left">@Translate("Product pakning", "Pakning")</th> <th class="text-right">@Translate("Product indhold", "Indhold")</th> </tr> @{ foreach (var unit in unitInformation.SupplementalUnits.OrderByDescending(x => x.UnitCode.Equals("palle", StringComparison.InvariantCultureIgnoreCase))) { <tr> <td class="text-left">1 @unit.UnitName</td> @if (unit.UnitCode.Equals(unit.Bom)) { <td class="text-right">@unit.BaseContentFactor @unit.BaseContentUOM</td> } else { <td class="text-right">@unit.QtyInBaseUnitOfMeasure @unit.Bom</td> } </tr> } } </table> } @* Debugging: *@ @*<p>standard BOM : @productStandardBom.UnitName</p> <p>defaultUnitid: @defaultUnitId</p> <p>beforeprice : @beforePrice</p>*@ @{ var pdpProductJson = new { //NOTE: name not working if dangurous characthers //Name = System.Web.HttpUtility.HtmlEncode(GetString("Ecom:Product.Name")), Number = string.Format("[{0}]", GetString("Ecom:Product.Number")), }; } <p>@*@(JsonConvert.SerializeObject(productUnitInformation))*@</p> <product-page inline-template> <template> <div class="col-xs-12"> <div v-show="loading"> <div class="loading"> <span class="spinner-xl-default"></span> </div> </div> @* //temp track object - remove when converting to clean VUE *@ <div id="productPage-@GetString("Ecom:Product.Number")" v-visible="!loading" style="visibility: hidden; opacity: 0;" v-fbq-track.product='@JsonConvert.SerializeObject(pdpProductJson)'> <section class="basic_pim js-product-scope" itemscope itemtype="http://schema.org/Product"> <div class="row @(!productScope_isSubstituteProduct ? "async-price" : "")" itemscope itemtype="http://schema.org/Product" data-product-key='@(this.GetJsonPriceKey())' data-product-retail-price='@(this.GetJsonRetailPrice())' data-product-unit-information='@JsonConvert.SerializeObject(productUnitInformation)'> <div class="col-xs-12 col-sm-6 product-media"> @RenderProductLabels(isTilbud, isVolumePriceDiscount, productScope_discountedCompletely, productScope_discountedTemporary, isNewProduct, isOutlet, "PDP") @if (specs.GetAllByKey("Image").Any()) { <text> @if (SpecImages.Any()) { <div class="product-images" id="product-images"> @foreach (var images in SpecImages) { <a class="product-image mfp-image" data-image-type="image" href="/Admin/Public/GetImage.ashx?Width=1000&amp;Height=1000&amp;Crop=5&amp;Compression=80&amp;Image=/Files/Images/XPI/@(images.Value)"> <img itemprop="image" class="img-responsive" src="/Admin/Public/GetImage.ashx?Width=400&amp;Height=400&amp;Crop=5&amp;Compression=80&amp;Image=/Files/Images/XPI/@(images.Value)" alt="@System.Web.HttpUtility.HtmlEncode(GetString("Ecom:Product.Name"))" /> </a> } @foreach (var video in SpecVideos) { <a class="product-image mfp-iframe" data-image-type="video" href="http://www.youtube.com/watch?v=@(video.Value)?rel=0&autoplay=1"> <img itemprop="image" width="400" class="img-responsive" src="http://img.youtube.com/vi/@(video.Value)/0.jpg" /> </a> } </div> if (SpecImages.Count() > 1 || SpecImages.Any() && SpecVideos.Any()) { <div id="product-images-thumbs" class="product-thumbs"> @foreach (var images in SpecImages) { <div class="product-thumb"> <div class="product-thumb-inner" data-thumb-type="image"> <img class="img-responsive" src="/Admin/Public/GetImage.ashx?Width=110&amp;Height=110&amp;Crop=5&amp;Compression=80&amp;Image=/Files/Images/XPI/@(images.Value)" alt="@System.Web.HttpUtility.HtmlEncode(GetString("Ecom:Product.Name"))" /> </div> </div> } @foreach (var video in SpecVideos) { <div class="product-thumb"> <div class="product-thumb-inner" data-thumb-type="video"> <img class="img-responsive" src="http://img.youtube.com/vi/@(video.Value)/1.jpg" alt="@System.Web.HttpUtility.HtmlEncode(GetString("Ecom:Product.Name"))" /> </div> </div> } </div> } } else { <div class="product-images"> <div class="product-image"> <div class="product-image-inner"> <img class="img-responsive" src="/Admin/Public/GetImage.ashx?&amp;Width=400&amp;Height=400&amp;Crop=5&amp;Compression=80&amp;Image=/Files/Images/Ecom/default.png" alt="@Translate("No image","No image")" /> </div> </div> </div> }</text> } else { <text>@inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> @if (image.GetImages().Any()) { <div class="product-images" id="product-images"> @if (image.GetImages().Any()) { foreach (var images in image.GetImages()) { <a class="product-image mfp-zoom" href="/Admin/Public/GetImage.ashx?Width=1000&amp;Height=1000&amp;Crop=5&amp;Compression=80&amp;Image=@(images.Url)"> <img itemprop="image" class="img-responsive" src="/Admin/Public/GetImage.ashx?Width=400&amp;Height=400&amp;Crop=5&amp;Compression=80&amp;Image=@(images.Url)" alt="@System.Web.HttpUtility.HtmlEncode(GetString("Ecom:Product.Name"))" /> </a> } } @if (!String.IsNullOrEmpty(GetString("Ecom:Product:Field.YoutubeVideoID"))) { var YoutubeSrc = "https://www.youtube-nocookie.com/embed/" + GetString("Ecom:Product:Field.YoutubeVideoID") + "?rel=0"; <div class="product-image"> <iframe src="@YoutubeSrc" width="640" height="360" frameborder="0" allowfullscreen></iframe> </div> } @if (!String.IsNullOrEmpty(GetString("Ecom:Product:Field.VimeoVideoID"))) { var VimeoSrc = "https://player.vimeo.com/video/" + GetString("Ecom:Product:Field.VimeoVideoID") + "?byline=0"; <div class="product-image"> <iframe src="@VimeoSrc" width="640" height="360" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe> </div> } </div> <div id="product-images-thumbs" class="product-thumbs"> @if (image.GetImages().Count() > 1 || image.GetImages().Any() && !String.IsNullOrEmpty(GetString("Ecom:Product:Field.YoutubeVideoID")) || !String.IsNullOrEmpty(GetString("Ecom:Product:Field.VimeoVideoID"))) { foreach (var images in image.GetImages()) { <div class="product-thumb"> <div class="product-thumb-inner" data-thumb-type="image"> <img class="img-responsive" src="/Admin/Public/GetImage.ashx?Width=110&amp;Height=110&amp;Crop=5&amp;Compression=80&amp;Image=@(images.Url)" alt="@System.Web.HttpUtility.HtmlEncode(GetString("Ecom:Product.Name"))" /> </div> </div> } } @if (!String.IsNullOrEmpty(GetString("Ecom:Product:Field.YoutubeVideoID"))) { <div class="product-thumb"> <div class="product-thumb-inner" data-thumb-type="video"> <span class="product-thumb-play"><i class="icon-youtube icon-5x" aria-hidden="true"></i></span> </div> </div> } @if (!String.IsNullOrEmpty(GetString("Ecom:Product:Field.VimeoVideoID"))) { <div class="product-thumb"> <div class="product-thumb-inner" data-thumb-type="video"> <span class="product-thumb-play"><i class="icon-vimeo icon-5x" aria-hidden="true"></i></span> </div> </div> } </div> } else { <div class="product-images"> <div class="product-image"> <div class="product-image-inner"> <img class="img-responsive" src="/Admin/Public/GetImage.ashx?Image=@(image.GetFirstImage().Url)&amp;Width=400&amp;Height=400&amp;Crop=5&amp;Compression=80" /> </div> </div> </div> }</text> } </div> <div class="col-xs-12 col-sm-6 product-data"> @if (specs.GetByKey("BrandSymbol") != null) { var brandSymbol = specs.GetByKey("BrandSymbol"); if (brandSymbol != null && !string.IsNullOrEmpty(brandSymbol.Value)) { <div class="brand-logo"> <img src="/Admin/Public/GetImage.ashx?Width=225&amp;Height=60&amp;Compression=80&amp;Crop=5&amp;Image=/Files/Images/XPI/@brandSymbol.Value" alt="@brandSymbol.Value" class="img-responsive" /> </div> } } <h1 itemprop="name" class="title-styled"> @System.Web.HttpUtility.HtmlEncode(GetString("Ecom:Product.Name")) </h1> <p class="print text-right"> <span class="product-id pull-left"> <i class="pe-is-ec-label-3-f pe-va"></i> @Translate("Product Number", "Product Number"): <span class="value" itemprop="sku"> @GetString("Ecom:Product.Number") </span> </span> @* Fix this href so it uses the NORRIQ.SEO URL "NIQ:ProductUrl" *@ <a class="hidden-print" rel="nofollow" href="@Navigation.GetUrlByNavigationTag("productsheet")?ProductID=@GetString("Ecom:Product.ID")&amp;VariantID=@GetString("Ecom:Product.VariantID")&amp;PDF=true&amp;Filename=@(GetString("Ecom:Product.Number")).pdf"><i class="pe-is-hs-printer-f" aria-hidden="true"></i> @Translate("Print PDF", "Print PDF")</a> </p> @if (!productScope_isSubstituteProduct) { <div class="product-price text-right" itemprop="offers" itemscope="" itemtype="http://schema.org/Offer"> @* Pricing *@ @* Volume prices *@ @if (isVolumePriceDiscount) { <div class="pricing indent"> @* <-- add class 'indent' when user is anonymous*@ <div class="table-responsive"> <table class="table table-condensed volume-table async-price-volumenpriser"> <tbody> @foreach (var volumenpris in volumenpriser.Priser) { <tr> @if (volumenpris.TranslatedUnitCaption.Equals(volumenpriser.BaseUnit)) { <td class="text-left">@volumenpris.MinimumQuantity x @volumenpris.TranslatedUnitCaption</td> } else { <td class="text-left">@volumenpris.MinimumQuantity @volumenpris.TranslatedUnitCaption (@volumenpris.MinimumQuantityInBaseUnit @volumenpriser.BaseUnit)</td> } @if (Pageview.User.LoggedIn) { <td class="text-right"> @volumenpriser.BaseUnit <span class="async-price-total" data-price-mode="details"> <i class="spinner-sm-default"></i> </span> </td> } else { <td class="text-right">@Translate("Volume Per", "pr.") @volumenpriser.BaseUnit @volumenpris.GetConvertedBOMPrice().ToString("N") @volumenpris.ConvertToCurrencyCode</td> } </tr> } </tbody> </table> </div> </div> } @if (Pageview.User.LoggedIn && !hidePrices) { <div class="pricing"> <table class="table table-condensed pricing-table no-margin"> <thead> <tr> <th class="text-left"></th> <th class="text-right js-hide-before" data-show-on-before-price="true">@Translate("NormalPrice", "Normalpris")</th> <th class="text-right js-hide-before font-color-red">@Translate("Discount", "Rabat")</th> <th class="text-right">@Translate("YourPrice", "Din pris")</th> </tr> </thead> <tbody> @foreach (var unit in units) { var supUnit = unit.SupplementalUnit; <tr class="async-price" data-product-key='@(this.GetJsonPriceKey(unit.UnitId))' data-product-retail-price='@(this.GetJsonRetailPrice(unit.UnitId))'> @if (unit.UnitName.Equals(supUnit.Bom)) { bool showSupplementalInfo = supUnit.BaseContentFactor > 0 && !string.IsNullOrEmpty(supUnit.BaseContentUOM); <td class="text-left">1 @unit.UnitName @(showSupplementalInfo ? string.Format("({0} {1})", @supUnit.BaseContentFactor, @supUnit.BaseContentUOM): "") </td> } else { <td class="text-left">1 @unit.UnitName (@supUnit.QtyInBaseUnitOfMeasure @supUnit.Bom) </td> } <td class="text-right font-striked"> <span class="js-hide-before" data-show-on-before-price="true"> <span class="async-price-unit" data-price-mode="details"> <i class="spinner-sm-default"></i> </span> </span> </td> <td class="text-right font-l font-color-red"> <span class="js-hide-before"> <span class="async-price-discount font-color-red" data-price-mode="details"> <i class="spinner-sm-default"></i> </span> </span> </td> <td class="text-right font-l"> <span> <span class="async-price-total" itemprop="price" content="@pricePForGoogle" data-price-mode="details"> <i class="spinner-sm-default"></i> </span> </span> </td> </tr> } @*Clone this *@ <tr id="async-price-baseunitOUM-template" data-informative-unit-price="" style="display:none; visibility:hidden"> <td class="text-left">1 <span class="async-price-baseunitOUM"></span></td> <td class="text-right font-striked"> <span data-show-on-before-price="true"> <span class="async-price-unit" data-price-mode="details"> <i class="spinner-sm-default"></i> </span> </span> </td> <td class="text-right font-l font-color-red"> @*<span class="js-hide-before"> <span class="async-price-discount font-color-red" data-price-mode="details"> <i class="spinner-sm-default"></i> </span> </span>*@ </td> <td class="text-right font-l"> <span> <span class="async-price-total" data-price-mode="details"> <i class="spinner-sm-default"></i> </span> </span> </td> </tr> </tbody> @if (packingSpec != null) { <tfoot> <tr> <td class="text-left" colspan="5">@Translate("ReMarks", "Bemærkninger:") @packingSpec.Value</td> </tr> </tfoot> } </table> </div> } else if (!hidePrices) { <div class="pricing indent"> </div> } @* Product Fees *@ @* Ifølge Emnelog ID 39 er der kun gebyrer på den danske shop. *@ @* Fee are outcommented from PDP on request from anthony *@ @* @if (Dynamicweb.Frontend.PageView.Current().AreaID == 1 && productFees.HasFees() && productFees.IsValid()) { <div class="text-right"> <ul class="list-unstyled js-fee-container"> @foreach (var fee in productFees.Fees) { var skipFee = !units.Select(u => u.UnitId).Contains(fee.UnitCode); if (skipFee) { continue; } var unit = units.FirstOrDefault(u => string.Equals(u.UnitId, fee.UnitCode)); var unitLabel = unit != null ? unit.UnitName : fee.UnitCode; <li data-fee-unit-key="@fee.UnitCode">@fee.Description @fee.GetConvertedFeePrice().ToString("N") @fee.GetDisplayCurrency() / @unitLabel</li> } </ul> </div> } *@ </div> <div class="product-info hidden-print"> <form class="form-horizontal form-product clearfix" id="prodform_@GetString("Ecom:Product:Page.ID")" name="prodform_@GetString("Ecom:Product:Page.ID")" method="post" action="@GetGlobalValue("Global:Pageview.Url.Raw")"> @* Because of DW and their use of Default units, we have to do this the manual way: http://doc.dynamicweb.com/documentation-8/ecommerce/product-catalog/products#sideNavTitle1-2-5-4 The ones commented out has been deemed not necessary. *@ @*@GetString("Ecom:Product.Form.Clean")*@ @*<input type="hidden" name="ProductURL" id="ProductURL" value="" />*@ <input type="hidden" name="CartCmd" value="add" /> <input type="hidden" name="ProductID" value="@(GetString("Ecom:Product.ID"))" /> <input type="hidden" name="VariantID" value="" /> @*<input type="hidden" name="UnitID" id="UnitID" value="STK" />*@ @*<input type="hidden" name="wishListID" id="wishListID" value="0" />*@ <label for="quantity" class="sr-only">@Translate("Qty", "Qty")</label> <div class="form-group"> <div class="col-sm-4"> <ordering-list-request-product-condition product-key='@GetString("Ecom:Product.ID")' inline-template> <div class=""> <template v-if="loading"> <div class="loading"> <span class="spinner-sm-default"></span> </div> </template> <template v-if="!loading"> <div class="input-group"> <div class="input-group-addon"> @Translate("Product antal", "Antal") </div> <input name="quantity" value="1" min="1" type="number" class="form-control form-control-qty text-center" autocomplete="off" :disabled="isRestricted && !isAvailable" /> </div> </template> </div> </ordering-list-request-product-condition> </div> <div class="col-sm-4"> <div class="popover-trigger"> <select name="UnitId" id="unitIdSelector" class="form-control form-unit unit-input JS-ASYNC-UNITSELECTOR JS-ASYNC-INPUT-VALUE" @(units.Count() <= 1 ? "readonly" : "") data-trigger-async-price="false"> @foreach (var unit in units) { <option value="@unit.UnitId" @(String.Equals(unit.UnitId, defaultUnitId) ? "selected" : "")>@unit.UnitName</option> } </select> </div> <div class="hide my-popover-content"> @RazorProductSupplementalPopup(productUnitInformation) </div> </div> <div class="col-sm-4"> @if (Pageview.User.LoggedIn) { <div class="product-button"> @RenderBuyButton(this, "PDP") </div> } else { <p> @Translate("product_view_loginToPurchase", "Log ind for at købe varen") </p> } </div> </div> </form> <div class="row"> @* Stocks *@ @* Stocks bliver hele tiden opdateret via asynkrone kald pga. at units og produktliste bliver loadet, derfor behøver vi ikke dette til at vise rigtig stocks. *@ @if (Pageview.User.LoggedIn) { <div class="col-xs-6 async-price" data-product-key='@(this.GetJsonPriceKey())' data-product-retail-price='@(this.GetJsonRetailPrice())'> <span class="async-price-stock"> <i class="spinner-sm-default"></i> </span> </div> } else { <div class="col-xs-6"> @{ var stock = GetDouble("Ecom:Product.Stock"); var isStykliste = GetBoolean("Ecom:Product:Field.Stykliste.Value"); var isSkaffevare = GetBoolean("Ecom:Product:Field.Skaffevare.Value"); } @if (isSkaffevare && stock == 0) { <i class="icon-stock icon-blue" title="@Translate("label_skaffevare", "Skaffevare")"></i> <span class="stock-label-text">@Translate("label_skaffevare", "Skaffevare")</span> } else { if (stock < 1 && !isStykliste) { <i class="icon-stock icon-yellow" title="@Translate("label_in_stock_in_x_days", "Forventes på lager indenfor 4 dage.")"></i> <span class="stock-label-text">@Translate("label_in_stock_in_x_days", "Forventes på lager indenfor 4 dage.")</span> } else { <i class="icon-stock icon-green" title="@stock"></i> if (isOutlet) { <span class="stock-label-text">@stock @Translate("label_in_stock", "In stock")</span> } else { <span class="stock-label-text">@Translate("label_in_stock", "In stock")</span> } } } </div> } @* Favoritelist *@ @if (Pageview.User.LoggedIn) { <div class="col-xs-6 text-right hidden-print"> @RenderFavoriteListIcon(this) </div> } </div> </div> <text>@using NLWI.Platforms.Dynamicweb8.Specs; @using NLWI.Platforms.Dynamicweb8.Specs.ViewModels @using StandardWebshop.CustomCode.ColorLookup @using StandardWebshop.CustomCode.Razor @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> @{ var specsRef = ((ProductSpecifications)specs); var databladeFiles = new List<ProductSpecification>(); var listOfDataBladeKey = new List<string> { "Datablade", "EnvironmentDocs", "DeclarationOfConformity", "SparePartsCatalogue", "UserGuide", "SafetyDatasheet", "SizeGuide" }; foreach (var key in listOfDataBladeKey) { var currentDataBlade = specsRef.GetAllByKey(key); databladeFiles.AddRange(currentDataBlade); } //var specs = this.GetProductSpecifications(); var showDescription = !String.IsNullOrWhiteSpace(GetString("Ecom:Product.LongDescription")) || !String.IsNullOrEmpty(specsRef.GetByKey("Produktbeskrivelse").Value); var showTabs = showDescription || specsRef.GetByGroup("Specifikationer").Any() || databladeFiles.Any(); var colorLookupService = ObjectFactory.GetInstance<ColorLookupService>(); } @if (showTabs) { <ul class="nav nav-tabs product-nav-tabs" role="tablist"> @if (showDescription) { <li role="presentation" class="active"> <a href="#desc" aria-controls="desc" role="tab" data-toggle="tab"> @Translate("Description", "Description") </a> </li> } @if (specsRef.GetByGroup("Specifikationer").Any()) { <li role="presentation" class="@(!showDescription ? "active": "")"> <a href="#specs" aria-controls="specs" role="tab" data-toggle="tab"> @Translate("Specifications", "Specifications") </a> </li> } @if (databladeFiles.Any()) { <li role="presentation" class="@(!showDescription && !specsRef.GetByGroup("Specifikationer").Any() ? "active": "")"> <a href="#docs" aria-controls="docs" role="tab" data-toggle="tab"> @Translate("Documents", "Documents") </a> </li> } </ul> <div class="tab-content product-tab-content"> @if (showDescription) { <div role="tabpanel" class="tab-pane active" id="desc" itemprop="description"> @specsRef.GetByKey("Produktbeskrivelse").Value </div> } @if (specsRef.GetByGroup("Specifikationer").Any()) { <div role="tabpanel" class="tab-pane @(!showDescription ? "active": "")" id="specs"> @RenderSpecifications(specsRef, "table", "BrandSymbol") </div> } @if (databladeFiles.Any()) { <div role="tabpanel" class="tab-pane @(!showDescription && !specsRef.GetByGroup("Specifikationer").Any() ? "active": "")" id="docs"> <ul class="list-unstyled"> @foreach (var specFile in databladeFiles) { var originalFilename = specFile.GetReferenceSpecification().GetByKey("Filename").Value; var title = originalFilename.Replace("_", " ").Replace("-", " "); <li> <a download="@originalFilename" href="/Files/XPI-Files/@(specFile.Value)" title="@originalFilename"> @specFile.Caption </a> </li> } </ul> </div> } </div> } </text> //end isSubstitute product statement } else { //if the product is a substitution product render this section instead. //This way to scope the feature is much easier to maintain changes in the future <div class="substitute-information-wrapper"> <p class="print"> @if (productScope_discountedCompletely) { @Translate("product_view_discountedCompletelyProductSection", "Denne vare er udgået af vores sortiment.") } else if (productScope_discountedTemporary) { @Translate("product_view_discountedTemporaryProductSection", "Denne vare er midlertidig udgået.") } else { //NOT SUPPORTED.. } </p> </div> <text>@inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> @{ Columns = "col-md-8"; } @if (GetLoop("ProductRelatedGroups").Any()) { foreach (var grp in GetLoop("ProductRelatedGroups")) { if (!grp.GetString("Ecom:Product:RelatedGroup.GroupID").Equals("RELGRP3")) { //Skip if this is NOT RELGRP3 continue; } if (grp.GetLoop("RelatedProducts").Where(x => !x.GetBoolean("NIQ:Product.PRIVATE")).Any()) { //TODO: add substitute products to all languages <h2 class="title-styled"> @grp.GetString("Ecom:Product:RelatedGroup.Name") </h2> <div class="productlist-grid-flex" id="[email protected]("Ecom:Product:RelatedGroup.GroupID")"> @{ var substituteProductList = grp.GetLoop("RelatedProducts").Where(x => !x.GetBoolean("NIQ:Product.PRIVATE")); } @foreach (var product in substituteProductList) { <text>@using System.Globalization @using System.Web.Mvc.Html @using Dynamicweb.NewsLetterV3 @using NORRIQ.EcomMedia @using StandardWebshop.CustomCode.Razor @using NORRIQ.Common8.Razor; @using NORRIQ.Common8.Factory @using Newtonsoft.Json @using Dynamicweb.eCommerce.Common; @using Dynamicweb.eCommerce.Products @using StandardWebshop.CustomCode.SupplementalUnit @using StandardWebshop.CustomCode.ViewModels.Variants; @using StandardWebshop.CustomCode.Volumenpriser @using StandardWebshop.CustomCode.Units; @using StandardWebshop.CustomCode.Units.Models @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> @{ var currentUser = Dynamicweb.Modules.UserManagement.User.GetCurrentUser(); var hidePrice = false; if (currentUser != null) { hidePrice = currentUser.CustomFieldValues.FirstOrDefault(cf => cf.CustomField.SystemName == "AccessUser_HidePrices").Value.ToString().ToLower() == "true" ? true : false; } //this is required do to lazy loading //product.GetLoop("Units").Select(u => new //{ // UnitId = u.GetString("Ecom:VariantOption.ID"), // // Change the number format here: // UnitPriceDouble = (u.GetDouble("Ecom:VariantOption.Price.PricePIP") / 100d), // UnitName = u.GetString("Ecom:VariantOption.Name"), // UnitObj = u //}).OrderBy(x => x.UnitPriceDouble); var link = product.GetString("NIQ:ProductUrl"); var tilbud = product.GetBoolean("Ecom:Product:Field.Tilbud.Value"); var buy = "/default.aspx?ID=" + Navigation.GetPageIdByNavigationTag("ecom") + "&amp;productid=" + product.GetString("Ecom:Product.ID") + "&amp;cartcmd=add"; var area = GetGlobalValue("Global:Area.Lang"); var media = NORRIQ.EcomMedia.Frontend.GetProductMedia(product); var ProductSpecs = product.GetProductSpecifications(); var Image = ProductSpecs.GetAllByKey("Image").Any() ? "/Files/Images/XPI/" + ProductSpecs.GetByKey("Image").Value : media.GetFirstImage().Url; var isLoggedIn = Pageview.User.LoggedIn; var priceForGoogle = product.GetString("NIQ:PriceForGoogle"); var btn_addText = Translate("Add to cart", "Add to cart"); // Units var unitInformation = product.GetUnitInformation() as UnitInformationViewModel; var productListUnits = unitInformation.Units; var productListDefaultUnit = unitInformation.ProductDefaultUnit; //volumenPrices var productgridVolumenpriser = product.GetVolumenpriser(); bool discountedCompletely = product.GetBoolean("NIQ:Product.DiscontunedCompletely"); bool discountedTemporary = product.GetBoolean("NIQ:Product.DiscontunedTemporary"); bool isSubstituteProduct = discountedTemporary || discountedCompletely; string substituteProductID = product.GetString("NIQ:Product.SubstituteProductId"); string subStituteLink = string.Empty; if (isSubstituteProduct && substituteProductID != null) { subStituteLink = string.Format("/Default.aspx?ID={0}&productID={1}", NORRIQ.Common8.Razor.Navigation.GetPageIdByNavigationTag("ecom"), substituteProductID); } tilbud = tilbud || productListUnits.Any(x => x.IsInformativePrice); var productGridIsVolumenDiscount = productgridVolumenpriser.HasPrices() && productgridVolumenpriser.IsValid(); } @if (productListDefaultUnit != null) { <product product-key="@product.GetString("Ecom:Product.ID")" inline-template> <template> <div v-bind:class="{hide: hide, fadeout : fadeout}" class="product-wrapper @Columns @(!isSubstituteProduct ? "async-price " : "" ) js-favProduct" data-product-display="flex" data-product-key-clean='@(product.GetString("Ecom:Product.ID"))' data-product-key='@(product.GetJsonPriceKey((string)productListDefaultUnit.UnitId))' data-product-retail-price='@(product.GetJsonRetailPrice())' data-product-unit-information='@JsonConvert.SerializeObject(unitInformation)'> <div itemscope itemtype="http://schema.org/Product" class="productlist-grid-product"> @{ var isNyhed = product.GetBoolean("Ecom:Product:Field.Nyhed.Value"); var isOutle = product.GetBoolean("Ecom:Product:Field.Outlet.Value"); } @RenderProductLabels(tilbud, productGridIsVolumenDiscount, discountedCompletely, discountedTemporary, isNyhed, isOutle) <a class="productlist-grid-image" href="@link" itemprop="url"> <img src="/Admin/Public/GetImage.ashx?Width=200&amp;Height=200&amp;Crop=5&amp;Compression=80&amp;Image=@Image" class="img-responsive" alt="@System.Web.HttpUtility.HtmlEncode(product.GetString("Ecom:Product.Name"))" itemprop="image" /> </a> <div class="productlist-grid-caption"> <a href="@link" class="productlist-grid-name" itemprop="name"> @System.Web.HttpUtility.HtmlEncode(product.GetString("Ecom:Product.Name")) </a> </div> <div class="offer" itemprop="offers" itemscope="" itemtype="http://schema.org/Offer"> @if (!isSubstituteProduct) { <div class="productlist-grid-info"> <span class="productlist-grid-number"> @Translate("Product Number", "Product Number") <span itemprop="sku">@product.GetString("Ecom:Product.Number")</span> </span> <span class="productlist-grid-stock"> @if (Pageview.User.LoggedIn) { <span class="async-price-stock" itemprop="availability"> <span class="spinner-sm-default"></span> </span> } else { @RenderStockInformations(product) } </span> </div> <div class="productlist-grid-footer"> <div class="productlist-grid-price-info"> <div class="productlist-grid-price js-price-container"> @if (Pageview.User.LoggedIn && !hidePrice) { <span class="async-price-unit"></span> <span class="productlist-grid-price-price async-price-total" itemprop="price"></span> } </div> </div> @if (ObjectFactory.GetInstance<NORRIQ.Common8.Context.AreaItemSettings>().GetCurrentAreaValue<string>("ProductlistGridHideButton") == "False") { <div class="productlist-grid-buying"> @if (product.GetLoop("VariantGroups").Any()) { <a href="@link" class="btn btn-buy"> <span class="product-added-text">@Translate("Buy", "Buy")</span> </a> } else { <form class="form" id="[email protected]("Ecom:Product.ID")" name="[email protected]("Ecom:Product.ID")" method="post" action="/Default.aspx?ID=@GetGlobalValue("Global:Page.ID")"> @* Because of DW and their use of Default units, we have to do this the manual way: http://doc.dynamicweb.com/documentation-8/ecommerce/product-catalog/products#sideNavTitle1-2-5-4 The ones commented out has been deemed not necessary. *@ @*@GetString("Ecom:Product.Form.Clean")*@ @*<input type="hidden" name="ProductURL" id="ProductURL" value="" />*@ <input type="hidden" name="CartCmd" value="add" /> <input type="hidden" name="ProductID" value="@(product.GetString("Ecom:Product.ID"))" /> <input type="hidden" name="VariantID" value="" /> @*<input type="hidden" name="UnitID" id="UnitID" value="STK" />*@ @*<input type="hidden" name="wishListID" id="wishListID" value="0" />*@ @{ } <ordering-list-request-product-condition product-key='@product.GetString("Ecom:Product.ID")' inline-template> <div class=""> <template v-if="loading"> <div class="loading"> <span class="spinner-sm-default"></span> </div> </template> <div v-show="!loading" class="input-group popover-trigger"> <input name="quantity" value="1" min="1" max="99999" type="number" class="form-control text-center" autocomplete="off" data-trigger="focus" data-rule-number="true" data-rule-min="1" :disabled="isRestricted && !isAvailable" /> <span class="input-group-btn"> <select name="UnitId" class="form-control form-unit unit-input JS-ASYNC-UNITSELECTOR JS-ASYNC-INPUT-VALUE" @(productListUnits.Count() <= 1 ? "readonly" : "")> @foreach (var unit in productListUnits) { <option value="@unit.UnitId" @(String.Equals(unit.UnitId, productListDefaultUnit.UnitId) ? "selected" : "")>@unit.UnitName</option> } </select> </span> </div> <div class="hide my-popover-content"> @RazorProductSupplementalPopup(unitInformation) </div> </div> </ordering-list-request-product-condition> @if (Pageview.User.LoggedIn) { @RenderBuyButton(product, "grid") } </form> } </div> } </div> } else { //if the product is a substitution product render this section instead. //This way to scope the feature is much easier to maintain changes in the future <div class="productlist-grid-info"> <span class="productlist-grid-number"> @Translate("Product Number", "Product Number") <span itemprop="sku">@product.GetString("Ecom:Product.Number")</span> </span> <span class="productlist-grid-stock"> @RenderStockInformations(product, true) </span> </div> <a class="btn btn-primary btn-block btn-air" href="@subStituteLink">@Translate("erstatningsvare")</a> } </div> @if (isLoggedIn && !product.GetLoop("VariantGroups").Any()) { <div class="productlist-grid-buttons"> @RenderFavoriteListIcon(product) </div> } </div> </div> </template> </product> } </text> } </div> } } }</text> } </div> </div> </section> <div class="col-xs-12"> <div class="row"> <div class="col-xs-12 product-related hidden-print"> @using System.Globalization @using System.Web.Mvc.Html @using Dynamicweb.NewsLetterV3 @using NORRIQ.EcomMedia @using StandardWebshop.CustomCode.Razor @using NORRIQ.Common8.Razor; @using NORRIQ.Common8.Factory @using Dynamicweb.eCommerce.Common; @using Newtonsoft.Json @using StandardWebshop.CustomCode.ViewModels.Variants; @using NLWI.Platforms.Dynamicweb8.Specs @using StandardWebshop.CustomCode.ColorLookup @using StandardWebshop.CustomCode.Razor @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> @if (GetLoop("ProductRelatedGroups").Any()) { foreach (var grp in GetLoop("ProductRelatedGroups")) { if (grp.GetString("Ecom:Product:RelatedGroup.GroupID").Equals("RELGRP2")) { <h2 class="title-styled"> @grp.GetString("Ecom:Product:RelatedGroup.Name") </h2> var productsBinding = grp.GetLoop("RelatedProducts").Where(x => !x.GetBoolean("NIQ:Product.PRIVATE")); tableModeBinding = "variants"; <text>@using System.Globalization @using System.Web.Mvc.Html @using Dynamicweb.NewsLetterV3 @using NORRIQ.EcomMedia @using StandardWebshop.CustomCode.Razor @using NORRIQ.Common8.Razor; @using NORRIQ.Common8.Factory @using Newtonsoft.Json @using Dynamicweb.eCommerce.Common; @using NLWI.Platforms.Dynamicweb8.Specs @using StandardWebshop.CustomCode.ColorLookup @using StandardWebshop.CustomCode.SupplementalUnit @using StandardWebshop.CustomCode.Units.Models @using StandardWebshop.CustomCode.ViewModels.Variants; @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> @{ var tableUser = Dynamicweb.Modules.UserManagement.User.GetCurrentUser(); var hidePriceinTableView = false; if (tableUser != null) { hidePriceinTableView = tableUser.CustomFieldValues.FirstOrDefault(cf => cf.CustomField.SystemName == "AccessUser_HidePrices").Value.ToString().ToLower() == "true" ? true : false; } var addToCartMode = ObjectFactory.GetInstance<NORRIQ.Common8.Context.AreaItemSettings>().GetCurrentAreaValue<string>("AddToCartMode"); var colorLookupService2 = ObjectFactory.GetInstance<ColorLookupService>(); var isLoggedIn = Pageview.User.LoggedIn; var products = productsBinding; if (products == null) { throw new Exception("product table binding reference is not set!"); } string tableMode = tableModeBinding; } <table class="table table-striped table-block productlist-table js-product-table"> <thead> <template v-if="!loading"> <tr> <th class="visible-printxx"></th> <th class="productlist-table-product"> @Translate("Product", "Product") </th> @*start Variant headers*@ <th class="productlist-table-variant">@*Description: variant size*@</th> <th class="productlist-table-variant">@*Description: variant color*@</th> @*end Variant headers*@ <th class="productlist-table-number" nowrap> @Translate("Product Number", "Product Number") </th> <th class="productlist-table-stock" nowrap> @Translate("Stock", "Stock") </th> @if (isLoggedIn) { <th class="productlist-table-favorite"> @if (isFavoriteList) { <orderinglist-filter></orderinglist-filter> } @*<i class="icon-favorite-added" aria-hidden="true"></i><span class="sr-only">@Translate("Favorite", "Favorite")</span>*@ </th> } @if (!hidePriceinTableView) { <th class="productlist-table-price"> @Translate("Price", "Price") </th> } <th> @Translate("Unit", "Unit") </th> <th class="productlist-table-quantity"> @Translate("Quantity", "Quantity") </th> </tr> </template> </thead> <tbody> @foreach (var product in products) { var tilbud = product.GetBoolean("Ecom:Product:Field.Tilbud.Value"); var LoopCounter = product.GetInteger("Ecom:Product.LoopCounter") - 1; var media = NORRIQ.EcomMedia.Frontend.GetProductMedia(product); var link = product.GetString("NIQ:ProductUrl"); var area = GetGlobalValue("Global:Area.Lang"); var productSpecs = product.GetProductSpecifications(); var Image = productSpecs.GetAllByKey("Image").Any() ? "/Files/Images/XPI/" + productSpecs.GetByKey("Image").Value : media.GetFirstImage().Url; var variants = product.GetLoop("VariantGroups").GetVariants(); // In IBH, the Product Number can be used as a unique product identifier. var currentProductNumber = product.GetString("Ecom:Product.Number"); // All variant products and their associated variant groups/options. var variantProducts = product.GetLoop("VariantCombinations").GetVariantProducts(variants, currentProductNumber); var productsDictionary = VariantViewModelBuilder.GetProductsInDimensionOrder(variants, variantProducts); var selectedVariant = VariantViewModelBuilder.GetSelectedOrEmpty(variantProducts); //variants var productSpecGroup = productSpecs.GetByGroup("Specifikationer"); //custom size names IEnumerable<string> filterSizeKeys = new List<string> { "specs_Handskestorrelse", "specs_Toejstoerrelse", "specs_Skostoerrelse", "specs_Stoerrelse" }; //remove prefix "specs_" filterSizeKeys = filterSizeKeys.Select(s => s.Replace("specs_", "")); var sizeObj = productSpecs.FirstOrDefault(x => filterSizeKeys.Any(s => s.Equals(x.Key)) && !string.IsNullOrEmpty(x.Value)); var colorList = productSpecGroup.Where(x => x.Key.Equals("Farve") && !string.IsNullOrEmpty(x.Value)); //end variants bool discountedCompletely = product.GetBoolean("NIQ:Product.DiscontunedCompletely"); bool discountedTemporary = product.GetBoolean("NIQ:Product.DiscontunedTemporary"); bool isSubstituteProduct = discountedTemporary || discountedCompletely; string substituteProductID = product.GetString("NIQ:Product.SubstituteProductId"); string subStituteLink = string.Empty; if (isSubstituteProduct && substituteProductID != null) { subStituteLink = string.Format("/Default.aspx?ID={0}&productID={1}", NORRIQ.Common8.Razor.Navigation.GetPageIdByNavigationTag("ecom"), substituteProductID); } // Units var unitInformation = product.GetUnitInformation() as UnitInformationViewModel; var productListUnits = unitInformation.Units; var productListDefaultUnit = unitInformation.ProductDefaultUnit; var listDefaultUnitId = productListDefaultUnit.UnitId;//;product.GetString("Ecom:Product.DefaultUnitID"); tilbud = tilbud || productListUnits.Any(x => x.IsInformativePrice); var volumePrices = product.GetVolumenpriser(); var isVolumenDiscount = volumePrices.HasPrices() && volumePrices.IsValid(); @* These lines are required because lazy load's its data. product.GetString("Ecom:VariantGroup.Label") product.GetString("Ecom:VariantGroup.Name") product.GetLoop("VariantAvailableOptions") product.GetString("Ecom:VariantOption.ID") product.GetString("Ecom:VariantOption.Name") *@ <template> <product product-key="@product.GetString("Ecom:Product.ID")" inline-template> <template> <tr @(Pageview.User.LoggedIn ? "v-bind:class='{hide: hide, fadeout : fadeout}'" : string.Empty) itemprop="offers" itemscope="" itemtype="http://schema.org/Offer" class="product-wrapper async-price js-favProduct" data-product-key-clean='@(product.GetString("Ecom:Product.ID"))' data-product-key='@(product.GetJsonPriceKey())' data-product-retail-price='@(product.GetJsonRetailPrice())' data-product-unit-information='@JsonConvert.SerializeObject(unitInformation)'> <td align="left" width="50" class="visible-printxx"> @if (tableMode == "variants") { <div class="image-wrapper"> <img itemprop="image" class="img-responsive" src="/Admin/Public/GetImage.ashx?Width=400&amp;Height=400&amp;Crop=5&amp;Compression=80&amp;Image=@Image" /> </div> } else { //default <img src="/Admin/Public/GetImage.ashx?Width=40&amp;Height=35&amp;Crop=5&amp;Compression=85&amp;Image=@Image" /> } </td> <td class="productlist-table-product"> @{ var isNyhed = product.GetBoolean("Ecom:Product:Field.Nyhed.Value"); var isOutle = product.GetBoolean("Ecom:Product:Field.Outlet.Value"); } @RenderProductLabels(tilbud, isVolumenDiscount, discountedCompletely, discountedTemporary, isNyhed, isOutle) <a href="@link" tabindex="0" class="productlist-table-name" itemprop="name"> @System.Web.HttpUtility.HtmlEncode(product.GetString("Ecom:Product.Name")) </a> </td> @*start Variant rows*@ <td class="productlist-table-variant productlist-table-size"> <span>@(sizeObj != null ? sizeObj.Value : string.Empty)</span> </td> <td class="productlist-table-variant productlist-table-color"> @if (colorList.Any()) { foreach (var colorObj in colorList) { var color = colorLookupService2.GetColorKey(colorObj.Value); <span class="spec-color spec-color-@color"></span> } } </td> @*end Variant rows*@ <td class="productlist-table-number" itemid="sku" data-label="@Translate("Product No", "Product No")" nowrap> @product.GetString("Ecom:Product.Number") </td> @if (isSubstituteProduct) { <td class="productlist-table-stock" itemprop="availability" href="http://schema.org/InStock" data-label="@Translate("Stock", "Stock")" nowrap> @RenderStockInformations(product, isSubstituteProduct) </td> if (isLoggedIn) { <td data-label="Favorite"> @RenderFavoriteListIcon(product, "table") </td> } <td class="productlist-table-price" nowrap="nowrap"></td> <td></td> <td class="productlist-table-variant"> <a class="btn btn-primary btn-block" href="@subStituteLink">@Translate("erstatningsvare")</a> </td> <td colspan="2"> <a class="btn btn-primary btn-block" href="@subStituteLink">@Translate("erstatningsvare")</a> </td> } else { if (isLoggedIn) { <td class="productlist-table-stock async-price-stock" itemprop="availability" href="http://schema.org/InStock" data-label="@Translate("Stock", "Stock")" nowrap> <i class="spinner-sm-default"></i> </td> } else { <td class="productlist-table-stock" itemprop="availability" href="http://schema.org/InStock" data-label="@Translate("Stock", "Stock")" nowrap> @RenderStockInformations(product, isSubstituteProduct) </td> } if (isLoggedIn) { <td data-label="Favorite"> @RenderFavoriteListIcon(product, "table") </td> } if (!hidePriceinTableView) { <td class="productlist-table-price js-price-container" nowrap="nowrap"> @if (isLoggedIn) { <span class="async-price-unit"></span> <span class="productlist-table-price-price async-price-total" itemprop="price" data-label="@Translate("Price", "Price")"> <i class="spinner-sm-default" aria-hidden="true"></i> </span> } else { var defaultUnit = productListUnits.FirstOrDefault(x => x.UnitId.Equals(listDefaultUnitId)); if (defaultUnit != null) { if (defaultUnit.IsInformativePrice) { <span class="product-price-before">@defaultUnit.UnitBeforePrice</span> } <span class="productlist-grid-price-price @(defaultUnit.IsInformativePrice ? "font-hilite" : string.Empty)" itemprop="price" content="@product.GetString("NIQ:PriceForGoogle")"> @defaultUnit.UnitPrice <span itemprop="priceCurrency" content="@Context.Currency.Symbol">@Context.Currency.Symbol</span> </span> } } </td> } @* Units *@ <td> <div class="popover-trigger"> <select name="UnitId" style="min-width: 80px;" class="form-control form-unit unit-input JS-ASYNC-UNITSELECTOR JS-ASYNC-INPUT-VALUE" @(productListUnits.Count() <= 1 ? "readonly" : "")> @foreach (var unit in productListUnits) { <option value="@unit.UnitId" @(String.Equals(unit.UnitId, listDefaultUnitId) ? "selected" : "")>@unit.UnitName</option> } </select> </div> <div class="hide my-popover-content"> @RazorProductSupplementalPopup(unitInformation) </div> </td> if (product.GetLoop("VariantGroups").Any()) { <td class="productlist-table-variant"> <a href="@link" class="btn btn-buy"><i class="icon-minicart" aria-hidden="true"></i> <span class="sr-only">@Translate("Buy", "Buy")</span></a> </td> } else { <td class="productlist-table-quantity"> @* For stadsing, we always have the "Single" add to cart. *@ @if (true || addToCartMode == "single") { <form class="form productlist-table-form" name="[email protected]("Ecom:Product.ID")" method="post" action="@GetGlobalValue("Global:Pageview.Url.Raw")"> @* Because of DW and their use of Default units, we have to do this the manual way: http://doc.dynamicweb.com/documentation-8/ecommerce/product-catalog/products#sideNavTitle1-2-5-4 The ones commented out has been deemed not necessary. *@ @*@GetString("Ecom:Product.Form.Clean")*@ @*<input type="hidden" name="ProductURL" id="ProductURL" value="" />*@ <input type="hidden" name="CartCmd" value="add" /> <input type="hidden" name="ProductID" value="@(product.GetString("Ecom:Product.ID"))" /> <input type="hidden" name="VariantID" value="" /> @*<input type="hidden" name="UnitID" id="UnitID" value="STK" />*@ @*<input type="hidden" name="wishListID" id="wishListID" value="0" />*@ @if (Pageview.User.LoggedIn) { @RenderBuyButton(product, "table") } </form> } else { <input type="tel" class="form-control qty-input text-center" onclick="this.focus();this.select();" name="Quantity@(LoopCounter)" id="Quantity@(LoopCounter)" value="@(product.GetInteger("NIQ:BasketQuantity"))" data-product-autoid="@(product.GetInteger("NIQ:ProductAutoId"))" data-tabindex="@(LoopCounter)" data-trigger="manual" /> <span class="productlist-table-added btn btn-buy qty-input-user-feedback" data-product-autoid="@(product.GetInteger("NIQ:ProductAutoId"))"> @if (product.GetInteger("NIQ:BasketQuantity") > 0) { <i class="icon-added"></i> } else { <i class="icon-minicart"></i> } </span> } </td> } } </tr> </template> </product> </template> } </tbody> </table> </text> <hr class="spacer" /> } } } <template> @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> @{ // Related products Columns = "col-xs-12 col-sm-4 col-md-4"; } @if (GetLoop("ProductRelatedGroups").Any()) { foreach (var grp in GetLoop("ProductRelatedGroups")) { if (grp.GetString("Ecom:Product:RelatedGroup.GroupID").Equals("RELGRP1")) { var relatedProductList = grp.GetLoop("RelatedProducts").Where(x => !x.GetBoolean("NIQ:Product.PRIVATE")).ToList(); if (relatedProductList.Any()) { <header class="basic_related-header" id="related-header"> <h2 class="title-styled"> @grp.GetString("Ecom:Product:RelatedGroup.Name") </h2> </header> if (relatedProductList.Count > 3) { <section class="basic_related"> <slick class="basic_related_slick" ref="slick" :options="slickRelatedOptions"> @foreach (var product in relatedProductList) { <template> @using System.Globalization @using System.Web.Mvc.Html @using Dynamicweb.NewsLetterV3 @using NORRIQ.EcomMedia @using StandardWebshop.CustomCode.Razor @using NORRIQ.Common8.Razor; @using NORRIQ.Common8.Factory @using Newtonsoft.Json @using Dynamicweb.eCommerce.Common; @using Dynamicweb.eCommerce.Products @using StandardWebshop.CustomCode.SupplementalUnit @using StandardWebshop.CustomCode.ViewModels.Variants; @using StandardWebshop.CustomCode.Volumenpriser @using StandardWebshop.CustomCode.Units; @using StandardWebshop.CustomCode.Units.Models @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> @{ var currentUser = Dynamicweb.Modules.UserManagement.User.GetCurrentUser(); var hidePrice = false; if (currentUser != null) { hidePrice = currentUser.CustomFieldValues.FirstOrDefault(cf => cf.CustomField.SystemName == "AccessUser_HidePrices").Value.ToString().ToLower() == "true" ? true : false; } //this is required do to lazy loading //product.GetLoop("Units").Select(u => new //{ // UnitId = u.GetString("Ecom:VariantOption.ID"), // // Change the number format here: // UnitPriceDouble = (u.GetDouble("Ecom:VariantOption.Price.PricePIP") / 100d), // UnitName = u.GetString("Ecom:VariantOption.Name"), // UnitObj = u //}).OrderBy(x => x.UnitPriceDouble); var link = product.GetString("NIQ:ProductUrl"); var tilbud = product.GetBoolean("Ecom:Product:Field.Tilbud.Value"); var buy = "/default.aspx?ID=" + Navigation.GetPageIdByNavigationTag("ecom") + "&amp;productid=" + product.GetString("Ecom:Product.ID") + "&amp;cartcmd=add"; var area = GetGlobalValue("Global:Area.Lang"); var media = NORRIQ.EcomMedia.Frontend.GetProductMedia(product); var ProductSpecs = product.GetProductSpecifications(); var Image = ProductSpecs.GetAllByKey("Image").Any() ? "/Files/Images/XPI/" + ProductSpecs.GetByKey("Image").Value : media.GetFirstImage().Url; var isLoggedIn = Pageview.User.LoggedIn; var priceForGoogle = product.GetString("NIQ:PriceForGoogle"); var btn_addText = Translate("Add to cart", "Add to cart"); // Units var unitInformation = product.GetUnitInformation() as UnitInformationViewModel; var productListUnits = unitInformation.Units; var productListDefaultUnit = unitInformation.ProductDefaultUnit; //volumenPrices var productgridVolumenpriser = product.GetVolumenpriser(); bool discountedCompletely = product.GetBoolean("NIQ:Product.DiscontunedCompletely"); bool discountedTemporary = product.GetBoolean("NIQ:Product.DiscontunedTemporary"); bool isSubstituteProduct = discountedTemporary || discountedCompletely; string substituteProductID = product.GetString("NIQ:Product.SubstituteProductId"); string subStituteLink = string.Empty; if (isSubstituteProduct && substituteProductID != null) { subStituteLink = string.Format("/Default.aspx?ID={0}&productID={1}", NORRIQ.Common8.Razor.Navigation.GetPageIdByNavigationTag("ecom"), substituteProductID); } tilbud = tilbud || productListUnits.Any(x => x.IsInformativePrice); var productGridIsVolumenDiscount = productgridVolumenpriser.HasPrices() && productgridVolumenpriser.IsValid(); } @if (productListDefaultUnit != null) { <product product-key="@product.GetString("Ecom:Product.ID")" inline-template> <template> <div v-bind:class="{hide: hide, fadeout : fadeout}" class="product-wrapper @Columns @(!isSubstituteProduct ? "async-price " : "" ) js-favProduct" data-product-display="flex" data-product-key-clean='@(product.GetString("Ecom:Product.ID"))' data-product-key='@(product.GetJsonPriceKey((string)productListDefaultUnit.UnitId))' data-product-retail-price='@(product.GetJsonRetailPrice())' data-product-unit-information='@JsonConvert.SerializeObject(unitInformation)'> <div itemscope itemtype="http://schema.org/Product" class="productlist-grid-product"> @{ var isNyhed = product.GetBoolean("Ecom:Product:Field.Nyhed.Value"); var isOutle = product.GetBoolean("Ecom:Product:Field.Outlet.Value"); } @RenderProductLabels(tilbud, productGridIsVolumenDiscount, discountedCompletely, discountedTemporary, isNyhed, isOutle) <a class="productlist-grid-image" href="@link" itemprop="url"> <img src="/Admin/Public/GetImage.ashx?Width=200&amp;Height=200&amp;Crop=5&amp;Compression=80&amp;Image=@Image" class="img-responsive" alt="@System.Web.HttpUtility.HtmlEncode(product.GetString("Ecom:Product.Name"))" itemprop="image" /> </a> <div class="productlist-grid-caption"> <a href="@link" class="productlist-grid-name" itemprop="name"> @System.Web.HttpUtility.HtmlEncode(product.GetString("Ecom:Product.Name")) </a> </div> <div class="offer" itemprop="offers" itemscope="" itemtype="http://schema.org/Offer"> @if (!isSubstituteProduct) { <div class="productlist-grid-info"> <span class="productlist-grid-number"> @Translate("Product Number", "Product Number") <span itemprop="sku">@product.GetString("Ecom:Product.Number")</span> </span> <span class="productlist-grid-stock"> @if (Pageview.User.LoggedIn) { <span class="async-price-stock" itemprop="availability"> <span class="spinner-sm-default"></span> </span> } else { @RenderStockInformations(product) } </span> </div> <div class="productlist-grid-footer"> <div class="productlist-grid-price-info"> <div class="productlist-grid-price js-price-container"> @if (Pageview.User.LoggedIn && !hidePrice) { <span class="async-price-unit"></span> <span class="productlist-grid-price-price async-price-total" itemprop="price"></span> } </div> </div> @if (ObjectFactory.GetInstance<NORRIQ.Common8.Context.AreaItemSettings>().GetCurrentAreaValue<string>("ProductlistGridHideButton") == "False") { <div class="productlist-grid-buying"> @if (product.GetLoop("VariantGroups").Any()) { <a href="@link" class="btn btn-buy"> <span class="product-added-text">@Translate("Buy", "Buy")</span> </a> } else { <form class="form" id="[email protected]("Ecom:Product.ID")" name="[email protected]("Ecom:Product.ID")" method="post" action="/Default.aspx?ID=@GetGlobalValue("Global:Page.ID")"> @* Because of DW and their use of Default units, we have to do this the manual way: http://doc.dynamicweb.com/documentation-8/ecommerce/product-catalog/products#sideNavTitle1-2-5-4 The ones commented out has been deemed not necessary. *@ @*@GetString("Ecom:Product.Form.Clean")*@ @*<input type="hidden" name="ProductURL" id="ProductURL" value="" />*@ <input type="hidden" name="CartCmd" value="add" /> <input type="hidden" name="ProductID" value="@(product.GetString("Ecom:Product.ID"))" /> <input type="hidden" name="VariantID" value="" /> @*<input type="hidden" name="UnitID" id="UnitID" value="STK" />*@ @*<input type="hidden" name="wishListID" id="wishListID" value="0" />*@ @{ } <ordering-list-request-product-condition product-key='@product.GetString("Ecom:Product.ID")' inline-template> <div class=""> <template v-if="loading"> <div class="loading"> <span class="spinner-sm-default"></span> </div> </template> <div v-show="!loading" class="input-group popover-trigger"> <input name="quantity" value="1" min="1" max="99999" type="number" class="form-control text-center" autocomplete="off" data-trigger="focus" data-rule-number="true" data-rule-min="1" :disabled="isRestricted && !isAvailable" /> <span class="input-group-btn"> <select name="UnitId" class="form-control form-unit unit-input JS-ASYNC-UNITSELECTOR JS-ASYNC-INPUT-VALUE" @(productListUnits.Count() <= 1 ? "readonly" : "")> @foreach (var unit in productListUnits) { <option value="@unit.UnitId" @(String.Equals(unit.UnitId, productListDefaultUnit.UnitId) ? "selected" : "")>@unit.UnitName</option> } </select> </span> </div> <div class="hide my-popover-content"> @RazorProductSupplementalPopup(unitInformation) </div> </div> </ordering-list-request-product-condition> @if (Pageview.User.LoggedIn) { @RenderBuyButton(product, "grid") } </form> } </div> } </div> } else { //if the product is a substitution product render this section instead. //This way to scope the feature is much easier to maintain changes in the future <div class="productlist-grid-info"> <span class="productlist-grid-number"> @Translate("Product Number", "Product Number") <span itemprop="sku">@product.GetString("Ecom:Product.Number")</span> </span> <span class="productlist-grid-stock"> @RenderStockInformations(product, true) </span> </div> <a class="btn btn-primary btn-block btn-air" href="@subStituteLink">@Translate("erstatningsvare")</a> } </div> @if (isLoggedIn && !product.GetLoop("VariantGroups").Any()) { <div class="productlist-grid-buttons"> @RenderFavoriteListIcon(product) </div> } </div> </div> </template> </product> } </template> } </slick> </section> } else { <div class="productlist-grid-flex"> @foreach (var product in relatedProductList) { <template> @using System.Globalization @using System.Web.Mvc.Html @using Dynamicweb.NewsLetterV3 @using NORRIQ.EcomMedia @using StandardWebshop.CustomCode.Razor @using NORRIQ.Common8.Razor; @using NORRIQ.Common8.Factory @using Newtonsoft.Json @using Dynamicweb.eCommerce.Common; @using Dynamicweb.eCommerce.Products @using StandardWebshop.CustomCode.SupplementalUnit @using StandardWebshop.CustomCode.ViewModels.Variants; @using StandardWebshop.CustomCode.Volumenpriser @using StandardWebshop.CustomCode.Units; @using StandardWebshop.CustomCode.Units.Models @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> @{ var currentUser = Dynamicweb.Modules.UserManagement.User.GetCurrentUser(); var hidePrice = false; if (currentUser != null) { hidePrice = currentUser.CustomFieldValues.FirstOrDefault(cf => cf.CustomField.SystemName == "AccessUser_HidePrices").Value.ToString().ToLower() == "true" ? true : false; } //this is required do to lazy loading //product.GetLoop("Units").Select(u => new //{ // UnitId = u.GetString("Ecom:VariantOption.ID"), // // Change the number format here: // UnitPriceDouble = (u.GetDouble("Ecom:VariantOption.Price.PricePIP") / 100d), // UnitName = u.GetString("Ecom:VariantOption.Name"), // UnitObj = u //}).OrderBy(x => x.UnitPriceDouble); var link = product.GetString("NIQ:ProductUrl"); var tilbud = product.GetBoolean("Ecom:Product:Field.Tilbud.Value"); var buy = "/default.aspx?ID=" + Navigation.GetPageIdByNavigationTag("ecom") + "&amp;productid=" + product.GetString("Ecom:Product.ID") + "&amp;cartcmd=add"; var area = GetGlobalValue("Global:Area.Lang"); var media = NORRIQ.EcomMedia.Frontend.GetProductMedia(product); var ProductSpecs = product.GetProductSpecifications(); var Image = ProductSpecs.GetAllByKey("Image").Any() ? "/Files/Images/XPI/" + ProductSpecs.GetByKey("Image").Value : media.GetFirstImage().Url; var isLoggedIn = Pageview.User.LoggedIn; var priceForGoogle = product.GetString("NIQ:PriceForGoogle"); var btn_addText = Translate("Add to cart", "Add to cart"); // Units var unitInformation = product.GetUnitInformation() as UnitInformationViewModel; var productListUnits = unitInformation.Units; var productListDefaultUnit = unitInformation.ProductDefaultUnit; //volumenPrices var productgridVolumenpriser = product.GetVolumenpriser(); bool discountedCompletely = product.GetBoolean("NIQ:Product.DiscontunedCompletely"); bool discountedTemporary = product.GetBoolean("NIQ:Product.DiscontunedTemporary"); bool isSubstituteProduct = discountedTemporary || discountedCompletely; string substituteProductID = product.GetString("NIQ:Product.SubstituteProductId"); string subStituteLink = string.Empty; if (isSubstituteProduct && substituteProductID != null) { subStituteLink = string.Format("/Default.aspx?ID={0}&productID={1}", NORRIQ.Common8.Razor.Navigation.GetPageIdByNavigationTag("ecom"), substituteProductID); } tilbud = tilbud || productListUnits.Any(x => x.IsInformativePrice); var productGridIsVolumenDiscount = productgridVolumenpriser.HasPrices() && productgridVolumenpriser.IsValid(); } @if (productListDefaultUnit != null) { <product product-key="@product.GetString("Ecom:Product.ID")" inline-template> <template> <div v-bind:class="{hide: hide, fadeout : fadeout}" class="product-wrapper @Columns @(!isSubstituteProduct ? "async-price " : "" ) js-favProduct" data-product-display="flex" data-product-key-clean='@(product.GetString("Ecom:Product.ID"))' data-product-key='@(product.GetJsonPriceKey((string)productListDefaultUnit.UnitId))' data-product-retail-price='@(product.GetJsonRetailPrice())' data-product-unit-information='@JsonConvert.SerializeObject(unitInformation)'> <div itemscope itemtype="http://schema.org/Product" class="productlist-grid-product"> @{ var isNyhed = product.GetBoolean("Ecom:Product:Field.Nyhed.Value"); var isOutle = product.GetBoolean("Ecom:Product:Field.Outlet.Value"); } @RenderProductLabels(tilbud, productGridIsVolumenDiscount, discountedCompletely, discountedTemporary, isNyhed, isOutle) <a class="productlist-grid-image" href="@link" itemprop="url"> <img src="/Admin/Public/GetImage.ashx?Width=200&amp;Height=200&amp;Crop=5&amp;Compression=80&amp;Image=@Image" class="img-responsive" alt="@System.Web.HttpUtility.HtmlEncode(product.GetString("Ecom:Product.Name"))" itemprop="image" /> </a> <div class="productlist-grid-caption"> <a href="@link" class="productlist-grid-name" itemprop="name"> @System.Web.HttpUtility.HtmlEncode(product.GetString("Ecom:Product.Name")) </a> </div> <div class="offer" itemprop="offers" itemscope="" itemtype="http://schema.org/Offer"> @if (!isSubstituteProduct) { <div class="productlist-grid-info"> <span class="productlist-grid-number"> @Translate("Product Number", "Product Number") <span itemprop="sku">@product.GetString("Ecom:Product.Number")</span> </span> <span class="productlist-grid-stock"> @if (Pageview.User.LoggedIn) { <span class="async-price-stock" itemprop="availability"> <span class="spinner-sm-default"></span> </span> } else { @RenderStockInformations(product) } </span> </div> <div class="productlist-grid-footer"> <div class="productlist-grid-price-info"> <div class="productlist-grid-price js-price-container"> @if (Pageview.User.LoggedIn && !hidePrice) { <span class="async-price-unit"></span> <span class="productlist-grid-price-price async-price-total" itemprop="price"></span> } </div> </div> @if (ObjectFactory.GetInstance<NORRIQ.Common8.Context.AreaItemSettings>().GetCurrentAreaValue<string>("ProductlistGridHideButton") == "False") { <div class="productlist-grid-buying"> @if (product.GetLoop("VariantGroups").Any()) { <a href="@link" class="btn btn-buy"> <span class="product-added-text">@Translate("Buy", "Buy")</span> </a> } else { <form class="form" id="[email protected]("Ecom:Product.ID")" name="[email protected]("Ecom:Product.ID")" method="post" action="/Default.aspx?ID=@GetGlobalValue("Global:Page.ID")"> @* Because of DW and their use of Default units, we have to do this the manual way: http://doc.dynamicweb.com/documentation-8/ecommerce/product-catalog/products#sideNavTitle1-2-5-4 The ones commented out has been deemed not necessary. *@ @*@GetString("Ecom:Product.Form.Clean")*@ @*<input type="hidden" name="ProductURL" id="ProductURL" value="" />*@ <input type="hidden" name="CartCmd" value="add" /> <input type="hidden" name="ProductID" value="@(product.GetString("Ecom:Product.ID"))" /> <input type="hidden" name="VariantID" value="" /> @*<input type="hidden" name="UnitID" id="UnitID" value="STK" />*@ @*<input type="hidden" name="wishListID" id="wishListID" value="0" />*@ @{ } <ordering-list-request-product-condition product-key='@product.GetString("Ecom:Product.ID")' inline-template> <div class=""> <template v-if="loading"> <div class="loading"> <span class="spinner-sm-default"></span> </div> </template> <div v-show="!loading" class="input-group popover-trigger"> <input name="quantity" value="1" min="1" max="99999" type="number" class="form-control text-center" autocomplete="off" data-trigger="focus" data-rule-number="true" data-rule-min="1" :disabled="isRestricted && !isAvailable" /> <span class="input-group-btn"> <select name="UnitId" class="form-control form-unit unit-input JS-ASYNC-UNITSELECTOR JS-ASYNC-INPUT-VALUE" @(productListUnits.Count() <= 1 ? "readonly" : "")> @foreach (var unit in productListUnits) { <option value="@unit.UnitId" @(String.Equals(unit.UnitId, productListDefaultUnit.UnitId) ? "selected" : "")>@unit.UnitName</option> } </select> </span> </div> <div class="hide my-popover-content"> @RazorProductSupplementalPopup(unitInformation) </div> </div> </ordering-list-request-product-condition> @if (Pageview.User.LoggedIn) { @RenderBuyButton(product, "grid") } </form> } </div> } </div> } else { //if the product is a substitution product render this section instead. //This way to scope the feature is much easier to maintain changes in the future <div class="productlist-grid-info"> <span class="productlist-grid-number"> @Translate("Product Number", "Product Number") <span itemprop="sku">@product.GetString("Ecom:Product.Number")</span> </span> <span class="productlist-grid-stock"> @RenderStockInformations(product, true) </span> </div> <a class="btn btn-primary btn-block btn-air" href="@subStituteLink">@Translate("erstatningsvare")</a> } </div> @if (isLoggedIn && !product.GetLoop("VariantGroups").Any()) { <div class="productlist-grid-buttons"> @RenderFavoriteListIcon(product) </div> } </div> </div> </template> </product> } </template> } </div> } } } } } </template> </div> </div> </div> </div> </div> </template> </product-page> <script append="true"> var getPrices = @(Pageview.User.LoggedIn ? 1 : 0); require(['jquery', 'lodash', 'standardwebshop/areas/ecom/product', 'jsrender'], function ($, _, product) { var units = @JsonConvert.SerializeObject(units); var productOptions = { containerScope: '.js-product-scope .async-price', getPrices: getPrices, asyncTemplate: $('#async-price'), unitCaptionMap: units, //get from template baseUnit: "@volumenpriser.BaseUnit", currencyCode: "@ProductCurrency", currentCulture: "@System.Globalization.CultureInfo.CurrentCulture.Name" }; product.init(productOptions); }); require(['standardwebshop/areas/ecom/product-list'], function (productList) { productList.init({ containerScope: '.product-related .async-price', asyncTemplate: $('#async-price'), productSort: $('#sortProducts'), getPrices: getPrices, unitContainerScope: '.product-related .JS-ASYNC-UNITSELECTOR', //unit-selector options baseUnit: "", // Get from data currencyCode: "@ProductCurrency", currentCulture: "@System.Globalization.CultureInfo.CurrentCulture.Name" }); }); </script>
Form is not valid - Please fill required fields. Error - contact administrator.