Favoritliste

Opret nye favoritgrupper og tilføj produkter til din favoritliste.

Error executing template "Designs/Swift/eCom/CustomerExperienceCenter/Favorites/FavoriteLists_Custom.cshtml"
System.ArgumentNullException: Value cannot be null.
Parameter name: source
   at System.Linq.Enumerable.Where[TSource](IEnumerable`1 source, Func`2 predicate)
   at CompiledRazorTemplates.Dynamic.RazorEngine_34368f908ed84d45b42ca9f0734d2fcf.<RenderContent>b__0_0(TextWriter __razor_helper_writer) in D:\dynamicweb.net\Solutions\twodayco3\simas.cloud.dynamicweb-cms.com\Files\Templates\Designs\Swift\eCom\CustomerExperienceCenter\Favorites\FavoriteLists_Custom.cshtml:line 57
   at CompiledRazorTemplates.Dynamic.RazorEngine_34368f908ed84d45b42ca9f0734d2fcf.Execute() in D:\dynamicweb.net\Solutions\twodayco3\simas.cloud.dynamicweb-cms.com\Files\Templates\Designs\Swift\eCom\CustomerExperienceCenter\Favorites\FavoriteLists_Custom.cshtml:line 40
   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 ViewModelTemplate<FavoriteListListViewModel> 2 @using Dynamicweb.Rendering 3 @using Dynamicweb.Ecommerce.Frontend 4 @using System.Linq 5 @using Co3.Simas.Custom.Constants 6 @using Co3.Simas.Custom.Extensions 7 @using Dynamicweb.Ecommerce.CustomerExperienceCenter.Favorites 8 @using ProductViewModel = Dynamicweb.Ecommerce.ProductCatalog.ProductViewModel 9 @{ 10 string themeRaw = Pageview.CurrentParagraph.Item["Theme"]?.ToString(); 11 string theme = !string.IsNullOrEmpty(themeRaw) ? " h-100 theme " + themeRaw.Replace(" ", "").Trim().ToLower() : ""; 12 bool sharedList = (Dynamicweb.Frontend.PageView.Current().CurrentParagraph.ModuleProperties.GetValue("RetrieveListBasedOn") == "UseCustomerNumber"); 13 } 14 @if (sharedList) 15 { 16 @SnippetStart("FavoriteListsShared") 17 if (theme != "") 18 { 19 <div class="@(theme)"> 20 @RenderContent() 21 </div> 22 } 23 else 24 { 25 @RenderContent() 26 } 27 28 @SnippetEnd("FavoriteListsShared") 29 } 30 else 31 { 32 if (theme != "") 33 { 34 <div class="@(theme)"> 35 @RenderContent() 36 </div> 37 } 38 else 39 { 40 @RenderContent() 41 } 42 43 <div class="mt-6"> 44 @RenderSnippet("FavoriteListsShared") 45 </div> 46 } 47 48 49 @helper RenderContent() 50 { 51 bool sharedList = (Dynamicweb.Frontend.PageView.Current().CurrentParagraph.ModuleProperties.GetValue("RetrieveListBasedOn") == "UseCustomerNumber"); 52 string title = Pageview.CurrentParagraph.Item["Title"]?.ToString(); 53 string listPageLink = Pageview.CurrentParagraph.Item["ProductListPage"] != null ? Pageview.CurrentParagraph.Item["ProductListPage"].ToString() : ""; 54 string currentPageUrl = "/Default.aspx?ID=" + Pageview.Page.ID; 55 string url = "/Default.aspx?ID=" + (GetPageIdByNavigationTag("CartService")); 56 57 IEnumerable<IGrouping<string, FavoriteListViewModel>> listGroups = Model.FavoriteLists.Where(fl => fl.ShowInList(sharedList)).OrderBy(fl => string.IsNullOrEmpty(fl.Category()) == false ? fl.Category() : "zz").ThenBy(fl => fl.Name).GroupBy(fl => fl.Category()); 58 59 int listsCount = listGroups.Count(); 60 int pageSize = Model.PageSize; 61 62 63 <header class="d-flex flex-wrap align-items-center"> 64 <h4 class="m-0 flex-fill mb-2"> 65 <small>@title (@listsCount)</small> 66 </h4> 67 @if (listsCount > 0) 68 { 69 <button type="button" class="btn btn-link p-0 border-0" data-bs-toggle="modal" data-list-isshared="@sharedList" data-bs-target="#createFavoriteListModal">+ @Translate("Add new favorite list")</button> 70 } 71 </header> 72 73 if (listsCount < 1) 74 { 75 <div class="grid"> 76 <div class="g-col-12 g-start-lg-3 g-col-lg-8 d-flex flex-column gap-3 text-center py-3"> 77 <h2 class="h5 m-0">@Translate("It looks like you do not have any favorites yet")</h2> 78 <p class="m-0">@Translate("Save and arrange the best things here until you are ready for them")</p> 79 80 <div class="d-flex flex-column flex-sm-row gap-3 justify-content-center"> 81 <button type="button" class="btn btn-link p-0 border-0" data-bs-toggle="modal" data-list-isshared="@sharedList" data-bs-target="#createFavoriteListModal">+ @Translate("Add new favorite list")</button> 82 </div> 83 </div> 84 </div> 85 } 86 else 87 { 88 <div class="mb-4"> 89 @{ 90 int accordionItemLoopCounter = 0; 91 } 92 @foreach (IGrouping<string, FavoriteListViewModel> categoryGroup in listGroups) 93 { 94 bool isFirstItemInLoop = accordionItemLoopCounter == 0; 95 bool expandFirstAccordionItem = false; //isFirstItemInLoop == true; 96 string accordionItemId = Guid.NewGuid().ToHtmlId(); 97 string groupName = string.IsNullOrEmpty(categoryGroup.Key) == false ? categoryGroup.Key : Translate("Ingen kategori"); 98 string buttonAriaExpanded = expandFirstAccordionItem == true ? "true" : "false"; 99 string buttonClassState = expandFirstAccordionItem == true ? "" : "collapsed"; 100 string collapseClassState = expandFirstAccordionItem == true ? "show" : "collapse"; 101 102 <div class="accordion mb-2"> 103 <div class="accordion-item"> 104 <h5 class="accordion-header"> 105 <button class="fw-bold fs-5 accordion-button @buttonClassState" type="button" data-bs-toggle="collapse" data-bs-target="#@accordionItemId" aria-expanded="@buttonAriaExpanded" aria-controls="@accordionItemId">@groupName</button> 106 </h5> 107 <div id="@accordionItemId" class="accordion-collapse @collapseClassState"> 108 <div class="accordion-body"> 109 <ul class="list-unstyled m-0"> 110 @foreach (FavoriteListViewModel theList in categoryGroup) 111 { 112 string favoriteListLink = listPageLink + "&amp;FavoriteListId=" + theList.Id; 113 string listName = !string.IsNullOrEmpty(theList.Name) ? theList.Name : Translate("Favorites"); 114 string location = theList.Location(); 115 string isShared = theList.IsShared().ToString().ToLowerInvariant(); 116 string description = theList.Description(); 117 string category = theList.Category(); 118 string machine = theList.Machine(); 119 <li class="mb-4"> 120 <p class="d-flex align-items-center m-0"> 121 <a href="@favoriteListLink" class="text-decoration-none"> 122 <strong>@listName</strong> 123 </a> 124 @if (theList.IsShared() == true) 125 { 126 string isSharedByUserName = theList.GetFavoriteList().IsShareByUserName(); 127 128 if (isSharedByUserName == "YOU" || isSharedByUserName == "UNKNOWN") 129 { 130 isSharedByUserName = Translate("SharedBy:" + isSharedByUserName, isSharedByUserName); 131 } 132 133 <small class="badge bg-info ms-3">@Translate("Shared by") @isSharedByUserName</small> 134 } 135 @if (theList.IsEditableForCurrentUser()) 136 { 137 <span class="mx-3"> &middot; </span> 138 139 <button type="button" 140 class="btn btn-link btn-sm p-0 me-2 renameFavoriteListModal" 141 data-bs-toggle="modal" 142 data-bs-target="#renameFavoriteListModal" 143 data-list-id="@theList.Id" 144 data-list-isshared="@isShared" 145 data-list-location="@location" 146 data-list-description="@description" 147 data-list-category="@category" 148 data-list-machine="@machine" 149 data-list-isshared="@sharedList" 150 data-list-name="@listName"> 151 @Translate("Rename") 152 </button> 153 <button type="button" 154 class="btn btn-link btn-sm p-0 mx-1 px-1 deleteFavoriteNameButton" 155 data-bs-toggle="modal" 156 data-bs-target="#deleteFavoriteListModal" 157 data-list-id="@theList.Id" 158 data-list-name="@listName"> 159 @Translate("Delete") 160 </button> 161 } 162 </p> 163 <p class="opacity-75 mb-1">@description</p> 164 <form method="post" action="@url" class="d-flex align-items-center"> 165 <input type="hidden" name="CartCmd" id="CartCmd" value="addMulti"> 166 @{ 167 int listProductLoopCounter = 1; 168 } 169 @foreach (FavoriteProduct favoriteProduct in theList.GetFavoriteList().Products()) 170 { 171 string quantityName = $"Quantity{listProductLoopCounter}"; 172 string productIdName = $"ProductID{listProductLoopCounter}"; 173 string locationName = $"EcomOrderLineFieldInput_{OrderLineFieldIds.Location}{listProductLoopCounter}"; 174 string machineName = $"EcomOrderLineFieldInput_{OrderLineFieldIds.Machine}{listProductLoopCounter}"; 175 string categoryName = $"EcomOrderLineFieldInput_{OrderLineFieldIds.Category}{listProductLoopCounter}"; 176 string listProductLoopCounterName = $"ProductLoopCounter{listProductLoopCounter}"; 177 178 <input type="hidden" name="@quantityName" value="@Math.Max(1, (int)favoriteProduct.Quantity)"> 179 <input type="hidden" name="@productIdName" value="@favoriteProduct.ProductId"> 180 <input type="hidden" name="@locationName" value="@location"> 181 <input type="hidden" name="@machineName" value="@machine"> 182 <input type="hidden" name="@categoryName" value="@category"> 183 <input type="hidden" name="@listProductLoopCounterName" value="@listProductLoopCounter"> 184 listProductLoopCounter += 1; 185 } 186 <button type="submit" class="btn btn-link btn-sm me-2 p-0">@Translate("Add all products in this list to your cart")</button> 187 </form> 188 </li> 189 } 190 </ul> 191 </div> 192 @{ int categoryProductLoopCounter = 1; } 193 <form method="post" action="@url" class="d-flex align-items-center text-center border-top"> 194 <input type="hidden" name="CartCmd" id="CartCmd" value="addMulti"> 195 @foreach (FavoriteListViewModel theList in categoryGroup) 196 { 197 string location = theList.Location(); 198 string machine = theList.Machine(); 199 string category = theList.Category(); 200 foreach (FavoriteProduct favoriteProduct in theList.GetFavoriteList().Products()) 201 { 202 string quantityName = $"Quantity{categoryProductLoopCounter}"; 203 string productIdName = $"ProductID{categoryProductLoopCounter}"; 204 string locationName = $"EcomOrderLineFieldInput_{OrderLineFieldIds.Location}{categoryProductLoopCounter}"; 205 string machineName = $"EcomOrderLineFieldInput_{OrderLineFieldIds.Machine}{categoryProductLoopCounter}"; 206 string categoryName = $"EcomOrderLineFieldInput_{OrderLineFieldIds.Category}{categoryProductLoopCounter}"; 207 string categoryProductLoopCounterName = $"ProductLoopCounter{categoryProductLoopCounter}"; 208 <input type="hidden" name="@quantityName" value="@Math.Max(1, (int)favoriteProduct.Quantity)"> 209 <input type="hidden" name="@productIdName" value="@favoriteProduct.ProductId"> 210 <input type="hidden" name="@locationName" value="@location"> 211 <input type="hidden" name="@machineName" value="@machine"> 212 <input type="hidden" name="@categoryName" value="@category"> 213 <input type="hidden" name="@categoryProductLoopCounterName" value="@categoryProductLoopCounter"> 214 categoryProductLoopCounter += 1; 215 } 216 } 217 <button type="submit" class="btn btn-link btn-sm mx-auto">@Translate("Add all products in this category to your cart")</button> 218 </form> 219 </div> 220 </div> 221 </div> 222 accordionItemLoopCounter++; 223 } 224 </div> 225 } 226 227 if (listsCount > pageSize) 228 { 229 <div class="p-3"> 230 @RenderPagination(currentPageUrl, Model.PageCount, Model.CurrentPage, Model.PageSize) 231 </div> 232 } 233 } 234 235 236 @if (!sharedList) 237 { 238 <div class="modal fade" tabindex="-1" id="createFavoriteListModal"> 239 <div class="modal-dialog modal-dialog-centered"> 240 <div class="modal-content"> 241 <div class="modal-header"> 242 <h5 class="modal-title">@Translate("Create favorite list")</h5> 243 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> 244 </div> 245 <div class="modal-body d-flex flex-column gap-3"> 246 <div hidden> 247 <label for="createFavoriteListInputName" class="form-label">@Translate("Name the favorite list")</label> 248 <input type="text" readonly="readonly" class="form-control" id="createFavoriteListInputName" placeholder="@Translate("Name")"> 249 </div> 250 <div> 251 <label for="createFavoriteListInputCategory" class="form-label">@Translate("Category")</label> 252 <input type="text" class="form-control" id="createFavoriteListInputCategory" placeholder="@Translate("Category - placeholder")"/> 253 </div> 254 <div> 255 <label for="createFavoriteListInputLocation" class="form-label">@Translate("Location")</label> 256 <input type="text" class="form-control" id="createFavoriteListInputLocation" placeholder="@Translate("Location - placeholder")"> 257 </div> 258 <div> 259 <label for="createFavoriteListInputMachine" class="form-label">@Translate("Machine")</label> 260 <input type="text" class="form-control" id="createFavoriteListInputMachine" placeholder="@Translate("Machine - placeholder")"> 261 </div> 262 263 <div> 264 <label for="createFavoriteListInputDescription" class="form-label">@Translate("Description")</label> 265 <textarea class="form-control" id="createFavoriteListInputDescription" placeholder="@Translate("Description - placeholder")"></textarea> 266 </div> 267 268 <div class="alert alert-danger m-0 d-none" role="alert" id="createFavoriteListError">@Translate("A Favorite List must have a name")</div> 269 </div> 270 <div class="modal-footer"> 271 <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">@Translate("Cancel")</button> 272 <button type="button" class="btn btn-primary" id="createFavoriteListButton">@Translate("Create list")</button> 273 </div> 274 </div> 275 </div> 276 </div> 277 278 <div class="modal fade" tabindex="-1" id="renameFavoriteListModal"> 279 <div class="modal-dialog modal-dialog-centered"> 280 <div class="modal-content"> 281 <div class="modal-header"> 282 <h5 class="modal-title">@Translate("Rename favorite list")</h5> 283 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> 284 </div> 285 <div class="modal-body"> 286 <div> 287 <label for="renameFavoriteListInputName" class="form-label">@Translate("Rename favorite list"):</label> 288 <input type="text" readonly="readonly" class="form-control" id="renameFavoriteListInputName" placeholder="@Translate("Name")"> 289 </div> 290 <div> 291 <label for="renameFavoriteListInputCategory" class="form-label">@Translate("Category")</label> 292 <input type="text" class="form-control" id="renameFavoriteListInputCategory" placeholder="@Translate("Category - placeholder")"/> 293 </div> 294 <div> 295 <label for="renameFavoriteListInputLocation" class="form-label">@Translate("Location")</label> 296 <input type="text" class="form-control" id="renameFavoriteListInputLocation" placeholder="@Translate("Location - placeholder")"/> 297 </div> 298 <div> 299 <label for="renameFavoriteListInputMachine" class="form-label">@Translate("Machine")</label> 300 <input type="text" class="form-control" id="renameFavoriteListInputMachine" placeholder="@Translate("Machine - placeholder")"/> 301 </div> 302 <div> 303 <label for="renameFavoriteListInputDescription" class="form-label">@Translate("Description")</label> 304 <textarea class="form-control" id="renameFavoriteListInputDescription" placeholder="@Translate("Description - placeholder")"></textarea> 305 </div> 306 <div class="form-check"> 307 <input class="form-check-input" type="checkbox" value="true" id="renameFavoriteListInputIsShared"> 308 <label class="form-check-label" for="renameFavoriteListInputIsShared"> 309 @Translate("IsShared - placeholder") 310 </label> 311 </div> 312 <div class="alert alert-danger m-0 d-none" role="alert" id="renameFavoriteListError">@Translate("A Favorite List must have a name")</div> 313 </div> 314 <div class="modal-footer"> 315 <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">@Translate("Cancel")</button> 316 <button type="button" class="btn btn-primary" id="renameFavoriteListButton">@Translate("Update list")</button> 317 </div> 318 </div> 319 </div> 320 </div> 321 322 <div class="modal fade" tabindex="-1" id="deleteFavoriteListModal"> 323 <div class="modal-dialog modal-dialog-centered"> 324 <div class="modal-content"> 325 <div class="modal-header"> 326 <h5 class="modal-title">@Translate("Delete favorite list")</h5> 327 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> 328 </div> 329 <div class="modal-body"> 330 <p>@Translate("You are about to delete"): <strong id="deleteFavoriteName"></strong>.</p> 331 <p>@Translate("Are you sure you want to delete it?")</p> 332 </div> 333 <div class="modal-footer"> 334 <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">@Translate("Cancel")</button> 335 <button type="button" class="btn btn-primary" id="deleteFavoriteListButton">@Translate("Delete list")</button> 336 </div> 337 </div> 338 </div> 339 </div> 340 341 <script> 342 let userId = @Pageview.User.ID; 343 let renameFavoriteListModal = document.querySelector("#renameFavoriteListModal") 344 let deleteFavoriteListModal = document.querySelector("#deleteFavoriteListModal") 345 let createFavoriteListModal = document.querySelector("#createFavoriteListModal") 346 347 renameFavoriteListModal.addEventListener('show.bs.modal', function (event) { 348 let button = event.relatedTarget 349 let renameIsShared = button.getAttribute('data-list-isshared') === 'true' ? true : false; 350 let renameFavoriteListId = button.getAttribute('data-list-id'); 351 let renameFromName = button.getAttribute('data-list-name') 352 let renameFromLocation = button.getAttribute('data-list-location') 353 let renameFromDescription = button.getAttribute('data-list-description') 354 let renameFromCategory = button.getAttribute('data-list-category') 355 let renameFromMachine = button.getAttribute('data-list-machine') 356 let renameFavoriteListInputName = document.getElementById('renameFavoriteListInputName'); 357 let renameFavoriteListInputLocation = document.getElementById('renameFavoriteListInputLocation'); 358 let renameFavoriteListInputDescription = document.getElementById('renameFavoriteListInputDescription'); 359 let renameFavoriteListInputCategory = document.getElementById('renameFavoriteListInputCategory'); 360 let renameFavoriteListInputMachine = document.getElementById('renameFavoriteListInputMachine'); 361 let renameFavoriteListInputIsShared = document.getElementById('renameFavoriteListInputIsShared'); 362 363 renameFavoriteListInputName.value = renameFromName; 364 renameFavoriteListInputLocation.value = renameFromLocation; 365 renameFavoriteListInputDescription.value = renameFromDescription; 366 renameFavoriteListInputCategory.value = renameFromCategory; 367 renameFavoriteListInputMachine.value = renameFromMachine; 368 renameFavoriteListInputIsShared.checked = renameIsShared; 369 370 document.querySelector("#renameFavoriteListButton").addEventListener("click", function () { 371 if (renameFavoriteListInputLocation.value !== "") { 372 // Rename Favorite List 373 document.location.href = "/?custfavoritecmd=renamefavoritelist&userId=" + userId + "&favoriteListId=" + renameFavoriteListId + "&name=" + renameFavoriteListInputName.value + "&location=" + renameFavoriteListInputLocation.value + "&description=" + renameFavoriteListInputDescription.value +"&category=" + renameFavoriteListInputCategory.value +"&machine=" + renameFavoriteListInputMachine.value + "&isshared=" + (renameFavoriteListInputIsShared.checked === true ? "true" : "false"); 374 } 375 else if (document.querySelector("#renameFavoriteListError")) { 376 document.querySelector("#renameFavoriteListError").classList.remove("d-none"); 377 } 378 }); 379 }) 380 381 deleteFavoriteListModal.addEventListener('show.bs.modal', function (event) { 382 let button = event.relatedTarget; 383 let deleteFavoriteListId = button.getAttribute('data-list-id'); 384 let deleteFavoriteListName = button.getAttribute('data-list-name'); 385 let deleteFavoriteName = document.querySelector("#deleteFavoriteName"); 386 387 // Update label to confirm before deletion 388 deleteFavoriteName.innerHTML = deleteFavoriteListName; 389 390 // Delete Favorite List 391 document.querySelector("#deleteFavoriteListButton").addEventListener("click", function () { 392 DeleteFavoriteList(userId, deleteFavoriteListId); 393 }); 394 }) 395 396 async function DeleteFavoriteList(userId, favoriteListId) { 397 var url = "/?favoritecmd=removefavoritelist&userId=" + userId + "&favoriteListId=" + favoriteListId; 398 399 let response = await fetch(url); 400 if (response.ok) { 401 document.location.href = "/Default.aspx?ID=@(Pageview.Page.ID)"; 402 } 403 } 404 405 createFavoriteListModal.addEventListener('show.bs.modal', function (event) { 406 let button = event.relatedTarget; 407 let createIsShared = button.getAttribute('data-list-isshared'); 408 409 // Create new Favorite List 410 document.querySelector("#createFavoriteListButton").addEventListener("click", function () { 411 let createFavoriteListName = document.querySelector("#createFavoriteListInputName").value; 412 let createFavoriteListLocation = document.querySelector("#createFavoriteListInputLocation").value; 413 let createFavoriteListInputDescription = document.getElementById('createFavoriteListInputDescription'); 414 let createFavoriteListMachine = document.querySelector("#createFavoriteListInputMachine").value; 415 let createFavoriteListCategory = document.querySelector("#createFavoriteListInputCategory").value; 416 417 if (createFavoriteListLocation !== "") { 418 419 document.location.href = "/?custfavoritecmd=createfavoritelist&userId=" + userId + "&name=" + createFavoriteListName + "&location=" + createFavoriteListLocation + "&category=" + createFavoriteListCategory + "&machine=" + createFavoriteListMachine + "&description=" + createFavoriteListInputDescription.value + "&isshared=" + createIsShared; 420 } 421 else if (document.querySelector("#createFavoriteListError")) { 422 document.querySelector("#createFavoriteListError").classList.remove("d-none"); 423 } 424 }); 425 }) 426 </script> 427 } 428 429 @helper RenderPagination(string currentPageLink, int pageCount, int currentPage, int pageSize) 430 { 431 <ul class="pagination m-0"> 432 @{ string pageHrefTemplate = string.Format("<a class=\"page-link\" href=\"{0}&PageNum={{0}}&PageSize={{1}}\">{{0}}</a>", currentPageLink); } 433 @for (int i = 1; i <= pageCount; i++) 434 { 435 var css = i == currentPage 436 ? "page-item active" 437 : "page-item"; 438 <li class="@css"> 439 @string.Format(pageHrefTemplate, i, pageSize) 440 </li> 441 } 442 </ul> 443 } 444
Error executing template "Designs/Swift/eCom/CustomerExperienceCenter/Favorites/FavoriteLists_Custom.cshtml"
System.ArgumentNullException: Value cannot be null.
Parameter name: source
   at System.Linq.Enumerable.Where[TSource](IEnumerable`1 source, Func`2 predicate)
   at CompiledRazorTemplates.Dynamic.RazorEngine_34368f908ed84d45b42ca9f0734d2fcf.<RenderContent>b__0_0(TextWriter __razor_helper_writer) in D:\dynamicweb.net\Solutions\twodayco3\simas.cloud.dynamicweb-cms.com\Files\Templates\Designs\Swift\eCom\CustomerExperienceCenter\Favorites\FavoriteLists_Custom.cshtml:line 57
   at CompiledRazorTemplates.Dynamic.RazorEngine_34368f908ed84d45b42ca9f0734d2fcf.Execute() in D:\dynamicweb.net\Solutions\twodayco3\simas.cloud.dynamicweb-cms.com\Files\Templates\Designs\Swift\eCom\CustomerExperienceCenter\Favorites\FavoriteLists_Custom.cshtml:line 25
   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 ViewModelTemplate<FavoriteListListViewModel> 2 @using Dynamicweb.Rendering 3 @using Dynamicweb.Ecommerce.Frontend 4 @using System.Linq 5 @using Co3.Simas.Custom.Constants 6 @using Co3.Simas.Custom.Extensions 7 @using Dynamicweb.Ecommerce.CustomerExperienceCenter.Favorites 8 @using ProductViewModel = Dynamicweb.Ecommerce.ProductCatalog.ProductViewModel 9 @{ 10 string themeRaw = Pageview.CurrentParagraph.Item["Theme"]?.ToString(); 11 string theme = !string.IsNullOrEmpty(themeRaw) ? " h-100 theme " + themeRaw.Replace(" ", "").Trim().ToLower() : ""; 12 bool sharedList = (Dynamicweb.Frontend.PageView.Current().CurrentParagraph.ModuleProperties.GetValue("RetrieveListBasedOn") == "UseCustomerNumber"); 13 } 14 @if (sharedList) 15 { 16 @SnippetStart("FavoriteListsShared") 17 if (theme != "") 18 { 19 <div class="@(theme)"> 20 @RenderContent() 21 </div> 22 } 23 else 24 { 25 @RenderContent() 26 } 27 28 @SnippetEnd("FavoriteListsShared") 29 } 30 else 31 { 32 if (theme != "") 33 { 34 <div class="@(theme)"> 35 @RenderContent() 36 </div> 37 } 38 else 39 { 40 @RenderContent() 41 } 42 43 <div class="mt-6"> 44 @RenderSnippet("FavoriteListsShared") 45 </div> 46 } 47 48 49 @helper RenderContent() 50 { 51 bool sharedList = (Dynamicweb.Frontend.PageView.Current().CurrentParagraph.ModuleProperties.GetValue("RetrieveListBasedOn") == "UseCustomerNumber"); 52 string title = Pageview.CurrentParagraph.Item["Title"]?.ToString(); 53 string listPageLink = Pageview.CurrentParagraph.Item["ProductListPage"] != null ? Pageview.CurrentParagraph.Item["ProductListPage"].ToString() : ""; 54 string currentPageUrl = "/Default.aspx?ID=" + Pageview.Page.ID; 55 string url = "/Default.aspx?ID=" + (GetPageIdByNavigationTag("CartService")); 56 57 IEnumerable<IGrouping<string, FavoriteListViewModel>> listGroups = Model.FavoriteLists.Where(fl => fl.ShowInList(sharedList)).OrderBy(fl => string.IsNullOrEmpty(fl.Category()) == false ? fl.Category() : "zz").ThenBy(fl => fl.Name).GroupBy(fl => fl.Category()); 58 59 int listsCount = listGroups.Count(); 60 int pageSize = Model.PageSize; 61 62 63 <header class="d-flex flex-wrap align-items-center"> 64 <h4 class="m-0 flex-fill mb-2"> 65 <small>@title (@listsCount)</small> 66 </h4> 67 @if (listsCount > 0) 68 { 69 <button type="button" class="btn btn-link p-0 border-0" data-bs-toggle="modal" data-list-isshared="@sharedList" data-bs-target="#createFavoriteListModal">+ @Translate("Add new favorite list")</button> 70 } 71 </header> 72 73 if (listsCount < 1) 74 { 75 <div class="grid"> 76 <div class="g-col-12 g-start-lg-3 g-col-lg-8 d-flex flex-column gap-3 text-center py-3"> 77 <h2 class="h5 m-0">@Translate("It looks like you do not have any favorites yet")</h2> 78 <p class="m-0">@Translate("Save and arrange the best things here until you are ready for them")</p> 79 80 <div class="d-flex flex-column flex-sm-row gap-3 justify-content-center"> 81 <button type="button" class="btn btn-link p-0 border-0" data-bs-toggle="modal" data-list-isshared="@sharedList" data-bs-target="#createFavoriteListModal">+ @Translate("Add new favorite list")</button> 82 </div> 83 </div> 84 </div> 85 } 86 else 87 { 88 <div class="mb-4"> 89 @{ 90 int accordionItemLoopCounter = 0; 91 } 92 @foreach (IGrouping<string, FavoriteListViewModel> categoryGroup in listGroups) 93 { 94 bool isFirstItemInLoop = accordionItemLoopCounter == 0; 95 bool expandFirstAccordionItem = false; //isFirstItemInLoop == true; 96 string accordionItemId = Guid.NewGuid().ToHtmlId(); 97 string groupName = string.IsNullOrEmpty(categoryGroup.Key) == false ? categoryGroup.Key : Translate("Ingen kategori"); 98 string buttonAriaExpanded = expandFirstAccordionItem == true ? "true" : "false"; 99 string buttonClassState = expandFirstAccordionItem == true ? "" : "collapsed"; 100 string collapseClassState = expandFirstAccordionItem == true ? "show" : "collapse"; 101 102 <div class="accordion mb-2"> 103 <div class="accordion-item"> 104 <h5 class="accordion-header"> 105 <button class="fw-bold fs-5 accordion-button @buttonClassState" type="button" data-bs-toggle="collapse" data-bs-target="#@accordionItemId" aria-expanded="@buttonAriaExpanded" aria-controls="@accordionItemId">@groupName</button> 106 </h5> 107 <div id="@accordionItemId" class="accordion-collapse @collapseClassState"> 108 <div class="accordion-body"> 109 <ul class="list-unstyled m-0"> 110 @foreach (FavoriteListViewModel theList in categoryGroup) 111 { 112 string favoriteListLink = listPageLink + "&amp;FavoriteListId=" + theList.Id; 113 string listName = !string.IsNullOrEmpty(theList.Name) ? theList.Name : Translate("Favorites"); 114 string location = theList.Location(); 115 string isShared = theList.IsShared().ToString().ToLowerInvariant(); 116 string description = theList.Description(); 117 string category = theList.Category(); 118 string machine = theList.Machine(); 119 <li class="mb-4"> 120 <p class="d-flex align-items-center m-0"> 121 <a href="@favoriteListLink" class="text-decoration-none"> 122 <strong>@listName</strong> 123 </a> 124 @if (theList.IsShared() == true) 125 { 126 string isSharedByUserName = theList.GetFavoriteList().IsShareByUserName(); 127 128 if (isSharedByUserName == "YOU" || isSharedByUserName == "UNKNOWN") 129 { 130 isSharedByUserName = Translate("SharedBy:" + isSharedByUserName, isSharedByUserName); 131 } 132 133 <small class="badge bg-info ms-3">@Translate("Shared by") @isSharedByUserName</small> 134 } 135 @if (theList.IsEditableForCurrentUser()) 136 { 137 <span class="mx-3"> &middot; </span> 138 139 <button type="button" 140 class="btn btn-link btn-sm p-0 me-2 renameFavoriteListModal" 141 data-bs-toggle="modal" 142 data-bs-target="#renameFavoriteListModal" 143 data-list-id="@theList.Id" 144 data-list-isshared="@isShared" 145 data-list-location="@location" 146 data-list-description="@description" 147 data-list-category="@category" 148 data-list-machine="@machine" 149 data-list-isshared="@sharedList" 150 data-list-name="@listName"> 151 @Translate("Rename") 152 </button> 153 <button type="button" 154 class="btn btn-link btn-sm p-0 mx-1 px-1 deleteFavoriteNameButton" 155 data-bs-toggle="modal" 156 data-bs-target="#deleteFavoriteListModal" 157 data-list-id="@theList.Id" 158 data-list-name="@listName"> 159 @Translate("Delete") 160 </button> 161 } 162 </p> 163 <p class="opacity-75 mb-1">@description</p> 164 <form method="post" action="@url" class="d-flex align-items-center"> 165 <input type="hidden" name="CartCmd" id="CartCmd" value="addMulti"> 166 @{ 167 int listProductLoopCounter = 1; 168 } 169 @foreach (FavoriteProduct favoriteProduct in theList.GetFavoriteList().Products()) 170 { 171 string quantityName = $"Quantity{listProductLoopCounter}"; 172 string productIdName = $"ProductID{listProductLoopCounter}"; 173 string locationName = $"EcomOrderLineFieldInput_{OrderLineFieldIds.Location}{listProductLoopCounter}"; 174 string machineName = $"EcomOrderLineFieldInput_{OrderLineFieldIds.Machine}{listProductLoopCounter}"; 175 string categoryName = $"EcomOrderLineFieldInput_{OrderLineFieldIds.Category}{listProductLoopCounter}"; 176 string listProductLoopCounterName = $"ProductLoopCounter{listProductLoopCounter}"; 177 178 <input type="hidden" name="@quantityName" value="@Math.Max(1, (int)favoriteProduct.Quantity)"> 179 <input type="hidden" name="@productIdName" value="@favoriteProduct.ProductId"> 180 <input type="hidden" name="@locationName" value="@location"> 181 <input type="hidden" name="@machineName" value="@machine"> 182 <input type="hidden" name="@categoryName" value="@category"> 183 <input type="hidden" name="@listProductLoopCounterName" value="@listProductLoopCounter"> 184 listProductLoopCounter += 1; 185 } 186 <button type="submit" class="btn btn-link btn-sm me-2 p-0">@Translate("Add all products in this list to your cart")</button> 187 </form> 188 </li> 189 } 190 </ul> 191 </div> 192 @{ int categoryProductLoopCounter = 1; } 193 <form method="post" action="@url" class="d-flex align-items-center text-center border-top"> 194 <input type="hidden" name="CartCmd" id="CartCmd" value="addMulti"> 195 @foreach (FavoriteListViewModel theList in categoryGroup) 196 { 197 string location = theList.Location(); 198 string machine = theList.Machine(); 199 string category = theList.Category(); 200 foreach (FavoriteProduct favoriteProduct in theList.GetFavoriteList().Products()) 201 { 202 string quantityName = $"Quantity{categoryProductLoopCounter}"; 203 string productIdName = $"ProductID{categoryProductLoopCounter}"; 204 string locationName = $"EcomOrderLineFieldInput_{OrderLineFieldIds.Location}{categoryProductLoopCounter}"; 205 string machineName = $"EcomOrderLineFieldInput_{OrderLineFieldIds.Machine}{categoryProductLoopCounter}"; 206 string categoryName = $"EcomOrderLineFieldInput_{OrderLineFieldIds.Category}{categoryProductLoopCounter}"; 207 string categoryProductLoopCounterName = $"ProductLoopCounter{categoryProductLoopCounter}"; 208 <input type="hidden" name="@quantityName" value="@Math.Max(1, (int)favoriteProduct.Quantity)"> 209 <input type="hidden" name="@productIdName" value="@favoriteProduct.ProductId"> 210 <input type="hidden" name="@locationName" value="@location"> 211 <input type="hidden" name="@machineName" value="@machine"> 212 <input type="hidden" name="@categoryName" value="@category"> 213 <input type="hidden" name="@categoryProductLoopCounterName" value="@categoryProductLoopCounter"> 214 categoryProductLoopCounter += 1; 215 } 216 } 217 <button type="submit" class="btn btn-link btn-sm mx-auto">@Translate("Add all products in this category to your cart")</button> 218 </form> 219 </div> 220 </div> 221 </div> 222 accordionItemLoopCounter++; 223 } 224 </div> 225 } 226 227 if (listsCount > pageSize) 228 { 229 <div class="p-3"> 230 @RenderPagination(currentPageUrl, Model.PageCount, Model.CurrentPage, Model.PageSize) 231 </div> 232 } 233 } 234 235 236 @if (!sharedList) 237 { 238 <div class="modal fade" tabindex="-1" id="createFavoriteListModal"> 239 <div class="modal-dialog modal-dialog-centered"> 240 <div class="modal-content"> 241 <div class="modal-header"> 242 <h5 class="modal-title">@Translate("Create favorite list")</h5> 243 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> 244 </div> 245 <div class="modal-body d-flex flex-column gap-3"> 246 <div hidden> 247 <label for="createFavoriteListInputName" class="form-label">@Translate("Name the favorite list")</label> 248 <input type="text" readonly="readonly" class="form-control" id="createFavoriteListInputName" placeholder="@Translate("Name")"> 249 </div> 250 <div> 251 <label for="createFavoriteListInputCategory" class="form-label">@Translate("Category")</label> 252 <input type="text" class="form-control" id="createFavoriteListInputCategory" placeholder="@Translate("Category - placeholder")"/> 253 </div> 254 <div> 255 <label for="createFavoriteListInputLocation" class="form-label">@Translate("Location")</label> 256 <input type="text" class="form-control" id="createFavoriteListInputLocation" placeholder="@Translate("Location - placeholder")"> 257 </div> 258 <div> 259 <label for="createFavoriteListInputMachine" class="form-label">@Translate("Machine")</label> 260 <input type="text" class="form-control" id="createFavoriteListInputMachine" placeholder="@Translate("Machine - placeholder")"> 261 </div> 262 263 <div> 264 <label for="createFavoriteListInputDescription" class="form-label">@Translate("Description")</label> 265 <textarea class="form-control" id="createFavoriteListInputDescription" placeholder="@Translate("Description - placeholder")"></textarea> 266 </div> 267 268 <div class="alert alert-danger m-0 d-none" role="alert" id="createFavoriteListError">@Translate("A Favorite List must have a name")</div> 269 </div> 270 <div class="modal-footer"> 271 <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">@Translate("Cancel")</button> 272 <button type="button" class="btn btn-primary" id="createFavoriteListButton">@Translate("Create list")</button> 273 </div> 274 </div> 275 </div> 276 </div> 277 278 <div class="modal fade" tabindex="-1" id="renameFavoriteListModal"> 279 <div class="modal-dialog modal-dialog-centered"> 280 <div class="modal-content"> 281 <div class="modal-header"> 282 <h5 class="modal-title">@Translate("Rename favorite list")</h5> 283 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> 284 </div> 285 <div class="modal-body"> 286 <div> 287 <label for="renameFavoriteListInputName" class="form-label">@Translate("Rename favorite list"):</label> 288 <input type="text" readonly="readonly" class="form-control" id="renameFavoriteListInputName" placeholder="@Translate("Name")"> 289 </div> 290 <div> 291 <label for="renameFavoriteListInputCategory" class="form-label">@Translate("Category")</label> 292 <input type="text" class="form-control" id="renameFavoriteListInputCategory" placeholder="@Translate("Category - placeholder")"/> 293 </div> 294 <div> 295 <label for="renameFavoriteListInputLocation" class="form-label">@Translate("Location")</label> 296 <input type="text" class="form-control" id="renameFavoriteListInputLocation" placeholder="@Translate("Location - placeholder")"/> 297 </div> 298 <div> 299 <label for="renameFavoriteListInputMachine" class="form-label">@Translate("Machine")</label> 300 <input type="text" class="form-control" id="renameFavoriteListInputMachine" placeholder="@Translate("Machine - placeholder")"/> 301 </div> 302 <div> 303 <label for="renameFavoriteListInputDescription" class="form-label">@Translate("Description")</label> 304 <textarea class="form-control" id="renameFavoriteListInputDescription" placeholder="@Translate("Description - placeholder")"></textarea> 305 </div> 306 <div class="form-check"> 307 <input class="form-check-input" type="checkbox" value="true" id="renameFavoriteListInputIsShared"> 308 <label class="form-check-label" for="renameFavoriteListInputIsShared"> 309 @Translate("IsShared - placeholder") 310 </label> 311 </div> 312 <div class="alert alert-danger m-0 d-none" role="alert" id="renameFavoriteListError">@Translate("A Favorite List must have a name")</div> 313 </div> 314 <div class="modal-footer"> 315 <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">@Translate("Cancel")</button> 316 <button type="button" class="btn btn-primary" id="renameFavoriteListButton">@Translate("Update list")</button> 317 </div> 318 </div> 319 </div> 320 </div> 321 322 <div class="modal fade" tabindex="-1" id="deleteFavoriteListModal"> 323 <div class="modal-dialog modal-dialog-centered"> 324 <div class="modal-content"> 325 <div class="modal-header"> 326 <h5 class="modal-title">@Translate("Delete favorite list")</h5> 327 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> 328 </div> 329 <div class="modal-body"> 330 <p>@Translate("You are about to delete"): <strong id="deleteFavoriteName"></strong>.</p> 331 <p>@Translate("Are you sure you want to delete it?")</p> 332 </div> 333 <div class="modal-footer"> 334 <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">@Translate("Cancel")</button> 335 <button type="button" class="btn btn-primary" id="deleteFavoriteListButton">@Translate("Delete list")</button> 336 </div> 337 </div> 338 </div> 339 </div> 340 341 <script> 342 let userId = @Pageview.User.ID; 343 let renameFavoriteListModal = document.querySelector("#renameFavoriteListModal") 344 let deleteFavoriteListModal = document.querySelector("#deleteFavoriteListModal") 345 let createFavoriteListModal = document.querySelector("#createFavoriteListModal") 346 347 renameFavoriteListModal.addEventListener('show.bs.modal', function (event) { 348 let button = event.relatedTarget 349 let renameIsShared = button.getAttribute('data-list-isshared') === 'true' ? true : false; 350 let renameFavoriteListId = button.getAttribute('data-list-id'); 351 let renameFromName = button.getAttribute('data-list-name') 352 let renameFromLocation = button.getAttribute('data-list-location') 353 let renameFromDescription = button.getAttribute('data-list-description') 354 let renameFromCategory = button.getAttribute('data-list-category') 355 let renameFromMachine = button.getAttribute('data-list-machine') 356 let renameFavoriteListInputName = document.getElementById('renameFavoriteListInputName'); 357 let renameFavoriteListInputLocation = document.getElementById('renameFavoriteListInputLocation'); 358 let renameFavoriteListInputDescription = document.getElementById('renameFavoriteListInputDescription'); 359 let renameFavoriteListInputCategory = document.getElementById('renameFavoriteListInputCategory'); 360 let renameFavoriteListInputMachine = document.getElementById('renameFavoriteListInputMachine'); 361 let renameFavoriteListInputIsShared = document.getElementById('renameFavoriteListInputIsShared'); 362 363 renameFavoriteListInputName.value = renameFromName; 364 renameFavoriteListInputLocation.value = renameFromLocation; 365 renameFavoriteListInputDescription.value = renameFromDescription; 366 renameFavoriteListInputCategory.value = renameFromCategory; 367 renameFavoriteListInputMachine.value = renameFromMachine; 368 renameFavoriteListInputIsShared.checked = renameIsShared; 369 370 document.querySelector("#renameFavoriteListButton").addEventListener("click", function () { 371 if (renameFavoriteListInputLocation.value !== "") { 372 // Rename Favorite List 373 document.location.href = "/?custfavoritecmd=renamefavoritelist&userId=" + userId + "&favoriteListId=" + renameFavoriteListId + "&name=" + renameFavoriteListInputName.value + "&location=" + renameFavoriteListInputLocation.value + "&description=" + renameFavoriteListInputDescription.value +"&category=" + renameFavoriteListInputCategory.value +"&machine=" + renameFavoriteListInputMachine.value + "&isshared=" + (renameFavoriteListInputIsShared.checked === true ? "true" : "false"); 374 } 375 else if (document.querySelector("#renameFavoriteListError")) { 376 document.querySelector("#renameFavoriteListError").classList.remove("d-none"); 377 } 378 }); 379 }) 380 381 deleteFavoriteListModal.addEventListener('show.bs.modal', function (event) { 382 let button = event.relatedTarget; 383 let deleteFavoriteListId = button.getAttribute('data-list-id'); 384 let deleteFavoriteListName = button.getAttribute('data-list-name'); 385 let deleteFavoriteName = document.querySelector("#deleteFavoriteName"); 386 387 // Update label to confirm before deletion 388 deleteFavoriteName.innerHTML = deleteFavoriteListName; 389 390 // Delete Favorite List 391 document.querySelector("#deleteFavoriteListButton").addEventListener("click", function () { 392 DeleteFavoriteList(userId, deleteFavoriteListId); 393 }); 394 }) 395 396 async function DeleteFavoriteList(userId, favoriteListId) { 397 var url = "/?favoritecmd=removefavoritelist&userId=" + userId + "&favoriteListId=" + favoriteListId; 398 399 let response = await fetch(url); 400 if (response.ok) { 401 document.location.href = "/Default.aspx?ID=@(Pageview.Page.ID)"; 402 } 403 } 404 405 createFavoriteListModal.addEventListener('show.bs.modal', function (event) { 406 let button = event.relatedTarget; 407 let createIsShared = button.getAttribute('data-list-isshared'); 408 409 // Create new Favorite List 410 document.querySelector("#createFavoriteListButton").addEventListener("click", function () { 411 let createFavoriteListName = document.querySelector("#createFavoriteListInputName").value; 412 let createFavoriteListLocation = document.querySelector("#createFavoriteListInputLocation").value; 413 let createFavoriteListInputDescription = document.getElementById('createFavoriteListInputDescription'); 414 let createFavoriteListMachine = document.querySelector("#createFavoriteListInputMachine").value; 415 let createFavoriteListCategory = document.querySelector("#createFavoriteListInputCategory").value; 416 417 if (createFavoriteListLocation !== "") { 418 419 document.location.href = "/?custfavoritecmd=createfavoritelist&userId=" + userId + "&name=" + createFavoriteListName + "&location=" + createFavoriteListLocation + "&category=" + createFavoriteListCategory + "&machine=" + createFavoriteListMachine + "&description=" + createFavoriteListInputDescription.value + "&isshared=" + createIsShared; 420 } 421 else if (document.querySelector("#createFavoriteListError")) { 422 document.querySelector("#createFavoriteListError").classList.remove("d-none"); 423 } 424 }); 425 }) 426 </script> 427 } 428 429 @helper RenderPagination(string currentPageLink, int pageCount, int currentPage, int pageSize) 430 { 431 <ul class="pagination m-0"> 432 @{ string pageHrefTemplate = string.Format("<a class=\"page-link\" href=\"{0}&PageNum={{0}}&PageSize={{1}}\">{{0}}</a>", currentPageLink); } 433 @for (int i = 1; i <= pageCount; i++) 434 { 435 var css = i == currentPage 436 ? "page-item active" 437 : "page-item"; 438 <li class="@css"> 439 @string.Format(pageHrefTemplate, i, pageSize) 440 </li> 441 } 442 </ul> 443 } 444