Filter:

Error executing template "/Designs/Swift/Paragraph/Swift_ProductListFacets_Custom.cshtml"
System.IO.IOException: The process cannot access the file 'D:\dynamicweb.net\Solutions\twodayco3\evasolo.cloud.dynamicweb-cms.com\Files\Templates\Designs\Swift\Translations.xml' because it is being used by another process.
   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)
   at Dynamicweb.Rendering.Translation.Source.WriteDocument(XmlDocument document)
   at Dynamicweb.Rendering.Translation.Source.Save()
   at Dynamicweb.Rendering.Translation.Source.UpdateTranslationSource(Source source, IEnumerable`1 newKeys, String designName, IEnumerable`1 cultures)
   at Dynamicweb.Rendering.Template.TranslateText(String text, String defaultValue, String cultureName)
   at Dynamicweb.Rendering.TemplateBase`1.Translate(String text, String defaultValue)
   at CompiledRazorTemplates.Dynamic.RazorEngine_c1b0767df89240cf83e66edfda2fc218.<>c__DisplayClass3_0.<RenderForm>b__2(FacetOptionViewModel i) in D:\dynamicweb.net\Solutions\twodayco3\evasolo.cloud.dynamicweb-cms.com\Files\Templates\Designs\Swift\Paragraph\Swift_ProductListFacets_Custom.cshtml:line 377
   at System.Linq.EnumerableSorter`2.ComputeKeys(TElement[] elements, Int32 count)
   at System.Linq.EnumerableSorter`1.Sort(TElement[] elements, Int32 count)
   at System.Linq.OrderedEnumerable`1.<GetEnumerator>d__1.MoveNext()
   at CompiledRazorTemplates.Dynamic.RazorEngine_c1b0767df89240cf83e66edfda2fc218.<>c__DisplayClass3_0.<RenderForm>b__0(TextWriter __razor_helper_writer) in D:\dynamicweb.net\Solutions\twodayco3\evasolo.cloud.dynamicweb-cms.com\Files\Templates\Designs\Swift\Paragraph\Swift_ProductListFacets_Custom.cshtml:line 377
   at CompiledRazorTemplates.Dynamic.RazorEngine_c1b0767df89240cf83e66edfda2fc218.Execute() in D:\dynamicweb.net\Solutions\twodayco3\evasolo.cloud.dynamicweb-cms.com\Files\Templates\Designs\Swift\Paragraph\Swift_ProductListFacets_Custom.cshtml:line 151
   at RazorEngine.Templating.TemplateBase.RazorEngine.Templating.ITemplate.Run(ExecuteContext context, TextWriter reader)
   at RazorEngine.Templating.RazorEngineService.RunCompile(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag)
   at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass16_0.<RunCompile>b__0(TextWriter writer)
   at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter)
   at Dynamicweb.Rendering.RazorTemplateRenderingProvider.Render(Template template)
   at Dynamicweb.Rendering.TemplateRenderingService.Render(Template template)
   at Dynamicweb.Rendering.Template.RenderRazorTemplate()

1 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.ParagraphViewModel> 2 @using Dynamicweb 3 @using Dynamicweb.Ecommerce.ProductCatalog 4 @using Dynamicweb.Frontend.Navigation 5 @using Dynamicweb.Environment 6 @using Dynamicweb.Core.Encoders 7 @using System.Web 8 9 @* TODO: REFACTURE/UPGRADE TO SWIFT (v1.25.0) *@ 10 @* CUSTOM FUNCTIONS - TODO: MOVE TO BE/PROJECT *@ 11 12 @functions 13 { 14 public class GroupFacetRelation 15 { 16 public string group { set; get; } 17 public string field { set; get; } 18 } 19 20 public List<GroupFacetRelation> GroupFacetRelations(ProductListViewModel model = null) 21 { 22 var groupFacetRelations = new List<GroupFacetRelation>() { }; 23 24 if (model != null && model.FacetGroups != null && model.FacetGroups.Any()) 25 { 26 if (model.Group == null) // NOTE: All top level groups is returned null in model (GroupID is not defined). 27 { 28 model.Group = new ProductGroupViewModel(); 29 model.Group.Id = Dynamicweb.Ecommerce.Services.ProductGroups.GetToplevelGroups(Pageview.Area.EcomLanguageId).FirstOrDefault(i => i.Name == Pageview.Page.MenuText)?.Id; // NOTE: Reference; page name = group name. 30 } 31 32 var sql = "SELECT GroupFacetRelationFacetGroup, GroupFacetRelationFacetField FROM EcomGroupFacetRelation WHERE GroupFacetRelationRepository = 'SwiftProducts' AND GroupFacetRelationGroupId = {0} AND (GroupFacetRelationFacetGroup IN ({1}) OR GroupFacetRelationFacetField IS NULL)"; 33 Dynamicweb.Data.CommandBuilder cb = Dynamicweb.Data.CommandBuilder.Create(sql, model.Group.Id, model.FacetGroups.Select(i => i.Name)); 34 35 using (var dr = Dynamicweb.Data.Database.CreateDataReader(cb)) 36 { 37 while (dr.Read()) 38 { 39 groupFacetRelations.Add(new GroupFacetRelation 40 { 41 group = Convert.ToString(dr["GroupFacetRelationFacetGroup"]), 42 field = Convert.ToString(dr["GroupFacetRelationFacetField"]) 43 }); 44 } 45 } 46 } 47 48 return groupFacetRelations; 49 } 50 51 public bool GroupFacetRelationEnable(List<GroupFacetRelation> groupFacetRelations, string group, string field) 52 { 53 // If GroupFacetRelationFacetGroup not exists = Show 54 // If GroupFacetRelationFacetGroup exists and GroupFacetRelationFacetField is empty = Hide 55 // If GroupFacetRelationFacetGroup exists and GroupFacetRelationFacetField equal FacetField = Show 56 // If GroupFacetRelationFacetGroup exists and GroupFacetRelationFacetField not equal FacetField = Hide 57 58 if (!groupFacetRelations.Any(i => i.group == group)) return true; 59 else if (groupFacetRelations.Any(i => i.group == group && i.field == field)) return true; 60 return false; 61 } 62 } 63 64 @{ 65 ProductListViewModel productList = new ProductListViewModel(); 66 67 if (Dynamicweb.Context.Current.Items.Contains("ProductList")) 68 { 69 productList = (ProductListViewModel)Dynamicweb.Context.Current.Items["ProductList"]; 70 } 71 72 // CUSTOM 73 var groupFacetRelations = GroupFacetRelations(productList); 74 75 string url = Pageview.SearchFriendlyUrl; 76 url = url.LastIndexOf("?") != -1 ? url.Substring(0, url.LastIndexOf("?")) : url; 77 78 //Fix for non-friendly urls 79 if (Dynamicweb.Context.Current.Request.QueryString.Get("GroupID") != null) 80 { 81 string groupId = Dynamicweb.Context.Current.Request.QueryString.Get("GroupID"); 82 url += "?GroupID=" + groupId; 83 } 84 85 if (!url.Contains("LayoutTemplate")) 86 { 87 url += url.Contains("?") ? "&LayoutTemplate=Designs/Swift/Swift_PageClean.cshtml" : "?LayoutTemplate=Designs/Swift/Swift_PageClean.cshtml"; 88 } 89 90 bool facetsFound = false; 91 int selectedFacetsCount = 0; 92 93 if (productList.FacetGroups != null) 94 { 95 foreach (FacetGroupViewModel facetGroup in productList.FacetGroups) 96 { 97 foreach (FacetViewModel facet in facetGroup.Facets) 98 { 99 if (facet.Options.Count() > 0 && GroupFacetRelationEnable(groupFacetRelations, facetGroup.Name, facet.FacetField)) 100 { 101 facetsFound = true; 102 103 foreach (FacetOptionViewModel option in facet.Options) 104 { 105 if (option.Selected) 106 { 107 selectedFacetsCount++; 108 } 109 } 110 } 111 } 112 } 113 } 114 string contentPadding = Model.Item.GetRawValueString("ContentPadding", ""); 115 contentPadding = Model.Item.GetRawValueString("ContentPadding", "") == "none" ? " px-0 py-2" : contentPadding; 116 contentPadding = Model.Item.GetRawValueString("ContentPadding", "") == "small" ? " px-3 py-2" : contentPadding; 117 118 bool enableSorting = Model.Item.GetBoolean("SortByNameAZ"); 119 enableSorting = Model.Item.GetBoolean("SortByNameZA") || enableSorting == true ? true : false; 120 enableSorting = Model.Item.GetBoolean("SortByNewest") || enableSorting == true ? true : false; 121 enableSorting = Model.Item.GetBoolean("SortByLowestPrice") || enableSorting == true ? true : false; 122 enableSorting = Model.Item.GetBoolean("SortByHighestPrice") || enableSorting == true ? true : false; 123 124 string layout = Model.Item.GetRawValueString("Layout", "vertical"); 125 } 126 127 @if (productList.TotalProductsCount > 0 && (facetsFound || Model.Item.GetBoolean("EnableGroupNavigation") || enableSorting)) 128 { 129 string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("Theme")) ? " theme " + Model.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : ""; 130 string modalTheme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("ModalTheme")) ? " theme " + Model.Item.GetRawValueString("ModalTheme").Replace(" ", "").Trim().ToLower() : ""; 131 string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/"; 132 string selectedFacetsLabel = selectedFacetsCount > 0 ? "(" + selectedFacetsCount + ")" : ""; 133 134 //Desktop 135 if (layout == "vertical") 136 { 137 <form method="post" action="@url" data-response-target-element="content" id="FacetsForm_Desktop_@Model.ID" class="d-none d-lg-block h-100 @theme item_@Model.Item.SystemName.ToLower()"> 138 @{ 139 @RenderForm(productList, "desktop", enableSorting, groupFacetRelations, layout) 140 } 141 </form> 142 } 143 if (layout == "horizontal") 144 { 145 contentPadding = Model.Item.GetRawValueString("ContentPadding", "") == "small" ? " p-3" : contentPadding; 146 147 148 <div class="@theme @contentPadding h-100"> 149 <form method="post" action="@url" data-response-target-element="content" id="FacetsForm_Desktop_@Model.ID" class="d-none d-lg-flex gap-3 flex-row flex-wrap item_@Model.Item.SystemName.ToLower()"> 150 @{ 151 @RenderForm(productList, "desktop", enableSorting, groupFacetRelations, layout) 152 } 153 154 @if (selectedFacetsCount > 0) 155 { 156 <button type="button" class="btn btn-sm me-sm-1 me-lg-2" onclick="swift.ProductList.ResetFacets(event)"><span class="icon-2">@ReadFile(iconPath + "rotate-ccw.svg")</span> @Translate("Clear filters")</button> 157 } 158 </form> 159 </div> 160 } 161 162 //Mobile 163 <div class="d-block d-lg-none mt-lg-0 @(contentPadding)@(theme) FacetsForm_Mobile_@Model.Item.SystemName.ToLower()_@Model.ID"> 164 <button type="button" class="btn btn-primary w-100" data-bs-toggle="modal" data-bs-target="#FacetsModal"> 165 <span class="d-flex align-items-center"> 166 <span class="flex-grow-1 text-start"> 167 @Translate("Filter") @selectedFacetsLabel 168 </span> 169 <span class="icon-2"> 170 @ReadFile(iconPath + "sliders.svg") 171 </span> 172 </span> 173 </button> 174 175 <form method="post" action="@url" data-response-target-element="content" class="modal" id="FacetsModal" tabindex="-1" aria-hidden="false"> 176 <div class="modal-dialog modal-fullscreen"> 177 <div class="modal-content"> 178 <div class="modal-header@(modalTheme)"> 179 <h5 class="modal-title">@Translate("Filters and sorting")</h5> 180 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" onclick="document.querySelector('body').style = ''"></button> 181 </div> 182 <div class="modal-body@(modalTheme)"> 183 @{ 184 @RenderForm(productList, "mobile", enableSorting, groupFacetRelations) 185 } 186 </div> 187 <div class="modal-footer d-flex@(modalTheme)"> 188 @if (selectedFacetsCount != 0) 189 { 190 <button type="button" class="btn btn-secondary flex-fill" onclick="swift.ProductList.ResetFacets(event)">@Translate("Clear") (@selectedFacetsCount)</button> 191 } 192 <button type="button" class="btn btn-primary flex-fill" onclick="location.reload();">@Translate("Update")</button> 193 </div> 194 </div> 195 </div> 196 </form> 197 </div> 198 } 199 else 200 { 201 if (Pageview.IsVisualEditorMode) 202 { 203 <div class="alert alert-dark m-0" role="alert"> 204 <span>@Translate("Facets: The facets selectors will be shown here, if any")</span> 205 </div> 206 } 207 else if (productList.TotalProductsCount > 0) 208 { 209 <div class="alert alert-dark m-0" id="NoFiltersAlert_@Model.ID"> 210 @Translate("No filters are available") 211 </div> 212 } 213 } 214 215 @* CUSTOM parameter *@ 216 @helper RenderForm(ProductListViewModel productList, string deviceType, bool enableSorting, List<GroupFacetRelation> groupFacetRelations, string layout = "vertical") 217 { 218 string groupId = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("GroupID")) ? Dynamicweb.Context.Current.Request.QueryString.Get("GroupID") : ""; 219 220 string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/"; 221 string pageSize = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("PageSize")) ? Dynamicweb.Context.Current.Request.QueryString.Get("PageSize") : productList.PageSize.ToString(); 222 223 string searchQuery = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("q")) ? Dynamicweb.Context.Current.Request.QueryString.Get("q") : ""; 224 string searchLayout = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("SearchLayout")) ? Dynamicweb.Context.Current.Request.QueryString.Get("SearchLayout") : ""; 225 226 string groupsTheme = ""; 227 string extraBottomMargin = ""; 228 if (deviceType != "mobile") 229 { 230 groupsTheme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("FacetGroupsTheme")) ? " theme " + Model.Item.GetRawValueString("FacetGroupsTheme").Replace(" ", "").Trim().ToLower() : ""; 231 extraBottomMargin = !string.IsNullOrEmpty(groupsTheme) ? "mb-3" : ""; 232 } 233 234 string contentPadding = Model.Item.GetRawValueString("ContentPadding", ""); 235 contentPadding = contentPadding == "none" ? " px-0 py-2" : contentPadding; 236 contentPadding = contentPadding == "small" ? " px-3 py-2" : contentPadding; 237 238 <input type="hidden" name="PageSize" value="@pageSize"> 239 240 if (!string.IsNullOrEmpty(searchQuery)) 241 { 242 <input type="hidden" name="q" value="@searchQuery"> 243 <input type="hidden" name="SearchLayout" value="@searchLayout"> 244 } 245 246 if (Model.Item.GetBoolean("EnableGroupNavigation")) 247 { 248 int startLevel = Convert.ToInt32(Model.Item.GetRawValueString("GroupNavigationStartLevel", "2")); 249 int stopLevel = Convert.ToInt32(Model.Item.GetRawValueString("GroupNavigationStopLevel", "9")); 250 251 var navigationSettings = new NavigationSettings(); 252 navigationSettings.StartLevel = startLevel; 253 navigationSettings.StopLevel = stopLevel; 254 navigationSettings.Parameters.Add("ID", deviceType); 255 navigationSettings.Parameters.Add("HideTexts", false); 256 navigationSettings.Parameters.Add("HideIcons", true); 257 navigationSettings.Parameters.Add("ContentPadding", contentPadding); 258 navigationSettings.ExpandMode = ExpandMode.All; 259 navigationSettings.Parameters.Add("menu-id", "product-list-facets"); 260 261 if (layout == "vertical") 262 { 263 // CUSTOM css 264 <div class="border-bottom d-none d-lg-block py-2@(@groupsTheme)"> 265 <div class="d-flex@(contentPadding)" data-bs-toggle="collapse" data-bs-target="#ProductGroupNavigation_@(deviceType)_@Model.ID" role="button" aria-expanded="true" aria-controls="ProductGroupNavigation_@(deviceType)_@Model.ID"> 266 <h2 class="opacity-85 m-0 flex-fill h6">@Translate("Navigation")</h2> 267 <div class="my-auto collapse-chevron-icon"></div> 268 </div> 269 <div class="collapse show" id="ProductGroupNavigation_@(deviceType)_@Model.ID"> 270 @Navigation.RenderNavigation("Navigation/Vertical.cshtml", navigationSettings) 271 </div> 272 </div> 273 } 274 } 275 276 if (enableSorting) 277 { 278 if (layout == "vertical") 279 { 280 <div class="border-bottom@(contentPadding)@(groupsTheme)"> 281 <h2 class="opacity-85 m-0 my-2 flex-fill h6">@Translate("Sort by")</h2> 282 <div class="d-flex flex-column gap-2" id="SortBy_@(deviceType)_@Model.ID"> 283 @{ 284 @RenderSorting(deviceType) 285 } 286 </div> 287 </div> 288 } 289 if (layout == "horizontal") 290 { 291 <button class="btn @(groupsTheme) dropdown-toggle" type="button" id="SortBy_@(deviceType)_@Model.ID" data-bs-toggle="dropdown" aria-expanded="false"> 292 @Translate("Sort by") 293 </button> 294 <div class="dropdown-menu p-3 @(groupsTheme)" aria-labelledby="SortBy_@(deviceType)_@Model.ID" style="min-width: 280px"> 295 <div class="d-flex flex-column gap-2"> 296 @{ 297 @RenderSorting(deviceType) 298 } 299 </div> 300 </div> 301 } 302 } 303 304 int groupCount = 0; 305 int maxGroups = 8; 306 int totalGroups = productList?.FacetGroups != null ? productList.FacetGroups.Count() : 0; 307 308 if (productList.FacetGroups != null) 309 { 310 foreach (FacetGroupViewModel facetGroup in productList.FacetGroups) 311 { 312 string border = groupCount != totalGroups ? "border-bottom" : ""; 313 314 foreach (FacetViewModel facet in facetGroup.Facets) 315 { 316 string collapseClass = string.Empty; 317 string showClass = " show"; 318 string ariaExpanded = "true"; 319 var expandedFacetGroups = Model.Item.GetRawValueString("ExpandFacetGroups", "all"); 320 321 if (expandedFacetGroups != "all" && System.Text.RegularExpressions.Regex.IsMatch(expandedFacetGroups, "([0-9])")) 322 { 323 if (groupCount >= Dynamicweb.Core.Converter.ToInt32(expandedFacetGroups)) 324 { 325 collapseClass = " collapsed"; 326 showClass = string.Empty; 327 ariaExpanded = "false"; 328 } 329 } 330 331 if (facet.Options.Count() > 0 && facet.RenderType != "OnSale" && GroupFacetRelationEnable(groupFacetRelations, facetGroup.Name, facet.FacetField)) 332 { 333 if (layout == "vertical") 334 { 335 <div class="@border@(contentPadding)@(@groupsTheme)"> 336 <div class="d-flex@(collapseClass)" data-bs-toggle="collapse" data-bs-target="#FacetGroup_@facet.QueryParameter.ToLower()_@(deviceType)_@Model.ID" role="button" aria-expanded="@ariaExpanded" aria-controls="FacetGroup_@facet.QueryParameter.ToLower()_@(deviceType)_@Model.ID"> 337 <h2 class="opacity-85 m-0 flex-fill h6 my-2">@Translate("Custom:Facet." + facet.Name, facet.Name)</h2> 338 <div class="my-auto collapse-chevron-icon"></div> 339 </div> 340 <div class="collapse@(showClass)" id="FacetGroup_@facet.QueryParameter.ToLower()_@(deviceType)_@Model.ID"> 341 @foreach (FacetOptionViewModel facetOption in facet.Options.OrderBy(i => Translate("Custom:FacetOption." + i.Label, i.Label))) 342 { 343 string renderType = facet.RenderType; 344 345 if (renderType == "Colors") 346 { 347 @RenderColorOption(facet, facetOption) 348 } 349 else 350 { 351 @RenderCheckboxOption(facet, facetOption) 352 } 353 } 354 </div> 355 </div> 356 } 357 if (layout == "horizontal") 358 { 359 string hideSelector = groupCount < maxGroups ? "" : "d-none"; 360 int selectedFacetsInGroup = 0; 361 362 foreach (FacetOptionViewModel option in facet.Options) 363 { 364 if (option.Selected) 365 { 366 selectedFacetsInGroup++; 367 } 368 } 369 370 string label = selectedFacetsInGroup > 0 ? Translate("Custom:Facet." + facet.Name, facet.Name) + "<span class=\"badge bg-dark opacity-50 text-white ms-2\">" + selectedFacetsInGroup + "</span>" : Translate("Custom:Facet." + facet.Name, facet.Name); 371 // CUSTOM: removed dropdown css class to prevent hover dropdown 372 <div class="@hideSelector js-facets-selector"> 373 <button class="btn @(groupsTheme) dropdown-toggle" type="button" id="FacetGroup_@facet.Name.Replace(" ", "")_@(deviceType)_@Model.ID" data-bs-toggle="dropdown" aria-expanded="false"> 374 @label 375 </button> 376 <div class="dropdown-menu p-3 @(groupsTheme)" aria-labelledby="FacetGroup_@facet.Name.Replace(" ", "")_@(deviceType)_@Model.ID" style="min-width: 280px"> 377 @foreach (FacetOptionViewModel facetOption in facet.Options.OrderBy(i => Translate("Custom:FacetOption." + i.Label, i.Label))) 378 { 379 string renderType = facet.RenderType; 380 381 if (renderType == "Colors") 382 { 383 @RenderColorOption(facet, facetOption) 384 } 385 else 386 { 387 @RenderCheckboxOption(facet, facetOption) 388 } 389 } 390 </div> 391 </div> 392 } 393 394 groupCount++; 395 } 396 else if (facet.Options.Count() > 0 && facet.RenderType == "OnSale") 397 { 398 var contextCurrency = Smartpage.EvaSolo.CampaignPrices.Helpers.OnSaleHelper.GetOnSaleParameterValue(); 399 400 if (facet.Options.Where(o => o.Count > 0 && o.Value == contextCurrency).Any()) 401 { 402 if (layout == "vertical") 403 { 404 <div class="@border@(contentPadding)@(@groupsTheme)"> 405 <div class="d-flex@(collapseClass)" data-bs-toggle="collapse" data-bs-target="#FacetGroup_@facet.Name.Replace(" ", "")_@(deviceType)_@Model.ID" role="button" aria-expanded="@ariaExpanded" aria-controls="FacetGroup_@facet.Name.Replace(" ", "")_@(deviceType)_@Model.ID"> 406 <h2 class="opacity-85 m-0 flex-fill h6 my-2">@Translate("Custom:Facet." + facet.Name, facet.Name)</h2> 407 <div class="my-auto collapse-chevron-icon"></div> 408 </div> 409 <div class="collapse@(showClass)" id="FacetGroup_@facet.Name.Replace(" ", "")_@(deviceType)_@Model.ID"> 410 @foreach (FacetOptionViewModel facetOption in facet.Options.Where(o => o.Value == contextCurrency)) 411 { 412 @RenderOnSaleOption(facet, facetOption) 413 } 414 </div> 415 </div> 416 } 417 if (layout == "horizontal") 418 { 419 string hideSelector = groupCount < maxGroups ? "" : "d-none"; 420 int selectedFacetsInGroup = Context.Current.Request.GetBoolean(facet.QueryParameter) ? 1 : 0; 421 422 string label = selectedFacetsInGroup > 0 ? Translate("Custom:Facet." + facet.Name, facet.Name) + "<span class=\"badge bg-dark opacity-50 text-white ms-2\">" + selectedFacetsInGroup + "</span>" : Translate("Custom:Facet." + facet.Name, facet.Name); 423 // CUSTOM: removed dropdown css class to prevent hover dropdown 424 <div class="@hideSelector js-facets-selector"> 425 <button class="btn @(groupsTheme) dropdown-toggle" type="button" id="FacetGroup_@facet.Name.Replace(" ", "")_@(deviceType)_@Model.ID" data-bs-toggle="dropdown" aria-expanded="false"> 426 @label 427 </button> 428 <div class="dropdown-menu p-3 @(groupsTheme)" aria-labelledby="FacetGroup_@facet.Name.Replace(" ", "")_@(deviceType)_@Model.ID" style="min-width: 280px"> 429 @foreach (FacetOptionViewModel facetOption in facet.Options.Where(o => o.Value == contextCurrency)) 430 { 431 @RenderOnSaleOption(facet, facetOption) 432 } 433 </div> 434 </div> 435 } 436 437 groupCount++; 438 } 439 } 440 } 441 } 442 } 443 444 if ((groupCount > maxGroups) && layout == "horizontal") 445 { 446 <button type="button" class="btn @(groupsTheme)" onclick="this.closest('form').querySelectorAll('.js-facets-selector').forEach(function (selector) { selector.classList.remove('d-none'); }); this.classList.add('d-none');"><span class="icon-2">@ReadFile(iconPath + "sliders.svg")</span> @Translate("All filters")</button> 447 } 448 } 449 450 @helper RenderSorting(string deviceType) 451 { 452 var sortByPriceKey = $"ProductPrice|{Dynamicweb.Ecommerce.Common.Context.Currency.Code}|{Dynamicweb.Ecommerce.Common.Context.Country.Code2}|WithVAT"; 453 454 string sortBySelection = Dynamicweb.Context.Current.Request?.Form["SortBy"] ?? ""; 455 sortBySelection = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("SortBy")) ? Dynamicweb.Context.Current.Request.QueryString.Get("SortBy") : sortBySelection; 456 string sortNameSelectedRelevance = sortBySelection.ToLower() == "" || sortBySelection.ToLower() == "relevance" ? "checked" : ""; 457 string sortNameSelectedAZ = sortBySelection.ToLower() == "nameforsort" ? "checked" : ""; 458 string sortNameSelectedZA = sortBySelection.ToLower() == "-nameforsort" ? "checked" : ""; 459 string sortPriceLowSelected = sortBySelection.ToLower() == $"{sortByPriceKey.ToLower()}" ? "checked" : ""; 460 string sortPriceHighSelected = sortBySelection.ToLower() == $"-{sortByPriceKey.ToLower()}" ? "checked" : ""; 461 string sortNewSelected = sortBySelection.ToLower() == "-created" ? "checked" : ""; 462 string sortMostSoldSelected = sortBySelection.ToLower() == "-ordercount" ? "checked" : ""; 463 464 string anonymousUsersLimitations = Pageview.AreaSettings.GetRawValueString("AnonymousUsers", ""); 465 bool anonymousUser = Pageview.User == null; 466 bool hidePrice = anonymousUsersLimitations.Contains("price") && anonymousUser; 467 468 if (Model.Item.GetBoolean("SortByRelevance")) 469 { 470 <div class="form-check"> 471 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="" id="SortByRelevance_@(deviceType)_@Model.ID" @sortNameSelectedRelevance> 472 <label class="form-check-label" for="SortByRelevance_@(deviceType)_@Model.ID"> 473 @Translate("Relevance") 474 </label> 475 </div> 476 } 477 if (Model.Item.GetBoolean("SortByNameAZ")) 478 { 479 <div class="form-check"> 480 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="NameForSort" id="SortByNameAZ_@(deviceType)_@Model.ID" @sortNameSelectedAZ> 481 <label class="form-check-label" for="SortByNameAZ_@(deviceType)_@Model.ID"> 482 @Translate("Name (A-Z)") 483 </label> 484 </div> 485 } 486 if (Model.Item.GetBoolean("SortByNameZA")) 487 { 488 <div class="form-check"> 489 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="-NameForSort" id="SortByNameZA_@(deviceType)_@Model.ID" @sortNameSelectedZA> 490 <label class="form-check-label" for="SortByNameZA_@(deviceType)_@Model.ID"> 491 @Translate("Name (Z-A)") 492 </label> 493 </div> 494 } 495 if (Model.Item.GetBoolean("SortByNewest")) 496 { 497 <div class="form-check"> 498 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="-created" id="SortByNew_@(deviceType)_@Model.ID" @sortNewSelected> 499 <label class="form-check-label" for="SortByNew_@(deviceType)_@Model.ID"> 500 @Translate("Newest") 501 </label> 502 </div> 503 } 504 if (!hidePrice) 505 { 506 507 if (Model.Item.GetBoolean("SortByLowestPrice")) 508 { 509 <div class="form-check"> 510 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="@(sortByPriceKey)" id="SortByPriceLow_@(deviceType)_@Model.ID" @sortPriceLowSelected> 511 <label class="form-check-label" for="SortByPriceLow_@(deviceType)_@Model.ID"> 512 @Translate("Lowest price") 513 </label> 514 </div> 515 } 516 if (Model.Item.GetBoolean("SortByHighestPrice")) 517 { 518 <div class="form-check"> 519 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="-@(sortByPriceKey)" id="SortByPriceHigh_@(deviceType)_@Model.ID" @sortPriceHighSelected> 520 <label class="form-check-label" for="SortByPriceHigh_@(deviceType)_@Model.ID"> 521 @Translate("Highest price") 522 </label> 523 </div> 524 } 525 } 526 if (Model.Item.GetBoolean("SortByMostSold")) 527 { 528 <div class="form-check"> 529 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="-OrderCount" id="SortByMostSold_@(deviceType)_@Model.ID" @sortMostSoldSelected> 530 <label class="form-check-label" for="SortByMostSold_@(deviceType)_@Model.ID"> 531 @Translate("Most sold") 532 </label> 533 </div> 534 } 535 } 536 537 @helper RenderCheckboxOption(FacetViewModel facet, FacetOptionViewModel facetOption) 538 { 539 string facetLabel = HtmlEncoder.HtmlEncode(facetOption.Label); 540 string disabled = facetOption.Count <= 0 ? "disabled" : ""; 541 string selected = facetOption.Selected ? "checked" : ""; 542 543 if (facetLabel.ToLower() == "true") 544 { 545 facetLabel = Translate("Yes"); 546 facetOption.Label = facetLabel; 547 } 548 549 if (facetLabel.ToLower() == "false") 550 { 551 facetLabel = Translate("No"); 552 facetOption.Label = facetLabel; 553 } 554 555 <label class="form-check mt-1" @disabled> 556 <input type="checkbox" onclick="swift.ProductList.Update(event)" class="form-check-input" name="@facet.QueryParameter" value="[@facetOption.Value]" data-filter-value="@facetLabel" @selected> 557 <span class="form-check-label d-flex align-items-center"> 558 <span class="flex-fill">@Translate("Custom:FacetOption." + facetOption.Label, facetOption.Label) </span> 559 @if (facet.FacetType.ToLower() == "field") 560 { 561 <small class="opacity-85">@facetOption.Count</small> 562 } 563 </span> 564 </label> 565 } 566 567 @helper RenderColorOption(FacetViewModel facet, FacetOptionViewModel facetOption) 568 { 569 string facetLabel = HtmlEncoder.HtmlEncode(facetOption.Label); 570 string disabled = facetOption.Count <= 0 ? "disabled" : ""; 571 string selected = facetOption.Selected ? "checked" : ""; 572 573 string image = facetOption.Value; 574 string colorCode = facetOption.Value; 575 576 var variantOption = Dynamicweb.Ecommerce.Services.VariantOptions.GetVariantOption(facetOption.Value.ToString()); 577 if (variantOption != null) 578 { 579 image = variantOption.LargeImage; 580 colorCode = variantOption.Color; 581 } 582 583 <div class="colorbox"> 584 <label> 585 <input type="checkbox" onclick="swift.ProductList.Update(event)" class="@disabled @selected" name="@facet.QueryParameter" value="[@facetOption.Value]" data-filter-value="@facetLabel" @selected title="@HtmlEncoder.HtmlAttributeEncode(facetOption.Label)"> 586 @if (colorCode.Contains("#")) 587 { 588 <span class="colorbox-background" style="background-color: @colorCode"></span> 589 <span class="visually-hidden">@Translate("Custom:FacetOption." + facetOption.Label, facetOption.Label)</span> 590 } 591 else 592 { 593 <img class="colorbox-background" src="/Admin/Public/GetImage.ashx?width=25&height=25&image=@image"> 594 <span class="visually-hidden">@Translate("Custom:FacetOption." + facetOption.Label, facetOption.Label)</span> 595 } 596 </label> 597 </div> 598 } 599 600 @helper RenderOnSaleOption(FacetViewModel facet, FacetOptionViewModel facetOption) 601 { 602 facetOption.Label = Translate("Custom:Facet.Label.OnSale", "Yes"); 603 facetOption.Value = "True"; 604 605 string facetLabel = HtmlEncoder.HtmlEncode(facetOption.Label); 606 string selected = Context.Current.Request.GetBoolean(facet.QueryParameter) ? "checked" : ""; 607 608 <label class="form-check mt-1"> 609 <input type="checkbox" onclick="swift.ProductList.Update(event)" class="form-check-input" name="@facet.QueryParameter" value="@facetOption.Value" data-filter-value="@facetLabel" @selected> 610 <span class="form-check-label d-flex align-items-center"> 611 <span class="flex-fill">@facetOption.Label </span> 612 @if (facet.FacetType.ToLower() == "field") 613 { 614 <small class="opacity-85">@facetOption.Count</small> 615 } 616 </span> 617 </label> 618 } 619

499,95 kr. OutOfStock

499,95 kr. OutOfStock

499,95 kr. OutOfStock

499,95 kr. OutOfStock

499,95 kr. OutOfStock

799,95 kr. OutOfStock

799,95 kr. OutOfStock

499,95 kr. OutOfStock

499,95 kr. OutOfStock

499,95 kr. OutOfStock
0.5 L
0.5 L

0.5 L

199,95 kr. OutOfStock
0.5 L
0.5 L

0.5 L

199,95 kr. OutOfStock
0.5 L
0.5 L

0.5 L

199,95 kr. OutOfStock

0,00 kr. OutOfStock

0,00 kr. OutOfStock

0,00 kr. OutOfStock
1248 ud af 2686 produkter
Hent flere produkter