Error executing template "Designs/Swift/eCom/CustomerExperienceCenter/Favorites/FavoriteLists.cshtml"
System.NullReferenceException: Object reference not set to an instance of an object.
at CompiledRazorTemplates.Dynamic.RazorEngine_d15b907190fb4d6bbf1ca1c2a0dbc1c3.Execute() in D:\DW9\Solutions\witt.dk\Files\Templates\Designs\Swift\eCom\CustomerExperienceCenter\Favorites\FavoriteLists.cshtml:line 214
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
5 @{
6 var themeRaw = Pageview.CurrentParagraph.Item["Theme"]?.ToString();
7 string theme = !string.IsNullOrEmpty(themeRaw) ? " h-100 theme " + themeRaw.Replace(" ", "").Trim().ToLower() : "";
8 }
9
10 @if (theme != "") {
11 <div class="@(theme)">
12 @RenderContent()
13 </div>
14 } else {
15 @RenderContent()
16 }
17
18 @helper RenderContent() {
19 string listPageLink = Pageview.CurrentParagraph.Item["ProductListPage"] != null ? Pageview.CurrentParagraph.Item["ProductListPage"].ToString() : "";
20 string currentPageUrl = "/Default.aspx?ID=" + Pageview.Page.ID;
21 int listsCount = Model.TotalFavoriteListsCount;
22 int pageSize = Model.PageSize;
23
24 <header class="d-flex flex-wrap align-items-center gap-3 p-3 border-bottom">
25 <h1 class="h6 m-0 flex-fill">@Translate("Favorite lists")</h1>
26 @if (Model.FavoriteLists != null)
27 {
28 if(Model.FavoriteLists.Count > 0) {
29 <button type="button" class="btn btn-link p-0 border-0" data-bs-toggle="modal" data-bs-target="#createFavoriteListModal">+ @Translate("Add new favorite list")</button>
30 }
31 }
32 </header>
33
34 if (Model.FavoriteLists == null || Model.FavoriteLists.Count < 1)
35 {
36 <div class="grid">
37 <div class="g-col-12 g-start-lg-3 g-col-lg-8 d-flex flex-column gap-3 text-center py-3">
38 <h2 class="h5 m-0">@Translate("It looks like you do not have any favorites yet")</h2>
39 <p class="m-0">@Translate("Save and arrange the best things here until you are ready for them")</p>
40
41 <div class="d-flex flex-column flex-sm-row gap-3 justify-content-center">
42 @if (!string.IsNullOrEmpty(listPageLink)) {
43 <a href="@listPageLink" class="btn btn-secondary">@Translate("Go exploring")</a>
44 }
45 <button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#createFavoriteListModal">@Translate("Create favorite list")</button>
46 </div>
47 </div>
48 </div>
49 }
50 else
51 {
52 string productCountLabel = Model.FavoriteLists.Count > 1 ? Translate("products") : Translate("product");
53
54 foreach (var theList in Model.FavoriteLists)
55 {
56 string favoriteListLink = currentPageUrl + "&FavoriteListId=" + theList.Id;
57 string listName = !string.IsNullOrEmpty(theList.Name) ? theList.Name : Translate("Favorites");
58
59 <article class="d-flex flex-column gap-3 p-3 border-bottom">
60
61 <header class="d-flex flex-row align-items-baseline lh-1">
62 <h3 class="flex-fill h6 m-0">
63 <a href="@favoriteListLink" class="text-decoration-none opacity-75">@listName</a>
64 </h3>
65 <span class="small text-end">@theList.ProductList.Products.Count @productCountLabel <span class="d-none d-sm-inline">@Translate("in this list")</span></span>
66 </header>
67
68 <div class="d-md-none grid grid-2">
69 @if(theList.ProductList.Products.Count > 0)
70 {
71 foreach (var item in theList.ProductList.Products.Take(2))
72 {
73 string productImage = "/Admin/Public/GetImage.ashx?Image=" + item.DefaultImage.Value + "&Format=webp&Width=350&Height=350";
74
75 <div class="ratio ratio-1x1">
76 <a href="@favoriteListLink" class="d-flex justify-content-center align-items-center">
77 <img
78 src="@productImage"
79 loading="lazy"
80 decoding="async"
81 class="mw-100 mh-100"
82 alt="@item.Name" />
83 </a>
84 </div>
85 }
86 }
87 else
88 {
89 <div class="g-col-12 py-5 text-center border">
90 <a href="@listPageLink">@Translate("This list is empty. Click here to be inspired")</a>
91 </div>
92 }
93 </div>
94
95 <div class="d-none d-md-grid d-print-grid grid grid-2 grid-md-5">
96 @if(theList.ProductList.Products.Count > 0)
97 {
98 foreach (var item in theList.ProductList.Products.Take(5))
99 {
100 string productImage = "/Admin/Public/GetImage.ashx?Image=" + item.DefaultImage.Value + "&Format=webp&Width=350&Height=350";
101
102 <div class="ratio ratio-1x1">
103 <a href="@favoriteListLink" class="d-flex justify-content-center align-items-center">
104 <img
105 src="@productImage"
106 loading="lazy"
107 decoding="async"
108 class="mw-100 mh-100"
109 alt="@item.Name" />
110 </a>
111 </div>
112 }
113 }
114 else
115 {
116 <div class="g-col-12 py-6 text-center border">
117 <a href="@listPageLink">@Translate("This list is empty. Click here to be inspired")</a>
118 </div>
119 }
120 </div>
121
122 <footer class="d-flex flex-row gap-3 align-items-center justify-content-end">
123 <button
124 type="button"
125 class="btn btn-link p-0 renameFavoriteListModal"
126 data-bs-toggle="modal"
127 data-bs-target="#renameFavoriteListModal"
128 data-list-id="@theList.Id"
129 data-list-name="@listName">@Translate("Rename")
130 </button>
131 <button
132 type="button"
133 class="btn btn-link p-0 deleteFavoriteNameButton"
134 data-bs-toggle="modal"
135 data-bs-target="#deleteFavoriteListModal"
136 data-list-id="@theList.Id"
137 data-list-name="@listName">@Translate("Delete")</button>
138 </footer>
139 </article>
140 }
141 }
142
143 if (listsCount > pageSize)
144 {
145 <div class="p-3">
146 @RenderPagination(currentPageUrl, Model.PageCount, Model.CurrentPage, Model.PageSize)
147 </div>
148 }
149 }
150
151 <div class="modal fade" tabindex="-1" id="createFavoriteListModal">
152 <div class="modal-dialog modal-dialog-centered">
153 <div class="modal-content">
154 <div class="modal-header">
155 <h5 class="modal-title">@Translate("Create favorite list")</h5>
156 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
157 </div>
158 <div class="modal-body d-flex flex-column gap-3">
159 <div>
160 <label for="createFavoriteListInputName" class="form-label">@Translate("Name the favorite list")</label>
161 <input type="text" class="form-control" id="createFavoriteListInputName" placeholder="@Translate("Name")">
162 </div>
163 <div class="alert alert-danger m-0 d-none" role="alert" id="createFavoriteListError">@Translate("A Favorite List must have a name")</div>
164 </div>
165 <div class="modal-footer">
166 <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">@Translate("Cancel")</button>
167 <button type="button" class="btn btn-primary" id="createFavoriteListButton">@Translate("Create list")</button>
168 </div>
169 </div>
170 </div>
171 </div>
172
173 <div class="modal fade" tabindex="-1" id="renameFavoriteListModal">
174 <div class="modal-dialog modal-dialog-centered">
175 <div class="modal-content">
176 <div class="modal-header">
177 <h5 class="modal-title">@Translate("Rename favorite list")</h5>
178 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
179 </div>
180 <div class="modal-body">
181 <div>
182 <label for="renameFavoriteListInputName" class="form-label">@Translate("Rename favorite list"):</label>
183 <input type="text" class="form-control" id="renameFavoriteListInputName" placeholder="@Translate("Name")">
184 </div>
185 </div>
186 <div class="modal-footer">
187 <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">@Translate("Cancel")</button>
188 <button type="button" class="btn btn-primary" id="renameFavoriteListButton">@Translate("Update list")</button>
189 </div>
190 </div>
191 </div>
192 </div>
193
194 <div class="modal fade" tabindex="-1" id="deleteFavoriteListModal">
195 <div class="modal-dialog modal-dialog-centered">
196 <div class="modal-content">
197 <div class="modal-header">
198 <h5 class="modal-title">@Translate("Delete favorite list")</h5>
199 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
200 </div>
201 <div class="modal-body">
202 <p>@Translate("You are about to delete"): <strong id="deleteFavoriteName"></strong>.</p>
203 <p>@Translate("Are you sure you want to delete it?")</p>
204 </div>
205 <div class="modal-footer">
206 <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">@Translate("Cancel")</button>
207 <button type="button" class="btn btn-primary" id="deleteFavoriteListButton">@Translate("Delete list")</button>
208 </div>
209 </div>
210 </div>
211 </div>
212
213 <script>
214 let userId = @Pageview.User.ID;
215 let renameFavoriteListModal = document.querySelector("#renameFavoriteListModal")
216 let deleteFavoriteListModal = document.querySelector("#deleteFavoriteListModal")
217
218 renameFavoriteListModal.addEventListener('show.bs.modal', function (event) {
219 let button = event.relatedTarget
220 let renameFavoriteListId = button.getAttribute('data-list-id');
221 let renameFromName = button.getAttribute('data-list-name')
222 let renameFavoriteListInputName = document.getElementById('renameFavoriteListInputName');
223
224 renameFavoriteListInputName.value = renameFromName;
225
226 document.querySelector("#renameFavoriteListButton").addEventListener("click", function () {
227 let favoriteListId = renameFavoriteListId;
228
229 // Rename Favorite List
230 document.location.href = "/?favoritecmd=renamefavoritelist&userId=" + userId + "&favoriteListId=" + favoriteListId + "&name=" + renameFavoriteListInputName.value;
231 });
232 })
233
234 deleteFavoriteListModal.addEventListener('show.bs.modal', function (event) {
235 let button = event.relatedTarget;
236 let deleteFavoriteListId = button.getAttribute('data-list-id');
237 let deleteFavoriteListName = button.getAttribute('data-list-name');
238 let deleteFavoriteName = document.querySelector("#deleteFavoriteName");
239
240 // Update label to confirm before deletion
241 deleteFavoriteName.innerHTML = deleteFavoriteListName;
242
243 // Delete Favorite List
244 document.querySelector("#deleteFavoriteListButton").addEventListener("click", function () {
245 let favoriteListId = deleteFavoriteListId;
246 DeleteFavoriteList(userId, favoriteListId);
247 });
248 })
249
250 async function DeleteFavoriteList(userId, favoriteListId) {
251 var url = "/?favoritecmd=removefavoritelist&userId=" + userId + "&favoriteListId=" + favoriteListId;
252
253 let response = await fetch(url);
254 if (response.ok) {
255 document.location.href = "/Default.aspx?ID=@(Pageview.Page.ID)";
256 }
257 }
258
259 // Create new Favorite List
260 document.querySelector("#createFavoriteListButton").addEventListener("click", function () {
261 let createFavoriteListName = document.querySelector("#createFavoriteListInputName").value;
262
263 if (createFavoriteListName != "") {
264 document.location.href = "/?favoritecmd=createfavoritelist&userId=" + userId + "&name=" + createFavoriteListName;
265 }
266 else if (document.querySelector("#createFavoriteListError"))
267 {
268 document.querySelector("#createFavoriteListError").classList.remove("d-none");
269 }
270 });
271 </script>
272
273
274 @helper RenderPagination(string currentPageLink, int pageCount, int currentPage, int pageSize)
275 {
276 <ul class="pagination m-0">
277 @{string pageHrefTemplate = string.Format("<a class=\"page-link\" href=\"{0}&PageNum={{0}}&PageSize={{1}}\">{{0}}</a>", currentPageLink);}
278 @for (int i = 1; i <= pageCount; i++)
279 {
280 var css = i == currentPage
281 ? "page-item active"
282 : "page-item";
283 <li class="@css">
284 @string.Format(pageHrefTemplate, i, pageSize)
285 </li>
286 }
287 </ul>
288 }
289