Exception in template (Designs\StandardWebshop\eCom/Productlist/ProductList.cshtml): System.ArgumentNullException: Value cannot be null.
Parameter name: source
at System.Linq.Enumerable.Contains[TSource](IEnumerable`1 source, TSource value, IEqualityComparer`1 comparer)
at Dynamicweb.Content.Caching.Storage.Contains(String key)
at Dynamicweb.eCommerce.Products.Group.get_CachedGroups()
at Dynamicweb.eCommerce.Products.Group.get_AllGroupsByLanguageID(String languageID)
at Dynamicweb.eCommerce.Products.Group.get_Subgroups()
at Dynamicweb.Frontend.NavigationProviders.GroupNavigationProvider._Closure$__20-0._Lambda$__0(GroupCollection items, Int32 thisLevel)
at Dynamicweb.Frontend.NavigationProviders.GroupNavigationProvider._Closure$__20-0._Lambda$__0(GroupCollection items, Int32 thisLevel)
at Dynamicweb.Frontend.NavigationProviders.GroupNavigationProvider._Closure$__20-0._Lambda$__0(GroupCollection items, Int32 thisLevel)
at Dynamicweb.Frontend.NavigationProviders.GroupNavigationProvider._Closure$__20-0._Lambda$__0(GroupCollection items, Int32 thisLevel)
at Dynamicweb.Frontend.NavigationProviders.GroupNavigationProvider.BuildGroupsProductCounts(GroupCollection topGroups, Int32 level, Int32 maxLevel)
at Dynamicweb.Frontend.NavigationProviders.GroupNavigationProvider.MakeGroupTree(Page page, NavigationItem parentNode, Boolean applyStartAndEndLevelToNavigation)
at Dynamicweb.Frontend.NavigationProviders.GroupNavigationProvider.Process(NavigationItem node, Boolean applyStartAndEndLevelToNavigation)
at Dynamicweb.Frontend.XmlNavigation.XML(Int32 ParentID, Int32 StartLevel, Int32 StopLevel, Expand expand, Int32 areaID)
at Dynamicweb.Frontend.XmlNavigation.GetNavigationHtml(Int32 ParentID, Int32 StartLevel, Int32 StopLevel, Expand ExpandMode, String NavigationName, String XsltPath, Int32 AreaID, Boolean SitemapMode, NameValueCollection settings, NameValueCollection attributes, IncludeMode mode)
at Dynamicweb.Frontend.XmlNavigation.GetNavigationHtml(NameValueCollection settings, NameValueCollection attributes)
at CompiledRazorTemplates.Dynamic.bfefdacfdbc.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()
@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 NLWI.Platforms.Dynamicweb8.Specs;
@using StandardWebshop.CustomCode.SupplementalUnit
@inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>>
@{
var Columns = "col-xs-6 col-sm-4 col-md-4";
var mode = ObjectFactory.GetInstance<TemporarilySettings>().GetAndUpdate("listmode") ?? "" + ObjectFactory.GetInstance<AreaItemSettings>().GetCurrentAreaValue<string>("ProductlistMode") + "";
var SortBy = GetString("Ecom:ProductList.SortBy");
var SortOrder = GetString("Ecom:ProductList.SortOrder");
var ProductCurrency = Context.Currency.Symbol;
var XPIData = ObjectFactory.GetInstance<NORRIQ.Common8.Context.AreaItemSettings>().GetCurrentAreaValue<string>("XPIData");
var query = HttpContext.Current.Request["EcomQuery"];
var AddNoIndex = !string.IsNullOrEmpty(HttpContext.Current.Request["PageNum"]);
var isFavoriteList = (System.Web.HttpContext.Current.Request["favoriteMode"] ?? string.Empty).Equals("true", StringComparison.InvariantCultureIgnoreCase);
}
@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 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 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>
}
@if (AddNoIndex)
{
@SnippetStart("AddNoIndex")
<meta name="robots" content="noindex" />
@SnippetEnd("AddNoIndex")
}
<aside class="col-xs-12 col-sm-12 col-md-3" data-content="sidebar" id="desktopSidebar">
@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;
@inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>>
<div class="panel-group" id="filterTabs" role="tablist" aria-multiselectable="true">
<ul class="filter-tabs">
@if (HttpContext.Current.Request["groupid"] != null || GetGlobalValue("Global:Page.NavigationTag").Contains("ecom"))
{
<li class="filter-tabs-item" role="tab" id="headingSubmenu">
<a class="collapsed"
role="button"
data-toggle="collapse"
data-parent="#filterTabs"
data-target="#collapseSubmenu"
aria-expanded="false"
aria-controls="collapseSubmenu">
<i class="icon-hamburger" aria-hidden="true"></i>
@Translate("Categories", "Categories")
</a>
</li>
}
@if (GetLoop("FacetGroups").Any())
{
<li class="filter-tabs-item" role="tab" id="headingFilter">
<a class="collapsed"
role="button"
data-toggle="collapse"
data-parent="#filterTabs"
data-target="#collapseFilter"
aria-expanded="false"
aria-controls="collapseFilter">
@*<i class="icon-filter" aria-hidden="true"></i>*@
<i class="pe-is-i-sliders-circle"></i>
@Translate("Filter", "Filter")
</a>
</li>
}
</ul>
<div class="clearfix"></div>
@if (HttpContext.Current.Request["groupid"] != null || GetGlobalValue("Global:Page.NavigationTag").Contains("ecom"))
{
<div class="panel">
<div id="collapseSubmenu"
class="filter-collapse collapse"
role="tabpanel"
aria-labelledby="headingSubmenu">
@if (HttpContext.Current.Request["groupid"] != null)
{
@RenderNavigation(new { Template = "submenu-ecom-inpath.xslt", Expandmode = "all", StartLevel = 1, EndLevel = 2 })
}
else
{
@RenderNavigation(new { Template = "submenu-ecom.xslt", Expandmode = "all", StartLevel = 1, EndLevel = 3 })
}
</div>
</div>
}
@if (GetLoop("FacetGroups").Any())
{
<div class="container filter-wrap">
<nav id="collapseFilter" class="filter-collapse collapse center_header-navigation" role="tabpanel" aria-labelledby="headingFilter">
<h2>@Translate("Filter", "Filter")</h2>
<button type="button" aria-label="Close Navigation" class="btn-close" aria-controls="collapseFilter" data-toggle="collapse" data-target="#collapseFilter">
<span> </span>
<span> </span>
</button>
</nav>
</div>
<div class="panel">
<div id="collapseFilterXX"
class="filter-collapse collapse center_header-navigation"
role="tabpanel"
aria-labelledby="headingFilter">
@*<form id="filter-form" method="get" action="/Default.aspx">
<input type='hidden' name='ID' value='@Pageview.Page.ID' />
@if (HttpContext.Current.Request["ecomquery"] != null)
{
<input type="hidden" name="ecomquery" value="@HttpContext.Current.Request["ecomquery"]" />
}
@foreach (LoopItem groups in GetLoop("FacetGroups"))
{
if (groups.GetLoop("Facets").Any())
{
foreach (LoopItem facets in groups.GetLoop("Facets"))
{
if (facets.GetLoop("FacetOptions").Any())
{
<div class="filter-group" id="@facets.GetString("Facet.QueryParameter")" name="@facets.GetString("Facet.QueryParameter")" data-filter-type="option">
<div class="filter-group-header">
<i class="icon-spinner icon-pulse" aria-hidden="true" style="display: none;"></i> @facets.GetString("Facet.Name")
</div>
<ul class="filter-group-list">
@foreach (LoopItem option in facets.GetLoop("FacetOptions"))
{
<li class="filter-group-item">
<div class="checkbox">
<label>
<input type="checkbox"
id="@facets.GetString("Facet.QueryParameter")@option.GetString("FacetOptions.LoopCounter")"
name="@facets.GetString("Facet.QueryParameter")"
value="@option.GetString("FacetOption.Value")"
@(option.GetBoolean("FacetOption.Selected") ? " checked=\"checked\" " : "") />
@option.GetString("FacetOption.Label") (@option.GetString("FacetOption.Count"))
</label>
</div>
</li>
}
</ul>
</div>
}
}
}
}
</form>
<script append="true">
require(['jquery', 'shared/norriq.searchfilter/norriq.searchfilter'], function ($, Filter) {
var filter = new Filter();
filter.init({
$filterForm: $('#filter-form'),
$filterGroups: $('.filter-group, .js-select-filter'),
$filterSlider: $('.filter-slider'),
$selectedFilters: $('.filter-active-option')
});
});
</script>*@
</div>
</div>
}
</div>
</aside>
<product-list inline-template>
<div class="col-xs-12 col-sm-12 col-md-9 js-product-list">
@*<ordering-list-selector>
</ordering-list-selector>*@
@using NORRIQ.Common8.Razor
@using NORRIQ.Universal.Extensions
@inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>>
@{
var PageID = (String.IsNullOrEmpty(GetString("Ecom:ProductList:Page.ID")) ? "" : "/Default.aspx?ID=" + GetString("Ecom:ProductList:Page.ID"));
var GroupID = (String.IsNullOrEmpty(GetString("Ecom:ProductList:Page.GroupID")) ? "" : "&GroupID=" + GetString("Ecom:ProductList:Page.GroupID"));
var pdfgroupid = System.Web.HttpContext.Current.Request.QueryString["groupid"];
var pdfgroupname = GetString("Ecom:Group.Name");
var pdfLink = "";
var pageURL = System.Web.HttpContext.Current.Request.Url.PathAndQuery.ToString().Split('&').Last();
var navigationTag = GetGlobalValue("Global:Page.NavigationTag");
var pageQuery = System.Web.HttpContext.Current.Request.Url.Query.ToString();
var originalPageQuery = pageQuery.ToString();
if (pageQuery.IndexOf("&") > -1)
{
pageQuery = "?" + pageQuery.Substring(pageQuery.IndexOf("&") + 1, pageQuery.Length - pageQuery.IndexOf("&") - 1);
}
else
{
pageQuery = "?";
}
}
@if (!String.IsNullOrEmpty(pdfgroupid))
{
pdfLink = Navigation.GetUrlByNavigationTag("productlistsheet") + "?GroupID=" + pdfgroupid + "&PDF=true&Filename=" + pdfgroupid + ".pdf";
}
else if (String.IsNullOrEmpty(pdfgroupid) && isFavoriteList && pageQuery.Contains("favoritelistid"))
{
pdfLink = Navigation.GetUrlByNavigationTag("favoritelist-customerprintlist") + pageQuery + "&PDF=true&Filename=" + Translate("Favoritliste", "Favoritliste") + ".pdf";
}
else if (String.IsNullOrEmpty(pdfgroupid) && isFavoriteList && pageQuery.Contains("orderinglistid"))
{
pdfLink = Navigation.GetUrlByNavigationTag("orderinglist-customerprintlist") + pageQuery + "&PDF=true&Filename=" + Translate("Favoritliste", "Favoritliste") + ".pdf";
}
else if (String.IsNullOrEmpty(pdfgroupid) && isFavoriteList)
{
pdfLink = Navigation.GetUrlByNavigationTag("sortiment-customerprintlist") + pageQuery + (pageQuery.IndexOf("?") > -1 ? "&" : "") + "PDF=true&Filename=" + Translate("Favoritliste", "Favoritliste") + ".pdf";
}
else if (String.IsNullOrEmpty(pdfgroupid) && pageURL.Contains("reorder"))
{
pdfLink = Navigation.GetUrlByNavigationTag("customerprintlist") + "?" + "&PDF=true&Filename=" + Translate("Genbestillingsliste", "Genbestillingsliste") + ".pdf";
}
<header class="productlist-header clearfix">
<div class="row">
<div class="@(isFavoriteList ? "col-sm-8" : "col-sm-10")">
@if (!isFavoriteList)
{
<h1 class="title-styled">
@if (!String.IsNullOrEmpty(GetString("Ecom:Group.Name")))
{
@GetString("Ecom:Group.Name")
}
else
{
@GetGlobalValue("Global:Page.Name")
}
@if (!String.IsNullOrEmpty(GetString("Ecom:ProductList:Search.Query")))
{
<small>
(@GetString("Ecom:ProductList:Search.Query"))
</small>
}
</h1>
}
</div>
<div class="@(isFavoriteList ? "col-sm-4" : "col-sm-2") text-right print-links">
@if (!String.IsNullOrEmpty(pdfgroupid) || !String.IsNullOrEmpty(pageURL))
{
if (isFavoriteList)
{
<div class="reinvoice-wrap">
@*@using NORRIQ.Common8.Factory
@using StandardWebshop.CustomCode.Basket.Services
@inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>>
@{
//bool reinvoiceExceptions = false;
//bool reInvoiceStatus = false;
//try
//{
// reInvoiceStatus = ObjectFactory.GetInstance<BasketService>().GetReInvoiceStatus();
//}
//catch (Exception e)
//{
// // ignored
// reinvoiceExceptions = true;
//}
}
<div id="re-invoice-container">
<div class="form-group">
<div class="checkbox">
<span style="display: none" class="js-re-invoice-loading spinner-sm-default"></span>
<label for="re-invoice-enabled">
<input id="re-invoice-checkbox" type="checkbox" data-target="reinvoice-form-field" /> @Translate("Enable_reinvoicing", "Viderefakturering")
<i class="pe-is-i-info-circle-f pe-lg text-primary" aria-hidden="true" title="@Translate("reinvoicing_explained", "Her har du mulighed for at vælge, at din ordre skal viderefaktureres.")"></i>
</label>
</div>
<div style="display: none;" class="js-re-invoice-error">
<div class="alert alert-warning-light text-center" role="alert">
<span class="error">
@Translate("reinvoice_error-info", "Status på viderefakturering kan ikke vises.")<br />
<small>@Translate("reinvoice_error-hint", "Prøv evt. at genindlæse siden.")</small>
</span>
</div>
</div>
</div>
</div>
*@
</div>
<a rel="nofollow" class="hidden-print pull-right" href="@pdfLink">
@Translate("DownloadFavlist", "Download favoritliste") <img src="/Files/Templates/Designs/StandardWebshop/css/file-pdf-solid.svg" style="width: 23px; padding-left: 3px;" />
</a>
}
else
{
<a rel="nofollow" class="hidden-print pull-right hidden-xs" href="javascript:window.print();">
<i class="fas fa-file-pdf"></i>
@Translate("Print", "Print")
</a>
}
}
</div>
</div>
@if (!String.IsNullOrWhiteSpace(GetString("Ecom:Group.LargeImage")))
{
<div class="productlist-header-image hidden-xs">
<img src="/Admin/Public/GetImage.ashx?Width=1140&Height=480&Compression=80&[email protected](GetString("Ecom:Group.LargeImage"))" />
</div>
}
@if (!String.IsNullOrEmpty(GetString("Ecom:Group.Description")))
{
<div class="productlist-description hidden-xs">
@GetString("Ecom:Group.Description")
</div>
}
@if (isFavoriteList)
{
<div class="mBot"></div>
}
@*
If active shows featured products before produclist
@RenderSnippet("FeaturedProduct")
*@
@if (GetLoop("Products").Any())
{
<text>@foreach (LoopItem groups in GetLoop("FacetGroups"))
{
if (groups.GetLoop("Facets").Any())
{
if (groups.GetLoop("Facets").Where(fo => fo.GetLoop("FacetOptions").Where(op => op.GetBoolean("FacetOption.Selected")).Any()).Any())
{
<div class="facets-selected">
<div class="facets-col-center">
<span>@Translate("selected_filters", "Valgte filtre:") </span>
@foreach (LoopItem selected in groups.GetLoop("Facets"))
{
foreach (LoopItem active in selected.GetLoop("FacetOptions"))
{
if (active.GetBoolean("FacetOption.Selected"))
{
<a href="javascript:void(0)" class="filter-active-option" data-filter-name="@selected.GetString("Facet.Name")" data-filter-type="option" data-filter-option="@selected.GetString("Facet.QueryParameter")@active.GetString("FacetOptions.LoopCounter")">
<span class="option-label">@selected.GetString("Facet.Name"):</span>
@if (active.GetString("FacetOption.Label").EndsWith(".jpg"))
{
var maerkeUrl = "/Files/Images/Symbol/" + active.GetString("FacetOption.Label");
var maerkeAlt = active.GetString("FacetOption.Label");
maerkeAlt = maerkeAlt.Substring(0, maerkeAlt.LastIndexOf(".jpg"));
@*<img src="@maerkeUrl" alt="@maerkeAlt" class="img-responsive" />*@
<span>@maerkeAlt</span>
}
else
{
<span class="option-title">@active.GetString("FacetOption.Label")</span>
}
<i class="pe-is-i-close-circle-f pe-va" aria-hidden="true"></i>@*was icon-close*@
</a>
}
}
}
@if (groups.GetLoop("Facets").Where(fo => fo.GetLoop("FacetOptions").Where(op => op.GetBoolean("FacetOption.Selected")).Any()).Any())
{
<a class="filter-active-option filter-reset" role="button" href="javascript:void(0)" data-filter-type="reset">
<span>@Translate("Clear filter", "Nulstil filtre")</span>
<i class="pe-is-bt-backspace-f pe-va pe-lg" aria-hidden="true"></i>@*was icon-close*@
</a>
}
</div>
</div>
}
}
}</text>
<text>@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 StandardWebshop.CustomCode.ColorLookup
@inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>>
@{
bool facetsAnySelected = false;
}
@if (GetLoop("FacetGroups").Any())
{
var colorLookupService = ObjectFactory.GetInstance<ColorLookupService>();
<div id="filter-container" class="productlist-filter">
<form id="filter-form" method="get" action="/Default.aspx">
<input type='hidden' name='ID' value='@Pageview.Page.ID' />
@if (!String.IsNullOrEmpty(GetString("Ecom:ProductList:Page.GroupID")))
{
<input type='hidden' name='GroupID' value='@GetString("Ecom:ProductList:Page.GroupID")' />
}
@if (HttpContext.Current.Request["ecomquery"] != null)
{
<input type="hidden" name="ecomquery" value="@HttpContext.Current.Request["ecomquery"]" />
}
@foreach (LoopItem groups in GetLoop("FacetGroups"))
{
if (groups.GetLoop("Facets").Any())
{
if (!facetsAnySelected)
{
facetsAnySelected = groups.GetLoop("Facets").Where(fo => fo.GetLoop("FacetOptions").Where(op => op.GetBoolean("FacetOption.Selected")).Any()).Any();
}
<ul class="nav nav-pills nav-filter">
@foreach (LoopItem facets in groups.GetLoop("Facets"))
{
if (facets.GetLoop("FacetOptions").Any())
{
var anySelected = facets.GetLoop("FacetOptions").Any(options => options.GetBoolean("FacetOption.Selected"));
//DON't make this general - use brackets only if needed for each node instead.
//var useBrackets = facets.GetLoop("FacetOptions").Where(o => o.GetString("FacetOption.Value").IndexOf(',') > -1).Any();
<li class="dropdown @(anySelected ? "active" : string.Empty)" id="@facets.GetString("Facet.QueryParameter")" role="presentation">
<a role="button" href="javascript:void()" class="dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="icon-spinner icon-pulse" aria-hidden="true" style="display: none;"></i> @facets.GetString("Facet.Name") <i class="icon-angle-down" aria-hidden="true"></i>
</a>
<div class="dropdown-menu dropdown-keep-open filla" aria-labelledby="@facets.GetString("Facet.QueryParameter")">
<nav id="" class="filter-collapse collapse mobile-only" role="tabpanel">
<h2>@facets.GetString("Facet.Name")</h2>
<div class="btn-close-filla">
<button type="button" class="btn-close" data-toggle="collapse">
<i class="pe-is-i-angle-left pe-3x" aria-hidden="true"></i>
</button>
</div>
</nav>
<div class="dropdown-inner">
@foreach (LoopItem option in facets.GetLoop("FacetOptions"))
{
string facetLabel = option.GetString("FacetOption.Label");
bool useBrackets = (option.GetString("FacetOption.Value").IndexOf(',') > -1);
if (facets.GetString("Facet.QueryParameter") == "Farve")
{
string colorKey = colorLookupService.GetColorKey(option.GetString("FacetOption.Value"));
<div class="checkbox-color">
<input type="checkbox"
id="@facets.GetString("Facet.QueryParameter")@option.GetString("FacetOptions.LoopCounter")"
name="@facets.GetString("Facet.QueryParameter")"
value="@(useBrackets ? "[" + option.GetString("FacetOption.Value") + "]" : option.GetString("FacetOption.Value"))"
@(option.GetBoolean("FacetOption.Selected") ? " checked=\"checked\" " : "") />
<label for="@facets.GetString("Facet.QueryParameter")@option.GetString("FacetOptions.LoopCounter")">
<span class="checkbox-color-parameter checkbox-color-@(useBrackets ? "[" + colorKey + "]" : colorKey)"></span>
<span class="checkbox-color-name">@option.GetString("FacetOption.Label")</span> <span class="cnt">(@option.GetString("FacetOption.Count"))</span>
</label>
</div>
}
else
{
<div class="checkbox">
<label for="@facets.GetString("Facet.QueryParameter")@option.GetString("FacetOptions.LoopCounter")">
<input type="checkbox"
id="@facets.GetString("Facet.QueryParameter")@option.GetString("FacetOptions.LoopCounter")"
name="@facets.GetString("Facet.QueryParameter")"
value="@(useBrackets ? "[" + option.GetString("FacetOption.Value") + "]" : option.GetString("FacetOption.Value"))"
@(option.GetBoolean("FacetOption.Selected") ? " checked=\"checked\" " : "") />
@{
bool isImage = SpecificationHelper.IsImageFile(facetLabel);
string facetLabelImageTxt = facetLabel.Split('.').FirstOrDefault();
//TODO: mso BAD implementation - should be removed later
Guid tmpGuid;
bool isGUID = !string.IsNullOrEmpty("facetLabelImageTxt") && Guid.TryParse(facetLabelImageTxt, out tmpGuid);
}
@if (isImage && isGUID)
{
//TODO: mso - after PIM data is structured
<img src="/Admin/Public/GetImage.ashx?Width=60&Height=60&Compression=80&Crop=5&Image=/Files/Images/XPI/@facetLabel" alt="@facetLabel" class="img-responsive" />
}
else if (!isGUID && isImage)
{
//TODO: mso BAD implementation.
//This should be cleaned up in the future
var maerkeUrl = "/Files/Images/Symbol/" + option.GetString("FacetOption.Label");
string maerkeAlt = facetLabel.Substring(0, facetLabel.LastIndexOf(".jpg"));
<text>
<img src="/Admin/Public/GetImage.ashx?Width=125&Height=125&Compression=80&Image=@maerkeUrl" alt="@maerkeAlt" class="img-responsive miniThumb" />
@Translate("specs_" + maerkeAlt, maerkeAlt) <span class="cnt">(@option.GetString("FacetOption.Count"))</span>
</text>
}
else
{
<text>
@facetLabel <span class="cnt">(@option.GetString("FacetOption.Count"))</span>
</text>
}
</label>
</div>
}
}
</div>
<div class="btn-wrap">
<button class="btn btn-action btn-block btn-raised">
@Translate("Anvend", "Anvend")
</button>
</div>
</div>
</li>
}
}
@*@if (groups.GetLoop("Facets").Where(fo => fo.GetLoop("FacetOptions").Where(op => op.GetBoolean("FacetOption.Selected")).Any()).Any())
{
<li class="dropdown show-mobile" role="presentation">
<a class="dropdown-toggle filter-active-option filter-reset" role="button" href="javascript:void(0)" data-filter-type="reset">
@Translate("Clear filter", "Nulstil filtre") <i class="pe-is-bt-backspace-f pe-va pe-lg" aria-hidden="true"></i>
</a>
</li>
}*@
</ul>
}
}
<div class="clearfix"></div>
<br/>
<br/>
<div class="btn-wrap mobile-only">
<button class="btn btn-action btn-block btn-raised" type="submit">
@Translate("Anvend", "Anvend")
</button>
</div>
@if (facetsAnySelected)
{
<br/>
<div class="btn-wrap mobile-only">
<button class="btn btn-default btn-block filter-active-option-reset" role="button" data-filter-type="reset">
@Translate("Clear filter", "Nulstil filtre")
</button>
</div>
}
</form>
</div>
<script append="true">
require(['jquery', 'shared/norriq.searchfilter/norriq.searchfilter'], function ($, Filter) {
var filter = new Filter();
filter.init({
$filterForm: $('#filter-form'),
$filterGroups: $('.filter-group, .js-select-filter'),
$filterSlider: $('.filter-slider'),
$selectedFilters: $('.filter-active-option, .filter-active-option-reset')
});
});
</script>
}</text>
<div class="row">
<div class="col-xs-12">
<div class="stroked"></div>
</div>
<div class="col-xs-12 col-sm-6 col-sm-offset-3 text-center">
<div class="productlist-header-info">
<span class="productlist-header-quantity">
@GetString("Ecom:ProductList.PageProdCnt") @Translate("Products", "Products")
</span>
<span class="productlist-header-vat">
@Translate("Prices without VAT", "Prices without VAT")
</span>
</div>
</div>
<div class="col-xs-12 col-sm-3" data-align="right">
@if (isFavoriteList)
{
<div class="form-inline form-sort" data-float="right">
@*<label for="sortProducts">
@Translate("label_sort_products", "Sorter")
</label>*@
<select class="form-control form-control-sort" id="sortProducts">
<option value="@(HttpContext.Current.Request.Url.SetQuery("SortBy", "ProductNameSort").SetQuery("SortOrder", "ASC").PathAndQuery)"
@((SortOrder == "ASC" && SortBy == "productnamesort") ? "selected" : "")>
@Translate("Name ascending", "Name A to Z")
</option>
<option value="@(HttpContext.Current.Request.Url.SetQuery("SortBy", "ProductNameSort").SetQuery("SortOrder", "DESC").PathAndQuery)"
@(SortOrder == "DESC" && SortBy == "productnamesort" ? "selected" : "")>
@Translate("Name descending", "Name Z to A")
</option>
<option value="@(HttpContext.Current.Request.Url.SetQuery("SortBy", "Varegruppe").SetQuery("SortOrder", "ASC").PathAndQuery)"
@(SortOrder == "ASC" && SortBy == "varegruppe" ? "selected" : "")>
@Translate("Varegruppe ascending", "Varegruppe A to Z")
</option>
<option value="@(HttpContext.Current.Request.Url.SetQuery("SortBy", "Varegruppe").SetQuery("SortOrder", "DESC").PathAndQuery)"
@(SortOrder == "DESC" && SortBy == "varegruppe" ? "selected" : "")>
@Translate("Varegruppe descending", "Varegruppe Z to A")
</option>
<option value="@(HttpContext.Current.Request.Url.SetQuery("SortBy", "Price").SetQuery("SortOrder", "ASC").PathAndQuery)"
@(SortOrder == "ASC" && SortBy == "price" ? "selected" : "")>
@Translate("Vejl. Pris ascending", "Vejl. Pris Stigende")
</option>
<option value="@(HttpContext.Current.Request.Url.SetQuery("SortBy", "Price").SetQuery("SortOrder", "DESC").PathAndQuery)"
@(SortOrder == "DESC" && SortBy == "price" ? "selected" : "")>
@Translate("Vejl. Pris descending", "Vejl. Pris Faldende")
</option>
</select>
</div>
}
else
{
<div class="btn-group views" role="group" aria-label="Toggle view">
<a class="btn @(mode == "table" ? "btn-grid active" : "btn-grid")"
href="@(HttpContext.Current.Request.Url.SetQuery("listmode", "table").PathAndQuery)">
<i class="icon-list" aria-hidden="true"></i> <span class="sr-only">@Translate("Table", "Tabel")</span>
</a>
<a class="btn @(mode == "grid" ? "btn-grid active" : "btn-grid")"
href="@(HttpContext.Current.Request.Url.SetQuery("listmode", "grid").PathAndQuery)">
<i class="icon-grid" aria-hidden="true"></i> <span class="sr-only">@Translate("Grid", "Grid")</span>
</a>
</div>
}
</div>
</div>
}
</header>
<div v-show="loading">
<div class="loading">
<span class="spinner-xl-default"></span>
</div>
</div>
<div v-show="!loading">
<section>
@if (GetLoop("Products").Any())
{
if (mode == "grid")
{
<div class="productlist-grid-flex">
@foreach (var product in GetLoop("Products"))
{
<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") + "&productid=" + product.GetString("Ecom:Product.ID") + "&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&Height=200&Crop=5&Compression=80&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>
}
else if(!hidePrice)
{
<span class="product-price-before">@(productListDefaultUnit.IsInformativePrice ? productListDefaultUnit.UnitBeforePrice : string.Empty)</span>
<span class="productlist-grid-price-price @(productListDefaultUnit.IsInformativePrice ? "font-hilite" : string.Empty)" itemprop="price" content="@priceForGoogle">
@productListDefaultUnit.UnitPrice
<span itemprop="priceCurrency" content="@ProductCurrency">@ProductCurrency</span>
</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>
@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>
}
else
{
var productsBinding = GetLoop("Products");
var tableModeBinding = "default";
<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&Height=400&Crop=5&Compression=80&Image=@Image" />
</div>
}
else
{
//default
<img src="/Admin/Public/GetImage.ashx?Width=40&Height=35&Crop=5&Compression=85&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" />*@
@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>
}
<text>@{
// Pagination
var paginationCurrentPage = GetInteger("Ecom:ProductList.CurrentPage");
var paginationTotalPages = GetInteger("Ecom:ProductList.TotalPages");
var prev = GetString("Ecom:ProductList.PrevPage.Clean");
var next = GetString("Ecom:ProductList.NextPage.Clean");
string pageCountText = Translate("Viser side") + " " + GetValue("Ecom:ProductList.CurrentPage") + " " + Translate("af") + " " + GetValue("Ecom:ProductList.TotalPages") + " (" + GetValue("Ecom:ProductList.PageProdCnt") + " " + Translate("varer") + ")";
}
@if (paginationTotalPages > 1)
{
<nav class="productlist-pagination">
<ul class="pagination">
<li class="@(paginationCurrentPage > 1 ? "" : "disabled")">
<a href="@(paginationCurrentPage > 1 ? prev : "javascript:void()")" aria-label="Previous">
<i aria-hidden="true" class="icon-chevron-left"></i>
</a>
</li>
@foreach (var pagination in GetLoop("Ecom:ProductList.Pages5"))
{
<li class="@(pagination.GetBoolean("Ecom:ProductList.Pages5.Page.IsCurrent") ? "active" : "")">
<a href="@(pagination.GetString("Ecom:ProductList.Pages5.Page.UrlHtmlEncoded"))">
@pagination.GetString("Ecom:ProductList.Pages5.Page.Number")
</a>
</li>
}
<li class="@(paginationTotalPages > paginationCurrentPage ? "" : "disabled")">
<a href="@(paginationTotalPages > paginationCurrentPage ? next : "javascript:void()")" aria-label="Next">
<i aria-hidden="true" class="icon-chevron-right"></i>
</a>
</li>
</ul>
<div class="pagecountinfo"><p>@pageCountText</p></div>
</nav>
}
@*@if (paginationTotalPages > 1)
{
<nav class="productlist-pagination">
<ul class="pagination">
<li class="pagitext">@Translate("Viser side")</li>
<li class="@(paginationCurrentPage > 1 ? "" : "disabled")">
<a href="@(paginationCurrentPage > 1 ? prev : "javascript:void()")" aria-label="Previous">
<i aria-hidden="true" class="icon-chevron-left"></i>
</a>
</li>
@foreach (var pagination in GetLoop("Ecom:ProductList.Pages5"))
{
<li class="@(pagination.GetBoolean("Ecom:ProductList.Pages5.Page.IsCurrent") ? "active" : "")">
<a href="@(pagination.GetString("Ecom:ProductList.Pages5.Page.UrlHtmlEncoded"))">
@pagination.GetString("Ecom:ProductList.Pages5.Page.Number")
</a>
</li>
}
<li class="@(paginationTotalPages > paginationCurrentPage ? "" : "disabled")">
<a href="@(paginationTotalPages > paginationCurrentPage ? next : "javascript:void()")" aria-label="Next">
<i aria-hidden="true" class="icon-chevron-right"></i>
</a>
</li>
<li class="pagitext">@Translate("af") @GetString("Ecom:ProductList.TotalPages")</li>
</ul>
</nav>
}*@
@if (!String.IsNullOrEmpty(GetString("Ecom:Group.Description")))
{
<div class="productlist-description visible-xs">
@GetString("Ecom:Group.Description")
</div>
}</text>
}
</section>
</div>
</div>
</product-list>
<script append="true">
require(['standardwebshop/areas/ecom/product-list'], function (productList) {
var getPrices = @(Pageview.User.LoggedIn ? 1 : 0);
productList.init({
containerScope: '.js-product-list .async-price',
asyncTemplate: $('#async-price'),
productSort: $('#sortProducts'),
getPrices: getPrices,
//unit-selector options
baseUnit: "", // Get from data
currencyCode: "@ProductCurrency",
currentCulture: "@System.Globalization.CultureInfo.CurrentCulture.Name"
});
});
var useQuery = @(!string.IsNullOrEmpty(query) ? 1 : 0);
if (useQuery) {
var results = @GetLoop("Products").Count;
var postfix = results > 0 ? "ProductsFound" : "Empty";
var category = "EcomSearch - " + postfix;
// Datalayer originates from GTM
if (typeof variable !== 'undefined') {
dataLayer.push({
'event': 'EcomSearch',
'eventCategory': category,
'eventAction': '@query',
'eventLabel': results
});
}
}
</script>