Trustpilot

ORDERS PLACED BEFORE 1PM WILL BE SHIPPED SAME WORKING DAY

EXCELLENT CUSTOMER SERVICE

ORDERS PLACED BEFORE 1PM WILL BE SHIPPED SAME WORKING DAY

14 DAYS RETURN POLICY

Exception in template (Designs\OutletCamping\eCom/Productlist/ProductListFacets.cshtml): System.NullReferenceException: Object reference not set to an instance of an object.
   at CompiledRazorTemplates.Dynamic.adacfcf.Execute()
   at RazorEngine.Templating.TemplateBase.RazorEngine.Templating.ITemplate.Run(ExecuteContext context) in c:\Users\abbottm\Documents\GitHub\RazorEngine\src\Core\RazorEngine.Core\Templating\TemplateBase.cs:line 126
   at RazorEngine.Templating.TemplateService.Run(ITemplate template, DynamicViewBag viewBag) in c:\Users\abbottm\Documents\GitHub\RazorEngine\src\Core\RazorEngine.Core\Templating\TemplateService.cs:line 608
   at RazorEngine.Templating.TemplateService.Parse(String razorTemplate, Object model, DynamicViewBag viewBag, String cacheName) in c:\Users\abbottm\Documents\GitHub\RazorEngine\src\Core\RazorEngine.Core\Templating\TemplateService.cs:line 439
   at RazorEngine.Razor.Parse[T](String razorTemplate, T model, DynamicViewBag viewBag, String cacheName) in c:\Users\abbottm\Documents\GitHub\RazorEngine\src\Core\RazorEngine.Core\Razor.cs:line 290
   at Dynamicweb.Rendering.Template.RenderRazorTemplate()
@using System @using System.Collections.Generic @using System.Globalization @using System.Linq @using System.Web @using Dynamicweb.Data; @using Dynamicweb.Extensibility @using Dynamicweb.Frontend @using Dynamicweb.Ecommerce.Products @using Dynamicweb.Indexing.Querying @using OaseOutdoors.Components.Shared.Modules.Ecom.ModelBuilders @using OaseOutdoors.Components.Shared.Modules.Ecom.Models @using OaseOutdoors.Services.EcomUrlService.Initialization @using OaseOutdoors.Services.UrlParserService.Initialization @using OaseOutdoors.Services.FacetService.Models @using OaseOutdoors.Services.GroupService.Initialization @using OaseOutdoors.Services.ImageService.Enums @using OaseOutdoors.Services.ImageService.Initialization @using OaseOutdoors.Services.ProductResourceService.Enums @using OaseOutdoors.Services.ProductResourceService.Initialization @using OaseOutdoors.Services.ProductService.Initialization @using OaseOutdoors.Services.StaticResourceService.Initialization @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> @{ var staticResourceService = ServiceLocator.Current.GetStaticResourceService(); var area = PageView.Current().Area; var areas = Dynamicweb.Services.Areas.GetAreas().Where(x => x.Active && x.Item["ShopPublished"] != null && (bool)x.Item["ShopPublished"] && x.Name.ToLower().Contains(area.Name.Split(':')[0].Trim().ToLower())).ToList(); string groupId = GetString("Ecom:Group.ID"); var group = Group.GetGroupById(groupId); var productViewModelService = new ProductViewModelBuilder(); var groupViewModelService = new GroupViewModelBuilder(); if (group.ShopId != Pageview.Area.EcomShopId) { var groupContext = HttpContext.Current; groupContext.Response.RedirectPermanent(new Uri(groupContext.Request.Url.Scheme + "://" + groupContext.Request.Url.Host + groupContext.Request.RawUrl).GetLeftPart(UriPartial.Path) + "-404", true); } var groupService = ServiceLocator.Current.GetGroupService(); var groupViewModel = groupViewModelService.GetViewModel(group); var beginSection = "<div class=\"container\"><section class=\"product-container\">"; var endSection = "</section></div>"; var urlService = ServiceLocator.Current.GetEcomUrlService(); var urlParserService = ServiceLocator.Current.GetUrlParserService(); var valutaSelector = HttpContext.Current.Request.Cookies["currencySelector"]; GroupCollection subGroups = null; if (group != null && group.HasChildGroups && group.Subgroups.Count > 1) { subGroups = group.Subgroups; } else if (group != null) { subGroups = group.ParentGroups.FirstOrDefault().Subgroups; } int breadCrumbTotal = groupViewModel.Breadcrumb.Count; int breadCrumbIndex = 1; var queryService = ServiceLocator.Current.GetInstance<IQueryService>(); var query = queryService.LoadQuery("Products", "ProductsSortAndFilter" + ".query"); var productService = ServiceLocator.Current.GetProductService(); var parameters = new Dictionary<string, object> { { "groupId", groupId } }; ////Price var heighestPriceProduct = productService.GetHighestOrLowest(query, parameters, Dynamicweb.Indexing.Querying.Sorting.SortDirection.Descending, "Price"); double heighestPrice = 0.0; var currencySymbol = ""; if (heighestPriceProduct != null) { heighestPrice = Math.Ceiling(heighestPriceProduct.Price.PriceWithVAT); currencySymbol = heighestPriceProduct.Price.Currency.Symbol; } var lowestPriceProduct = productService.GetHighestOrLowest(query, parameters, Dynamicweb.Indexing.Querying.Sorting.SortDirection.Ascending, "Price"); double lowestPrice = 0.0; if (lowestPriceProduct != null) { lowestPrice = Math.Floor(lowestPriceProduct.Price.PriceWithVAT); } var currentPriceQueryString = (!string.IsNullOrWhiteSpace(HttpContext.Current.Request.QueryString.Get("pricevat"))) ? HttpContext.Current.Request.QueryString.Get("pricevat") : HttpContext.Current.Request.QueryString.Get("pricevateur"); string[] currentPriceArray = { }; if (!string.IsNullOrWhiteSpace(currentPriceQueryString)) { currentPriceArray = currentPriceQueryString.Split(','); } var currentPriceLowValue = lowestPrice; var currentPriceHighValue = heighestPrice; if (currentPriceArray.Length == 2) { var currentPriceLowQuery = currentPriceArray.FirstOrDefault(); if (!string.IsNullOrWhiteSpace(currentPriceLowQuery)) { currentPriceLowValue = Convert.ToInt32(currentPriceLowQuery); } var currentPriceHighQuery = currentPriceArray.LastOrDefault(); if (!string.IsNullOrWhiteSpace(currentPriceHighQuery)) { currentPriceHighValue = Convert.ToInt32(currentPriceHighQuery); } } ////end price //Weight var heighestWeightProduct = productService.GetHighestOrLowest(query, parameters, Dynamicweb.Indexing.Querying.Sorting.SortDirection.Descending, "WeightNotAnalyzed"); double heighestWeight = 0.0; if (heighestWeightProduct != null) { heighestWeight = Math.Ceiling(heighestWeightProduct.Weight); } var lowestWeightProduct = productService.GetHighestOrLowest(query, parameters, Dynamicweb.Indexing.Querying.Sorting.SortDirection.Ascending, "WeightNotAnalyzed"); double lowestWeight = 0.0; if (lowestWeightProduct != null) { lowestWeight = Math.Floor(lowestWeightProduct.Weight); } var currentWeightQueryString = HttpContext.Current.Request.QueryString.Get("weight"); string[] currentWeightArray = { }; if (!string.IsNullOrWhiteSpace(currentWeightQueryString)) { currentWeightArray = currentWeightQueryString.Split(','); } var currentWeightLowValue = lowestWeight; var currentWeightHighValue = heighestWeight; if (currentWeightArray.Length == 2) { var currentWeightLowQuery = currentWeightArray.FirstOrDefault(); if (!string.IsNullOrWhiteSpace(currentWeightLowQuery)) { currentWeightLowValue = Convert.ToInt32(currentWeightLowQuery); } var currentWeightHighQuery = currentWeightArray.LastOrDefault(); if (!string.IsNullOrWhiteSpace(currentWeightHighQuery)) { currentWeightHighValue = Convert.ToInt32(currentWeightHighQuery); } } } @SnippetStart("canonical") <link rel="canonical" href="@groupViewModel.Canonical" /> @foreach (var hrefLang in groupViewModel.HrefLangs) { <link rel="alternate" hreflang="@hrefLang.HrefLang" href="@hrefLang.Href" /> } @SnippetEnd("canonical") @SnippetStart("languageSelector") <ul> @foreach (var languageArea in areas) { var hrefLang = groupViewModel.HrefLangs.FirstOrDefault(x => x.HrefAreaId == languageArea.ID); if (hrefLang == null || hrefLang.Href.ToLower().Contains("page-not-found")) { hrefLang = new HrefLangViewModel(); hrefLang.HrefName = languageArea.Item["ShopLanguageName"].ToString() ?? string.Empty; hrefLang.HrefLang = languageArea.CultureInfo.Name; hrefLang.Href = "/Default.aspx?areaid=" + languageArea.ID; hrefLang.HrefAreaId = languageArea.ID; } if (hrefLang != null && hrefLang.HrefLang != "x-default") { <li class="country-picker__item @(hrefLang.HrefAreaId == Pageview.AreaID ? "country-picker__item--current" : string.Empty)"> <a href="@hrefLang.Href"> <svg aria-hidden="true"> <use xlink:href="@staticResourceService.AddTimeStamp("/static/dist/svg/_bundle.svg")#outletcamping-arrow-right"></use> </svg> <span>@hrefLang.HrefName</span> </a> </li> } } </ul> @SnippetEnd("languageSelector") @if (groupViewModel.Hero != null) { @RenderParagraphContent(groupViewModel.Hero.ID) } @helper SortingMarkup(GroupViewModel groupViewModel, String triggerId, Boolean initModule = true) { var rawUrl = Dynamicweb.Context.Current.Request.Url; var uri = new Uri(rawUrl.ToString()); // this gets all the query string key value pairs as a collection var newQueryString = HttpUtility.ParseQueryString(uri.Query); // this removes the key if exists newQueryString.Remove("sortby"); newQueryString.Remove("sortorder"); var baseUrl = uri.GetLeftPart(UriPartial.Path); baseUrl = newQueryString.Count > 0 ? String.Format("{0}?{1}", baseUrl, newQueryString) : baseUrl; baseUrl = baseUrl.Contains("?") ? baseUrl + "&" : baseUrl + "?"; <div class="sorting" @(initModule ? "data-module=\"sorting\"" : string.Empty)> <input id="product-list-sorting-@triggerId" type="checkbox" class="trigger"> <label for="product-list-sorting-@triggerId" class="sorting__button btn"> <span class="btn__icon"> <svg role="img"><use xlink:href="@groupViewModel.StaticResourceService.AddTimeStamp("/static/dist/svg/_bundle.svg")#sorting"></use></svg> </span> <span class="btn__text"> @Translate("Sorting", "Sorting"): @if (HttpContext.Current.Request.QueryString.Get("sortby") == "Price") { @Translate("Price", "Price") } else if (HttpContext.Current.Request.QueryString.Get("sortby") == "ProductTitle") { @Translate("Alphabetical", "Alphabetical") } else { @Translate("Standard", "Standard") } </span> </label> <div class="sorting__options"> <ul> <li> <a href="@(baseUrl)">@Translate("Standard", "Standard")</a> </li> <li> <a href="@(baseUrl)sortby=Price&sortorder=asc">@Translate("Price", "Price")</a> </li> <li> <a href="@(baseUrl)sortby=ProductTitle&sortorder=asc">@Translate("Alphabetical", "Alphabetical")</a> </li> </ul> </div> </div> } <section class="content content--breadcrumb container-ribbon"> <div class="container"> <ol class="breadcrumb" itemscope itemtype="http://schema.org/BreadcrumbList"> @foreach (var item in groupViewModel.Breadcrumb) { if (item == groupViewModel.Breadcrumb.LastOrDefault()) { <li class="breadcrumb__item @(item == groupViewModel.Breadcrumb.LastOrDefault() ? "breadcrumb__item--current" : "")" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"> <meta itemprop="item" href="@item.Link"> <a> <span itemprop="name"> @if (breadCrumbIndex == breadCrumbTotal - 1) { @* The second to last breadcrumb item is the only one visible on mobile devices and thus the only one with this SVG *@ <svg aria-hidden="true"><use xlink:href="@groupViewModel.StaticResourceService.AddTimeStamp("/static/dist/svg/_bundle.svg")#arrow-left"></use></svg> } @item.LinkTitle </span> </a> <meta itemprop="position" content="@breadCrumbIndex"> </li> } else { <li class="breadcrumb__item @(item == groupViewModel.Breadcrumb.LastOrDefault() ? "breadcrumb__item--current" : "")" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"> <a itemprop="item" href="@item.Link"> <span itemprop="name"> @if (breadCrumbIndex == breadCrumbTotal - 1) { @* The second to last breadcrumb item is the only one visible on mobile devices and thus the only one with this SVG *@ <svg aria-hidden="true"><use xlink:href="@groupViewModel.StaticResourceService.AddTimeStamp("/static/dist/svg/_bundle.svg")#arrow-left"></use></svg> } @item.LinkTitle </span> </a> <meta itemprop="position" content="@breadCrumbIndex"> </li> } breadCrumbIndex++; } </ol> </div> </section> @if (subGroups != null) { <section class="content content--subnavigation container-ribbon"> <div class="container"> <nav class="subnavigation"> <ul> @foreach (var subGroup in subGroups) { var productsCount = groupService.GetProductsCount(subGroup); <li class="subnavigation__item @(subGroup.Id == groupId ? "subnavigation__item--active" : "")"> <a href="@urlService.GetUrl(subGroup.IdUrlEncoded)"> @subGroup.Name @(productsCount == 0 ? "" : "(" + productsCount + ")") </a> </li> } </ul> </nav> </div> </section> } @if (group != null && group.HasProducts()) { int count = 0; int ribbonIndex = 0; <section class="content content--product-list-title container-ribbon"> <div class="container"> <button type="button" class="filters-toggle"> <div> <svg role="img"><use xlink:href="@groupViewModel.StaticResourceService.AddTimeStamp("/static/dist/svg/_bundle.svg")#filters"></use></svg> </div> <div class="header__expand-menu-title" style="margin-left:0px;">FILTER</div> </button> @SortingMarkup(groupViewModel, "1") <div> @if (groupViewModel.Hero != null) { <span class="h-1">@group.Name</span> } else { <h1><span class="h-1">@group.Name</span></h1> } </div> </div> </section> foreach (var facetGroup in GetLoop("FacetGroups")) { if (subGroups != null) { <section class="content content--product-list-subgroups"> <section class="filter__groups"> <div class="container"> <nav> <ul style="background-color: #deeeed;margin: 5px;"> @foreach (var subGroup in subGroups) { var productsCount = groupService.GetProductsCount(subGroup); <li class="filter__groups-item @(subGroup.Id == groupId ? "subnavigation__item--active" : "")"> <a href="@urlService.GetUrl(subGroup.IdUrlEncoded)"> @subGroup.Name @(productsCount == 0 ? "" : "(" + productsCount + ")") </a> </li> } </ul> </nav> </div> </section> </section> } <section class="filter filter--hidden-on-mobile content content--product-list-filters container-ribbon" data-see-more="@Translate("SeeMore", "See more")" data-total-page-count="@GetString("Ecom:ProductList.TotalPages")" data-total-number="@GetString("Ecom:ProductList.PageProdCnt")" data-group-id="@group.Id" data-module="filter"> <form> <div class="container"> <div class="filter__container"> <div class="filter__icon-container"> <span class="filter__icon"> <svg role="img"><use xlink:href="@groupViewModel.StaticResourceService.AddTimeStamp("/static/dist/svg/_bundle.svg")#filters"></use></svg> </span> </div> <div class="filter__facets"> @*Weight*@ @if (lowestWeight < heighestWeight) { <div class="filter__facets-container filter__facets-container--large" data-facet-name="@Translate("weight", "Weight")" data-facet-queryname="weight"> <div class="filter__facet"> <div class="filter__facet-head"> <span class="btn"> <span class="btn__icon"> <svg role="img"> <use xlink:href="@groupViewModel.StaticResourceService.AddTimeStamp("/static/dist/svg/_bundle.svg")#outletcamping-arrow-right"></use> </svg> </span> <span class="btn__text">@Translate("weight", "Weight")</span> </span> </div> <div class="filter__facet-body filter__facet-body--slider"> <div class="filter__range" id="range-filter-weight" data-range-current-min="@currentWeightLowValue" data-range-current-max="@currentWeightHighValue" data-range-min="@lowestWeight" data-range-max="@heighestWeight" data-range-unit="kg" data-range-name="weight"></div> <div class="range-filter__container"> <div class="range-filter-weight-min"></div> <div class="range-filter-weight-max"></div> </div> <input id="weight-min" hidden name="weight" type="text" value="@currentWeightLowValue" /> <input id="weight-max" hidden name="weight" type="text" value="@currentWeightHighValue" /> </div> </div> </div> } @*Price*@ @if (lowestPrice < heighestPrice && (valutaSelector == null || Pageview.AreaID != 1)) { <div class="filter__facets-container filter__facets-container--large" data-facet-name="@Translate("price", "Price")" data-facet-queryname="pricevat"> <div class="filter__facet"> <div class="filter__facet-head"> <span class="btn"> <span class="btn__icon"> <svg role="img"> <use xlink:href="@groupViewModel.StaticResourceService.AddTimeStamp("/static/dist/svg/_bundle.svg")#outletcamping-arrow-right"></use> </svg> </span> <span class="btn__text">@Translate("price", "Price")</span> </span> </div> <div class="filter__facet-body filter__facet-body--slider"> <div class="filter__range" id="range-filter-pricevat" data-range-current-min="@currentPriceLowValue" data-range-current-max="@currentPriceHighValue" data-range-min="@lowestPrice" data-range-max="@heighestPrice" data-range-unit="@currencySymbol" data-range-name="pricevat"></div> <div class="range-filter__container"> <div class="range-filter-pricevat-min"></div> <div class="range-filter-pricevat-max"></div> </div> <input id="pricevat-min" hidden name="pricevat" type="text" value="@currentPriceLowValue" /> <input id="pricevat-max" hidden name="pricevat" type="text" value="@currentPriceHighValue" /> </div> </div> </div> } @if (lowestPrice < heighestPrice && (valutaSelector != null && Pageview.AreaID == 1)) { <div class="filter__facets-container filter__facets-container--large" data-facet-name="@Translate("price", "Price")" data-facet-queryname="pricevateur"> <div class="filter__facet"> <div class="filter__facet-head"> <span class="btn"> <span class="btn__icon"> <svg role="img"> <use xlink:href="@groupViewModel.StaticResourceService.AddTimeStamp("/static/dist/svg/_bundle.svg")#outletcamping-arrow-right"></use> </svg> </span> <span class="btn__text">@Translate("price", "Price")</span> </span> </div> <div class="filter__facet-body filter__facet-body--slider"> <div class="filter__range" id="range-filter-pricevateur" data-range-current-min="@currentPriceLowValue" data-range-current-max="@currentPriceHighValue" data-range-min="@lowestPrice" data-range-max="@heighestPrice" data-range-unit="@currencySymbol" data-range-name="pricevateur"></div> <div class="range-filter__container"> <div class="range-filter-pricevateur-min"></div> <div class="range-filter-pricevateur-max"></div> </div> <input id="pricevateur-min" hidden name="pricevateur" type="text" value="@currentPriceLowValue" /> <input id="pricevateur-max" hidden name="pricevateur" type="text" value="@currentPriceHighValue" /> </div> </div> </div> } @*end price*@ @foreach (var facet in facetGroup.GetLoop("Facets")) { var renderType = facet.GetString("Facet.RenderType"); var optionsCount = facet.GetInteger("Facet.OptionWithResultCount"); if (optionsCount < 1 || renderType == "Range" && optionsCount < 2) { continue; } var facetMinValue = 0; var facetMaxValue = 0; List<int> facetValues = new List<int>(); var facetOptions = facet.GetLoop("FacetOptions"); if (renderType == "Range") { foreach (var facetOption in facetOptions) { var facetValue = facetOption.GetString("FacetOption.Value").Trim(); if (isStringInt(facetValue) && int.Parse(facetValue) > 0) { facetValues.Add(int.Parse(facetValue)); } } facetMinValue = facetValues.Min(); facetMaxValue = facetValues.Max(); } string facetClass = "filter__facets-container"; if (facet.GetString("Facet.QueryParameter") == "color") { facetClass = "filter__facets-container filter__facets-container--large"; } var id = 0; var faceType = (renderType == "Range") ? "filter__facet-body--slider" : string.Empty; var queryParam = facet.GetString("Facet.QueryParameter"); if(renderType == "Range" && facetMinValue < facetMaxValue || renderType != "Range") { <div class="@facetClass" data-facet-name="@facet.GetString("Facet.Name")" data-facet-queryname="@facet.GetString("Facet.QueryParameter")"> <div class="filter__facet"> <div class="filter__facet-head"> <span class="btn"> <span class="btn__icon"> <svg role="img"> <use xlink:href="@groupViewModel.StaticResourceService.AddTimeStamp("/static/dist/svg/_bundle.svg")#outletcamping-arrow-right"></use> </svg> </span> <span class="btn__text">@Translate(facet.GetString("Facet.Name"), facet.GetString("Facet.Name"))</span> </span> </div> <div class="filter__facet-body @faceType"> @switch (renderType) { case "Checkboxes": foreach (var facetOption in facetOptions) { <div class="filter__facet-seperator"> <input type="checkbox" @(facetOption.GetBoolean("FacetOption.Selected") ? "checked" : "") name="@facet.GetString("Facet.QueryParameter")" value="@facetOption.GetString("FacetOption.Value")" id="@facet.GetString("Facet.QueryParameter")@id" /> <label for="@facet.GetString("Facet.QueryParameter")@id"> @facetOption.GetString("FacetOption.Label").Replace("xxx", " ") @if (facet.GetString("Facet.QueryParameter") == "width" || facet.GetString("Facet.QueryParameter") == "height") { <text>cm</text> } </label> </div> id++; } break; case "Range": if (facetValues.Count > 0) { string[] facetSelectedValues = { facetMinValue.ToString(), facetMaxValue.ToString() }; if (HttpContext.Current.Request.QueryString.Get(queryParam) != null) { facetSelectedValues = HttpContext.Current.Request.QueryString.Get(queryParam).Split(','); } var facetCurrentMinValue = facetSelectedValues[0]; var facetCurrentMaxValue = facetSelectedValues[1]; <div class="filter__range" id="range-filter-@queryParam" data-range-current-min="@facetCurrentMinValue" data-range-current-max="@facetCurrentMaxValue" data-range-min="@facetMinValue" data-range-max="@facetMaxValue" data-range-unit="@Translate(queryParam + "-unit", queryParam + "-unit")" data-range-name="@queryParam"> </div> <div class="range-filter__container"> <div class="range-filter-@queryParam-min"></div> <div class="range-filter-@queryParam-max"></div> </div> <input id="@queryParam-min" hidden name="@queryParam" type="text" value="@facetCurrentMinValue" /> <input id="@queryParam-max" hidden name="@queryParam" type="text" value="@facetCurrentMaxValue" /> } break; } </div> </div> </div> } } </div> <div class="filter__filter-container"> <button type="button" class="filter__list-item filter__filter-reset filter__filter-reset--hidden"> <span>@Translate("FilterResetAll", "Reset all")</span> </button> <button class="btn btn--filled"> <span class="btn__text">@Translate("Filter", "Filter")</span> </button> </div> @SortingMarkup(groupViewModel, "2", false) </div> <div class="filter__list-container hidden"> <div class="filter__list"></div> <button type="button" class="filter__list-item filter__filter-reset"> <span> <svg role="img"> <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/static/dist/svg/_bundle.svg#close"></use> </svg> </span> <span>@Translate("FilterResetAll", "Reset all")</span> </button> </div> </div> @if (!String.IsNullOrEmpty(HttpContext.Current.Request.QueryString.Get("sortby"))) { <input name="sortby" type="hidden" value="@HttpContext.Current.Request.QueryString.Get("sortby")"> } @if (!String.IsNullOrEmpty(HttpContext.Current.Request.QueryString.Get("sortorder"))) { <input name="sortorder" type="hidden" value="@HttpContext.Current.Request.QueryString.Get("sortorder")"> } </form> </section> } <section class="content content--body"> <div class="product-item-wrapper container-ribbon"> <div class="container"> <section class="product-container"> @foreach (var p in GetLoop("Products")) { if (groupViewModel.HeroProduct != null && p.GetString("Ecom:Product.ID") == groupViewModel.HeroProduct.Id) { // Skip if this is the chosen hero product continue; } if (groupViewModel.IsFiltered == false && count % 6 == 0 && count > 0) { if (count == 6 && groupViewModel.HeroProduct != null) { //Show hero @RenderHeroProduct(groupViewModel.HeroProduct, groupViewModel, true) } else if (count == 6 && groupViewModel.FeaturedRibbonIds.Count > ribbonIndex && ribbonIndex != groupViewModel.FeaturedRibbonIds.Count - 1) { @endSection //Show embedded content @RenderParagraphContent(groupViewModel.FeaturedRibbonIds[ribbonIndex]) ribbonIndex++; @beginSection } else if (count > 0 && groupViewModel.FeaturedRibbonIds.Count > ribbonIndex && ribbonIndex != groupViewModel.FeaturedRibbonIds.Count - 1) { @endSection //Show embedded content @RenderParagraphContent(groupViewModel.FeaturedRibbonIds[ribbonIndex]) ribbonIndex++; @beginSection } } count++; @RenderProduct(p, groupViewModel, false) } @if (groupViewModel.IsFiltered == false && groupViewModel.FeaturedRibbonIds != null && groupViewModel.FeaturedRibbonIds.Count > ribbonIndex) { @endSection //Render any remaining ribbons on product page for (int i = ribbonIndex; i < groupViewModel.FeaturedRibbonIds.Count; i++) { if (i != groupViewModel.FeaturedRibbonIds.Count - 1) { @RenderParagraphContent(groupViewModel.FeaturedRibbonIds[i]) } } @beginSection } @if (groupViewModel.FeaturedRibbonIds.Count > 0) { @RenderParagraphContent(groupViewModel.FeaturedRibbonIds[groupViewModel.FeaturedRibbonIds.Count - 1]) } </section> <div class="search-results__button"> <span class="btn"> <span class="btn__text">@Translate("LoadMore", "Load More")</span> </span> </div> </div> </div> @if (groupViewModel.SEO != null) { @RenderParagraphContent(groupViewModel.SEO.ID) } </section> } @helper RenderProduct(LoopItem product, GroupViewModel groupViewModel, bool isHero) { var productClass = isHero ? "product-item--hero" : "product-item--flex"; <article itemscope itemtype="http://schema.org/Product" class="product-item @productClass"> <link itemprop="brand" content="@product.GetString("Ecom:Product:Field.BrandName")" /> <link itemprop="description" content="@product.GetString("Ecom:Product.LongDescription")" /> <link itemprop="sku" content="@product.GetString("Ecom:Product.Number")" /> <a itemprop="url" href="@groupViewModel.UrlService.GetUrl(groupViewModel.Id, product.GetString("Ecom:Product.ID"))"> <div class="product-item__header"> @{ var imageService = ServiceLocator.Current.GetImageService(); var productResourceService = ServiceLocator.Current.GetProductResourceService(); var imagePath = productResourceService.Get(product.GetString("Ecom:Product:Field.Image001"), FileFormat.Jpeg); var img = imageService.Begin(imagePath); var imgSrc = img.SetWidth(800).SetHeight(800).SetCrop(CropType.KeepAspectRatio).SetCompression(80).GetCrop(); } <figure class="lazy" data-src-sm="@imgSrc" data-alt="@product.GetString("Ecom:Product.Name")"> <noscript><img src="@imgSrc" itemprop="image" content="@imgSrc" alt="@product.GetString("Ecom:Product.Name")"></noscript> </figure> @if (!string.IsNullOrEmpty(product.GetString("Ecom:Product:Field.OutletcampingSplash")) && !string.IsNullOrEmpty(product.GetString("Ecom:Product:Field.OutletcampingSplashColor"))) { var splashTexts = product.GetString("Ecom:Product:Field.OutletcampingSplash").Split(' '); <div class="product-item__splash" style="background: @product.GetString("Ecom:Product:Field.OutletcampingSplashColor");"> <div class="product-item__splash-text"> <p> @for (var i = 0; i <= splashTexts.Length - 1; i++) { if (i == 1) { <span class="product-item__splash-text--bold"> @splashTexts[i]</span> } else { @splashTexts[i] } } </p> </div> </div> } </div> <div class="product-item__body"> @{ var periodEndDateSql = Database.ExecuteScalar(CommandBuilder.Create("SELECT p.PeriodEndDate FROM EcomProducts AS ep INNER JOIN EcomPeriods AS p ON ep.ProductPeriodId = p.PeriodId WHERE ep.ProductId = {0} AND ep.ProductLanguageId = {1}", product.GetString("Ecom:Product.ID"), product.GetString("Ecom:Product.LanguageID"))); var periodEndDate = (periodEndDateSql != null) ? (DateTime)periodEndDateSql : DateTime.MinValue; if (periodEndDate >= DateTime.Now && periodEndDate <= DateTime.Now.AddDays(14)) { <div data-module="countdown"> <div class="product-item__countdown" data-date="@periodEndDate.ToString("MM/dd/yyyy HH:mm:ss")"> <div class="product-item__countdown-title">@Translate("Offer ends in")</div> <div class="product-item__countdown-counter"></div> <div class="product-item__countdown-text"> <span>@Translate("Hours", "Hours")</span> <span>@Translate("Min", "Min")</span> <span>@Translate("Sec", "Sec")</span> </div> </div> </div> } } <div class="product-item__headline"> <h2 itemprop="name">@product.GetString("Ecom:Product.Name")</h2> </div> @if (!string.IsNullOrEmpty(@product.GetString("Ecom:Product.Price.Price"))) { <div itemprop="offers" itemscope itemtype="http://schema.org/Offer" class="product-item__price"> <link itemprop="availability" href="http://schema.org/InStock"> <link itemprop="url" href="@groupViewModel.UrlService.GetUrl(groupViewModel.Id, product.GetString("Ecom:Product.ID"))" /> @if (!string.IsNullOrEmpty(product.GetString("Ecom:Product:Field.Savepct.Value"))) { <div class="save"> <span>@Translate("Save", "Save") @product.GetString("Ecom:Product:Field.Savepct.Value")%</span> </div> } <div class="price"><span itemprop="priceCurrency" content="@product.GetString("Ecom:Product.Price.Currency.Symbol")">@product.GetString("Ecom:Product.Price.Currency.Symbol")</span> <span itemprop="price" content="@product.GetDouble("Ecom:Product.Price.PriceWithVAT.Value").ToString("F", new CultureInfo("en-GB"))">@product.GetString("Ecom:Product.Price.Price")</span></div> <div class="if-discount"> @if (!string.IsNullOrEmpty(product.GetString("Ecom:Product:Field.PriceBefore.Value"))) { if (product.GetDouble("Ecom:Product:Field.PriceBefore.Value") > 0) { <span>@Translate("Before", "Used to be") @product.GetString("Ecom:Product.Price.Currency.Symbol") @product.GetString("Ecom:Product:Field.PriceBefore.Value")</span> } } </div> </div> } <div class="product-item__button"> <span class="btn"> @if (Pageview.AreaID != 2) { <span class="btn__icon"> <img src="@groupViewModel.StaticResourceService.AddTimeStamp("/static/dist/media/cart-white-outletcamping.png")"> </span> } <span class="btn__text">@Translate("SeeMore", "See more")</span> </span> </div> </div> </a> @if (isHero && groupViewModel.HeroImage != null) { <figure> <img src="@groupViewModel.HeroImage.SetWidth(800).SetHeight(400).SetCrop(CropType.KeepAspectRatio).SetCompression(80).GetCrop()" /> </figure> } </article> } @helper RenderHeroProduct(ProductViewModel productViewModel, GroupViewModel groupViewModel, bool isHero) { var productClass = isHero ? "product-item--hero" : "product-item--flex"; <article itemscope itemtype="http://schema.org/Product" class="product-item @productClass"> <a itemprop="url" href="@groupViewModel.UrlService.GetUrl(groupViewModel.Id, productViewModel.Id)"> <div class="product-item__header"> <figure> <img src="@productViewModel.MainImage.SetWidth(800).SetHeight(800).SetCrop(CropType.KeepAspectRatio).SetCompression(80).GetCrop()" itemprop="image" content="@productViewModel.MainImage.SetWidth(800).SetHeight(800).SetCrop(CropType.KeepAspectRatio).SetCompression(80).GetCrop()" alt=""> </figure> @if (!string.IsNullOrEmpty(productViewModel.OutletcampingSplash) && !string.IsNullOrEmpty(productViewModel.OutletcampingSplashColor)) { var splashTexts = productViewModel.OutletcampingSplash.Split(' '); <div class="product-item__splash product-item__splash" style="background: @productViewModel.OutletcampingSplashColor;"> <div class="product-item__splash-text"> <p> @for (var i = 0; i <= splashTexts.Length - 1; i++) { if (i == 1) { <span class="product-item__splash-text--bold"> @splashTexts[i]</span> } else { @splashTexts[i] } } </p> </div> </div> } </div> <div class="product-item__body"> @{ if (productViewModel.PeriodEndDate >= DateTime.Now && productViewModel.PeriodEndDate <= DateTime.Now.AddDays(14)) { <div data-module="countdown"> <div class="product-item__countdown" data-date="@productViewModel.PeriodEndDate.ToString("MM/dd/yyyy HH:mm:ss")"> <div class="product-item__countdown-title">@Translate("Offer ends in")</div> <div class="product-item__countdown-counter"></div> <div class="product-item__countdown-text"> <span>@Translate("Hours", "Hours")</span> <span>@Translate("Min", "Min")</span> <span>@Translate("Sec", "Sec")</span> </div> </div> </div> } } <div class="product-item__headline"> <h1 itemprop="name">@productViewModel.Name</h1> </div> @if (!string.IsNullOrEmpty(@productViewModel.Price)) { <div itemprop="offers" itemscope itemtype="http://schema.org/Offer" class="product-item__price"> <div class="price"><span itemprop="priceCurrency" content="@productViewModel.Currency">@productViewModel.CurrencySymbol</span> <span itemprop="price" content="@productViewModel.UnformatedPrice">@productViewModel.Price</span></div> <div class="if-discount"> @if (!string.IsNullOrEmpty(productViewModel.BeforePrice)) { <span>@Translate("Before", "Used to be") @productViewModel.CurrencySymbol @productViewModel.BeforePrice</span> } </div> </div> } <div class="product-item__button"> <span class="btn"> @if (Pageview.AreaID != 2) { <span class="btn__icon"> <img src="@groupViewModel.StaticResourceService.AddTimeStamp("/static/dist/media/cart-white-outletcamping.png")"> </span> } <span class="btn__text">@Translate("SeeMore", "See more")</span> </span> </div> </div> </a> @if (isHero && groupViewModel.HeroImage != null) { <figure> <img src="@groupViewModel.HeroImage.SetWidth(800).SetHeight(400).SetCrop(CropType.KeepAspectRatio).SetCompression(80).GetCrop()" /> </figure> } </article> } @SnippetStart("jarvis") @{ var raptorArea = PageView.Current().Area; var settingsRaptorApiKey = PageView.Current().Area.Item["SettingsRaptorApiKey"]; } @if (settingsRaptorApiKey != null) { if (PageView.Current().Device == Dynamicweb.Frontend.Devices.DeviceType.Desktop && !string.IsNullOrEmpty(settingsRaptorApiKey.ToString())) { var jarvis = (HttpContext.Current.Request.Cookies["jarvis"] != null) ? HttpContext.Current.Request.Cookies["jarvis"].Value : "1"; var jarvisBoxStatus = (jarvis == "1") ? "jarvis--open" : string.Empty; var jarvisBtnStatus = (jarvis == "1") ? "" : "jarvis-btn--open"; var raptorAreaId = raptorArea.ID; var raptorBrandId = (raptorArea.Item["SettingsRaptorUserId"] != null) ? raptorArea.Item["SettingsRaptorUserId"].ToString() : string.Empty; var raptorCookieId = (HttpContext.Current.Request.Cookies[raptorBrandId + "rsa"] != null) ? HttpContext.Current.Request.Cookies[raptorBrandId + "rsa"].Value : ""; var raptorContent1 = groupViewModel.JarvisHistory; var raptorContent2 = groupViewModel.JarvisTopCategory; var settingsShopId = raptorArea.Item["SettingsShopId"].ToString(); var ecomPageId = urlParserService.GetPageId(settingsShopId); if (!string.IsNullOrEmpty(raptorCookieId)) { <div data-module="jarvis"> <div class="jarvis @jarvisBoxStatus"> <div class="jarvis__header"> <span class="your">@Translate("Your", "Your")</span> <span class="guide">@Translate("Guide", "Guide")</span> <span class="logo"></span> </div> <div class="jarvis__guide"> <button class="jarvis__close"><span class="round"><svg viewBox="0 0 100 100"><path d="M 10,50 L 60,100 L 70,90 L 30,50 L 70,10 L 60,0 Z" class="arrow"></path></svg></span> @Translate("Hide the wizard", "Hide the wizard")</button> <div class="jarvis__text"> <p> @Translate("The guide follows you around and finds new recommendations based on what you're looking at.", "The guide follows you around and finds new recommendations based on what you're looking at.") </p> </div> </div> <div class="jarvis__alternatives"> <section class="featured-products container-ribbon ribbon"> <h3>@Translate("Most seen in this category", "Most seen in this category")</h3> <div class="featured-products__container" data-url="/webservices/jarvis.ashx?areaId=@raptorAreaId&raptorFunction=GetTopViewedInCategory&raptorCategoryId=@groupId"> @foreach (var raptorProduct in raptorContent2) { var raptorProductView = productViewModelService.GetViewModel(raptorProduct); if (raptorProductView.MainImage != null) { raptorProductView.RaptorImage = raptorProductView.MainImage.SetWidth(500).SetHeight(300).SetCrop(CropType.KeepAspectRatio).SetCompression(50).GetCrop(); } raptorProductView.RaptorUrl = urlService.GetUrl(raptorProductView.GroupId, raptorProductView.Id, ecomPageId.GetValueOrDefault()); <article itemscope itemtype="http://schema.org/Product\" class="product-item"> <a itemprop="url" href="@raptorProductView.RaptorUrl"> <div class="product-item__header"> <figure> <img src="@raptorProductView.RaptorImage" itemprop="image" content="OaseOutdoors.Services.ImageService.ImageService" alt="@raptorProductView.Name"> </figure> </div> <div class="product-item__body"> <div class="product-item__headline"> <h3 itemprop="name" class="h-1">@raptorProductView.Name</h3> </div> <div itemprop="offers" itemscope itemtype="http://schema.org/Offer" class="product-item__price"> <div class="price"><span itemprop=\"priceCurrency\" content="@raptorProductView.Currency">@raptorProductView.CurrencySymbol</span> <span itemprop="price" content="@raptorProductView.UnformatedPrice">@raptorProductView.Price</span></div> </div> </div> </a> </article> } </div> </section> </div> <div class="jarvis__suggest"> <section class="featured-products container-ribbon ribbon"> <h3>@Translate("You have previously looked at", "You have previously looked at")</h3> <div class="featured-products__container" data-url="/webservices/jarvis.ashx?areaId=@raptorAreaId&raptorFunction=GetCookieHistory"> @foreach (var raptorProduct in raptorContent1) { var raptorProductView = productViewModelService.GetViewModel(raptorProduct); if (raptorProductView.MainImage != null) { raptorProductView.RaptorImage = raptorProductView.MainImage.SetWidth(500).SetHeight(300).SetCrop(CropType.KeepAspectRatio).SetCompression(50).GetCrop(); } raptorProductView.RaptorUrl = urlService.GetUrl(raptorProductView.GroupId, raptorProductView.Id, ecomPageId.GetValueOrDefault()); <article itemscope itemtype="http://schema.org/Product\" class="product-item"> <a itemprop="url" href="@raptorProductView.RaptorUrl"> <div class="product-item__header"> <figure> <img src="@raptorProductView.RaptorImage" itemprop="image" content="OaseOutdoors.Services.ImageService.ImageService" alt="@raptorProductView.Name"> </figure> </div> <div class="product-item__body"> <div class="product-item__headline"> <h3 itemprop="name" class="h-1">@raptorProductView.Name</h3> </div> <div itemprop="offers" itemscope itemtype="http://schema.org/Offer" class="product-item__price"> <div class="price"><span itemprop=\"priceCurrency\" content="@raptorProductView.Currency">@raptorProductView.CurrencySymbol</span> <span itemprop="price" content="@raptorProductView.UnformatedPrice">@raptorProductView.Price</span></div> </div> </div> </a> </article> } </div> </section> </div> </div> <div class="jarvis-btn @jarvisBtnStatus"> <img src="/static/dist/img/jarvis/jarvis-small.png"> </div> </div> } } } @SnippetEnd("jarvis") @functions { public bool isStringInt(String s) { try { int.Parse(s); return true; } catch (FormatException ex) { return false; } } }