Bordtennisbord
0 products
We did not find anything matching your search result
Error executing template "Designs/Swift/Paragraph/Swift_MenuRelatedContent.cshtml" System.ArgumentException: An item with the same key has already been added. Key: 2nd_ecom_121 at System.Collections.Generic.Dictionary`2.TryInsert(TKey key, TValue value, InsertionBehavior behavior) at Dynamicweb.Ecommerce.Products.GroupService.GetSubgroups(Group group, Boolean showUnTranslated) at Dynamicweb.Ecommerce.Frontend.Navigation.GroupNavigationTreeNodeProvider.GetNodes(NavigationContext context, NavigationSettings settings, NavigationTreeNode parent) at System.Linq.Enumerable.SelectManySingleSelectorIterator`2.MoveNext() at System.Linq.Enumerable.SelectIterator[TSource,TResult](IEnumerable`1 source, Func`3 selector)+MoveNext() at CompiledRazorTemplates.Dynamic.RazorEngine_86605f67853f4499ad7e0408544bc05e.ExecuteAsync() at RazorEngine.Templating.TemplateBase.Run(ExecuteContext context, TextWriter reader) at RazorEngine.Templating.RazorEngineCore.RunTemplate(ICompiledTemplate template, TextWriter writer, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineService.Run(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.DynamicWrapperService.Run(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineServiceExtensions.Run(IRazorEngineService service, String name, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass23_0.<Run>b__0(TextWriter writer) at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter) at RazorEngine.Templating.RazorEngineServiceExtensions.Run(IRazorEngineService service, String name, Type modelType, Object model, DynamicViewBag viewBag) 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.Frontend.Navigation 3 @using Dynamicweb.Ecommerce.ProductCatalog 4 5 @functions { 6 7 NavigationTreeViewModel GetNavigationTreeFromPageId(int pageId = 0, bool includeFolders = false, int startLevel = 1, int stopLevel = 9) 8 { 9 var navigationSettings = new NavigationSettings() 10 { 11 StartLevel = startLevel, 12 StopLevel = stopLevel, 13 RootPageId = pageId, 14 IncludeFoldersAndHidden = includeFolders, 15 ExpandMode = ExpandMode.All, 16 }; 17 18 return Navigation.GetNavigationViewModel(navigationSettings); 19 } 20 21 string GetGroupFieldValue(string fieldSystemName, NavigationTreeNodeViewModel node) 22 { 23 ProductGroupViewModel productGroup = node.GetProductGroup(); 24 string fieldValue = string.Empty; 25 IList<FieldValueViewModel> groupFields = productGroup.GroupFields != null ? productGroup.GroupFields : null; 26 if (groupFields != null) 27 { 28 foreach (FieldValueViewModel field in groupFields) 29 { 30 31 if (field.SystemName == fieldSystemName) 32 { 33 fieldValue = field != null ? field.Value.ToString() : string.Empty; 34 } 35 } 36 } 37 38 return fieldValue; 39 } 40 41 bool NavigationTreeHasChildren(NavigationTreeNodeViewModel rootNode) 42 { 43 foreach (var subNode in rootNode.Nodes) 44 { 45 if (subNode.Nodes.Any()) 46 { 47 return true; 48 } 49 } 50 return false; 51 } 52 53 int GetPageIdFromLink(string pageLink) 54 { 55 return !string.IsNullOrEmpty(pageLink) ? Convert.ToInt32(pageLink.Substring(pageLink.LastIndexOf('=') + 1)) : 0; 56 57 } 58 59 string GetSubmenuType(NavigationTreeNodeViewModel rootNode) 60 { 61 string submenuType = string.Empty; 62 var page = Dynamicweb.Content.Services.Pages.GetPage(rootNode.PageId); 63 var pageType = !string.IsNullOrEmpty(page.ItemType) ? page.ItemType : "Swift_Page"; 64 if (page.PropertyItem is object && page.PropertyItem.TryGetValue("SubmenuType", out object submenuTypeValue)) 65 { 66 submenuType = Dynamicweb.Core.Converter.ToString(submenuTypeValue); 67 } 68 return submenuType; 69 } 70 71 bool IsMegaMenu(NavigationTreeNodeViewModel rootNode, string submenuType) 72 { 73 switch (submenuType) 74 { 75 case "dropdown": 76 return false; 77 case "auto": 78 return NavigationTreeHasChildren(rootNode); 79 default: 80 return true; 81 } 82 } 83 84 string isActive(NavigationTreeNodeViewModel node) 85 { 86 return node.IsActive ? "aria-current='page'" : string.Empty; 87 } 88 89 string isActiveDropdown(NavigationTreeNodeViewModel node) 90 { 91 return node.IsActive ? "class=\"active\"" : string.Empty; 92 } 93 94 bool GetRelatedContentStructure(IEnumerable<NavigationTreeNodeViewModel> relatedContentNodes) 95 { 96 bool relatedContentIsNested = false; 97 98 foreach (var relatedContentNode in relatedContentNodes.Where(node => node.ShowInMenu)) 99 { 100 if (relatedContentNode.Nodes.Any()) 101 { 102 return relatedContentIsNested = true; 103 } 104 } 105 106 return relatedContentIsNested; 107 } 108 109 } 110 111 @{ 112 // Page settings 113 int navigationRootPageId = !string.IsNullOrEmpty(Model.Item.GetString("NavigationRoot")) ? Model.Item.GetLink("NavigationRoot").PageId : 0; 114 var rootNavigation = GetNavigationTreeFromPageId(navigationRootPageId); 115 int maxEndNodes = Model.Item.GetInt32("MaxEndNodes"); 116 string maxEndNodesText = Model.Item.GetString("ShowAllLinkLabel"); 117 118 //CSS Settings 119 string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("Theme")) ? "theme " + Model.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : ""; 120 string spacing = Model.Item.GetRawValueString("Spacing", "compact"); 121 string headerSpacing = spacing == "wide" ? "mb-2" : "mb-1"; 122 string itemSpacing = spacing == "normal" ? "pb-2" : spacing == "wide" ? "pb-3" : "pb-1"; 123 124 string headerAlignment = Model.Item.GetRawValueString("HeaderAlignment", "start"); 125 headerAlignment = $"justify-content-{headerAlignment} text-{headerAlignment}"; 126 127 string textAlignment = Model.Item.GetRawValueString("TextAlignment", "start"); 128 textAlignment = $"text-{textAlignment}"; 129 130 string headerLinkAnimation = Model.Item.GetRawValueString("HeaderLinkAnimation", "left"); 131 headerLinkAnimation = headerLinkAnimation == "none" ? "text-decoration-underline-hover" : $"hover-underline-animation-{headerLinkAnimation}"; 132 133 string menuAlignment = Model.Item.GetRawValueString("MenuAlignment", "start"); 134 menuAlignment = $"justify-content-{menuAlignment}"; 135 136 string clickable = "text-decoration-underline-hover text-decoration-accent-hover"; 137 138 } 139 140 <div class="nav-wrapper megamenu-wrapper item_@Model.Item.SystemName.ToLower()" id="Menu_@Model.ID"> 141 <nav class="d-flex gap-2 @headerAlignment"> 142 @* Fix to get CMS pages sorted/rendered after Ecom groups *@ 143 @* foreach (var rootNode in rootNavigation.Nodes.Where(node => node.ShowInMenu))*@ 144 @foreach (var rootNode in rootNavigation.Nodes.Where(node => node.ShowInMenu).OrderBy(n => n.PageId.ToString().Length)) 145 { 146 string relatedContentNavigationRoot = GetGroupFieldValue("ProductGroupRelatedContent", rootNode); 147 int relatedContentPageId = !string.IsNullOrEmpty(relatedContentNavigationRoot) ? GetPageIdFromLink(relatedContentNavigationRoot) : 0; 148 var relatedContentNodes = GetNavigationTreeFromPageId(relatedContentPageId, true).Nodes; 149 bool hasRelatedContent = relatedContentNodes.Any() && relatedContentPageId != 0; 150 bool relatedContentIsNested = hasRelatedContent ? GetRelatedContentStructure(relatedContentNodes) : false; 151 bool nodesExist = rootNode.Nodes.Any() || hasRelatedContent; 152 string relatedContentGap = spacing == "wide" ? "gap-4" : "gap-3"; 153 relatedContentGap = relatedContentIsNested ? relatedContentGap : string.Empty; 154 string submenuType = GetSubmenuType(rootNode); 155 bool isMegaMenu = IsMegaMenu(rootNode, submenuType); 156 string submenuTypeCss = isMegaMenu ? "position-static" : string.Empty; 157 string dropdown = nodesExist ? "dropdown" : string.Empty; 158 string dropdownAttributes = nodesExist ? "role=\"button\" data-bs-toggle=\"dropdown\" data-bs-offset=\"0,0\" aria-expanded=\"false\"" : string.Empty; 159 160 <div class="nav-item @dropdown @submenuTypeCss"> 161 @if (rootNode.IsClickable) 162 { 163 164 <a class="nav-link p-2 fw-bold @headerLinkAnimation" href="@rootNode.Link" @dropdownAttributes @isActive(rootNode)> 165 <span class="text-wrap-nowrap">@rootNode.Name</span> 166 </a> 167 } 168 else 169 { 170 <span class="nav-link p-2 fw-bold @headerLinkAnimation" @dropdownAttributes> 171 <span class="text-wrap-nowrap">@rootNode.Name</span> 172 </span> 173 } 174 175 @if (nodesExist) 176 { 177 if (isMegaMenu) 178 { 179 <div class="dropdown-menu border-0 megamenu @theme"> 180 <div class="container-xl overflow-y-auto"> 181 <div class="d-flex py-2 gap-3"> 182 183 @if (hasRelatedContent) 184 { 185 <div class="col-auto megamenu-col d-flex flex-column me-4 pe-4 border-end @relatedContentGap @textAlignment @menuAlignment"> 186 @foreach (var relatedContentNode in relatedContentNodes.Where(node => node.ShowInMenu)) 187 { 188 <div> 189 @if (relatedContentNode.IsClickable) 190 { 191 <a class="nav-link px-0 lh-1 @itemSpacing @headerSpacing @clickable" href="@relatedContentNode.Link" @isActive(relatedContentNode)> 192 <strong>@relatedContentNode.Name</strong> 193 </a> 194 } 195 else 196 { 197 <div class="nav-link px-0 lh-1 pe-none @itemSpacing @headerSpacing" href="@relatedContentNode.Link" @isActive(relatedContentNode)> 198 <strong>@relatedContentNode.Name</strong> 199 </div> 200 } 201 202 @foreach (var relatedContentSubNode in relatedContentNode.Nodes.Where(node => node.ShowInMenu)) 203 { 204 if (relatedContentSubNode.IsClickable) 205 { 206 <a class="nav-link px-0 lh-1 @itemSpacing @clickable" href="@relatedContentSubNode.Link" @isActive(relatedContentSubNode)> 207 <span>@relatedContentSubNode.Name</span> 208 </a> 209 } 210 else 211 { 212 <div class="nav-link px-0 lh-1 pe-none @itemSpacing" href="@relatedContentSubNode.Link"> 213 <span>@relatedContentSubNode.Name</span> 214 </div> 215 } 216 } 217 </div> 218 } 219 </div> 220 221 } 222 223 <div class="col d-flex flex-wrap gap-3 @menuAlignment @textAlignment"> 224 225 @foreach (var subNode in rootNode.Nodes.Where(node => node.ShowInMenu)) 226 { 227 <div class="col-auto megamenu-col @textAlignment"> 228 @if (subNode.IsClickable) 229 { 230 <a class="nav-link px-0 lh-1 @itemSpacing @headerSpacing @clickable" href="@subNode.Link" @isActive(subNode)> 231 <strong>@subNode.Name</strong> 232 </a> 233 } 234 else 235 { 236 <div class="nav-link px-0 lh-1 pe-none @itemSpacing @headerSpacing"> 237 <strong>@subNode.Name</strong> 238 </div> 239 } 240 241 @foreach (var (endNode, index) in subNode.Nodes.Select((node, i) => (node, i))) 242 { 243 if (index < maxEndNodes && endNode.ShowInMenu) 244 { 245 if (endNode.IsClickable) 246 { 247 <a class="nav-link px-0 lh-1 @itemSpacing @clickable" href="@endNode.Link" @isActive(endNode)> 248 @endNode.Name 249 </a> 250 } 251 else 252 { 253 <div class="nav-link px-0 lh-1 pe-none @itemSpacing"> 254 @endNode.Name 255 </div> 256 } 257 258 continue; 259 } 260 261 if (!string.IsNullOrWhiteSpace(maxEndNodesText)) 262 { 263 <a class="nav-link px-0 text-decoration-underline mt-1 lh-1 @itemSpacing" href="@subNode.Link"> 264 @Translate(maxEndNodesText) 265 </a> 266 } 267 268 break; 269 } 270 </div> 271 272 } 273 </div> 274 </div> 275 </div> 276 </div> 277 } 278 else 279 { 280 <ul class="dropdown-menu dropdown-menu-shadow @theme @textAlignment"> 281 282 @if (hasRelatedContent) 283 { 284 foreach (var relatedContentNode in relatedContentNodes) 285 { 286 if (relatedContentNode.IsClickable) 287 { 288 <li @isActiveDropdown(relatedContentNode)> 289 <a class="dropdown-item py-2 lh-1 @clickable" href="@relatedContentNode.Link" @isActive(relatedContentNode)> 290 <strong>@relatedContentNode.Name</strong> 291 </a> 292 </li> 293 } 294 else 295 { 296 <li> 297 <span class="dropdown-item py-2 lh-1 pe-none"> 298 <strong>@relatedContentNode.Name</strong> 299 </span> 300 </li> 301 302 } 303 304 foreach (var relatedContentSubNode in relatedContentNode.Nodes.Where(node => node.ShowInMenu)) 305 { 306 if (relatedContentSubNode.IsClickable) 307 { 308 <li @isActiveDropdown(relatedContentSubNode)> 309 <a class="dropdown-item py-2 lh-1 @clickable" href="@relatedContentSubNode.Link" @isActive(relatedContentSubNode)> 310 <strong>@relatedContentSubNode.Name</strong> 311 </a> 312 </li> 313 } 314 else 315 { 316 <li> 317 <span class="dropdown-item py-2 lh-1 pe-none"> 318 <strong>@relatedContentSubNode.Name</strong> 319 </span> 320 </li> 321 } 322 } 323 } 324 325 <li class="dropdown-divider"></li> 326 } 327 328 @foreach (var subNode in rootNode.Nodes.Where(node => node.ShowInMenu)) 329 { 330 if (subNode.IsClickable) 331 { 332 333 <li @isActiveDropdown(subNode)> 334 <a class="dropdown-item py-2 lh-1 @clickable" href="@subNode.Link" @isActive(subNode)> 335 <strong>@subNode.Name</strong> 336 </a> 337 </li> 338 } 339 else 340 { 341 <li> 342 <span class="dropdown-item py-2 lh-1 pe-none"> 343 <strong>@subNode.Name</strong> 344 </span> 345 </li> 346 } 347 } 348 </ul> 349 } 350 } 351 </div> 352 } 353 </nav> 354 </div> 355 <script type="module"> 356 swift.Menu.setMenuContentOffset('Menu_@Model.ID'); 357 </script> 358