Error executing template "Designs/RoadPro/eCom/Product/ProductRedirect.cshtml"
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
at System.Collections.Generic.Dictionary`2.Enumerator.MoveNext()
at Dynamicweb.Modules.Searching.Rules.Parser.UnescapeStrings(String s)
at Dynamicweb.Modules.Searching.Rules.Parser.ParseSimpleExpression(String expression)
at Dynamicweb.Modules.Searching.Rules.Parser.Parse(String input)
at Dynamicweb.ItemPublisher.FilterHelper.ToXml(String filter)
at Dynamicweb.ItemPublisher.Frontend.GetContentBySettings(String settings)
--- End of inner exception stack trace ---
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at Dynamicweb.Extensibility.AddIns.AddInManager.InvokeFunction(Object instance, String functionName, Object[] arguments)
at Dynamicweb.Rendering.TemplateBase`1.RenderItemList(Object settings)
at CompiledRazorTemplates.Dynamic.RazorEngine_18952c6da71e4ad78e224610a9c655bc.Execute() in F:\Domains\Sites\roadprobrands.com\Files\Templates\Designs\RoadPro\eCom\Product\ProductRedirect.cshtml:line 582
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 RazorTemplateBase<RazorTemplateModel<Template>>
2 @using Dynamicweb.Rendering;
3
4 @if(!string.IsNullOrEmpty(System.Web.HttpContext.Current.Request.Params["detail"]) && GetInteger("Ecom:Product.PrimaryOrCurrentPageID") != Pageview.Page.ID)
5 {
6 string redirect = "/Default.aspx?ID=" + GetString("Ecom:Product.PrimaryOrCurrentPageID") + "&ProductID=" + GetString("Ecom:Product.ID");
7 if(!string.IsNullOrEmpty(System.Web.HttpContext.Current.Request.QueryString["variantID"]))
8 {
9 redirect += "&variantID=" + System.Web.HttpContext.Current.Request.QueryString["variantID"].ToString();
10 }
11 System.Web.HttpContext.Current.Response.Redirect(Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl(redirect));
12 }
13 @inherits RazorTemplateBase<RazorTemplateModel<Template>>
14 @using System
15 @using Dynamicweb.Rendering;
16 @using System;
17 @using System.IO;
18 @using System.Web;
19 @using System.Text;
20 @using System.Collections.Generic;
21 @using System.Linq
22 @using System.Text.RegularExpressions;
23 @using Dynamicweb.Content.Items
24 @{ string designName = GetString("Template:DesignBaseUrl").Replace("/Files/Templates/Designs/", "").Replace("/", "");}@functions{
25 public static string GetImage(string sourceString, int imageWidth, int imageHeight, int imageWidthTablet = 0, int imageHeightTablet = 0, int imageWidthMobile = 0, int imageHeightMobile = 0, string imageFormat = "jpg", int imageCompression = 0, int imageCrop = 5, string background = "", string designName = "RoadPro")
26 {
27 Dynamicweb.Frontend.PageView currentPageview = Dynamicweb.Frontend.PageView.Current();
28 string currDevice = currentPageview.Device.ToString();
29 string alternativeImage = !String.IsNullOrEmpty(currentPageview.Area.Item["NoImage"].ToString()) ? currentPageview.Area.Item["NoImage"].ToString() : "/Files/Templates/Designs/"+ designName + "/images/alternativeImage.jpg";
30 string widthString = "";
31 string heightString = "";
32 string getImageFormat = imageFormat != "jpg" ? "&Format=" + imageFormat : "";
33 string getImageCompression = imageCompression != 0 ? "&Compression=" + imageCompression : "";
34 string bgColor = !string.IsNullOrEmpty(background) ? "&Background="+background : "";
35 int getImageWidth = imageWidth != 0 ? imageWidth : 0;
36 int getImageHeight = imageHeight != 0 ? imageHeight : 0;
37
38 if (currDevice == Dynamicweb.Frontend.Devices.DeviceType.Tablet.ToString())
39 {
40 getImageWidth = imageWidthTablet != 0 ? imageWidthTablet : getImageWidth;
41 getImageHeight = imageHeightTablet != 0 ? imageHeightTablet : getImageHeight;
42 }
43 else if (currDevice == Dynamicweb.Frontend.Devices.DeviceType.Mobile.ToString())
44 {
45 getImageWidth = imageWidthMobile != 0 ? imageWidthMobile : getImageWidth;
46 getImageHeight = imageHeightMobile != 0 ? imageHeightMobile : getImageHeight;
47 }
48
49 if (getImageWidth != 0)
50 {
51 widthString = "&Width=" + getImageWidth;
52 }
53 if (getImageHeight != 0)
54 {
55 heightString = "&Height=" + getImageHeight;
56 }
57
58 string output = "/Admin/Public/GetImage.ashx?Image=" + sourceString + widthString + heightString + "&altFmImage_path=" + alternativeImage + getImageFormat + getImageCompression + "&Crop=" + imageCrop + bgColor;
59 return output;
60 }
61 }
62 @inherits RazorTemplateBase<RazorTemplateModel<Template>>
63 @using Dynamicweb.Rendering;
64
65 @functions{
66 private string GetImagePathUrl(string small, string medium, string large, string pattern)
67 {
68 string imagePath;
69
70 if (!string.IsNullOrEmpty(small))
71 imagePath = small;
72 else if (!string.IsNullOrEmpty(medium))
73 imagePath = medium;
74 else if (!string.IsNullOrEmpty(large))
75 imagePath = large;
76 else
77 imagePath = pattern;
78
79 return imagePath;
80 }
81 }
82 @functions{
83 public string GetCurrentUrl()
84 {
85 string currentUrl = Pageview.GlobalTags.GetTagByName("Global:Request.Scheme").Value.ToString() + "://" + Pageview.GlobalTags.GetTagByName("Global:Request.Host").Value.ToString() + Pageview.GlobalTags.GetTagByName("Global:Pageview.Url").Value.ToString();
86
87 return currentUrl;
88 }
89 }
90 @{
91 // General API
92 Dynamicweb.Content.Items.Item areaItem = Pageview.Area.Item;
93 bool isLoggedIn = Dynamicweb.Security.UserManagement.User.IsExtranetUserLoggedIn();
94 bool isFrontEnd = Dynamicweb.Environment.ExecutingContext.IsFrontEnd();
95 string currentPageId = Pageview.Page.ID.ToString();
96 // ----
97 string titleKey = "title";
98 string title = "";
99 string imageKey = "image";
100 string image = "";
101 string document = "";
102 string documentKey = "document";
103 //Product
104 bool showQuantity = (areaItem["ShowQuantityField"] ?? "").ToString() == "True" ? true : false;
105 bool productIsFavorite = GetBoolean("Ecom:Product.IsProductInFavoriteList");
106 bool isGiftCard = GetInteger("Ecom:Product.Type") == 3;
107 string variantDefaultId = GetString("Ecom:Product.DefaultVariantComboID");
108 string variantCurrentId = GetString("Ecom:Product.VariantID");
109 string variantId = (!string.IsNullOrEmpty(variantCurrentId)) ? variantCurrentId : variantDefaultId;
110 string stockStatus = GetInteger("Ecom:Product.Stock") > 0 ? "fa-check" : "fa-close";
111 string productId = GetString("Ecom:Product.ID");
112 string productLanguage = GetString("Ecom:Product.LanguageID");
113 string productName = GetString("Ecom:Product.Name");
114 string productNumber = GetString("Ecom:Product.Number");
115 string productIntro = GetString("Ecom:Product.ShortDescription");
116 string productDescription = GetString("Ecom:Product.LongDescription");
117 string pointPrice = GetString("Ecom:Product.PointPrice");
118 string productDetails = GetString("Ecom:Product:Field.Features.Value.Clean");
119 string productWarranty = GetString("Ecom:Product:Field.Warranty.Value.Clean");
120 string productPrice = GetString("Ecom:Product.Price");
121 string brand = GetString("Ecom:Product:Field.Brand");
122 string productLink = GetString("Ecom:Product.Link.Clean");
123 int productStock = GetInteger("Ecom:Product.AvailableAmount");
124 bool newProduct = GetBoolean("Ecom:Product:Field.New");
125 //Image
126 string imagePatternName = productNumber.Replace("/", "_");
127 string pattern = imagePatternName + ".*";
128 string pattern2 = imagePatternName + "_*";
129 string productImage = GetImagePathUrl(GetString("Ecom:Product.ImageSmall.Clean"), GetString("Ecom:Product.ImageMedium.Clean"), GetString("Ecom:Product.ImageLarge.Clean"), pattern);
130 string productGetImage = GetImage(productImage, 350, 350);
131 string imagesFolder = "/Files/Files/"+designName+"/Products/";
132 string imagePattern = imagesFolder + imagePatternName + ".jpg";
133 List<Dictionary<string, string>> imagesList = new List<Dictionary<string, string>>();
134 List<Dictionary<string, string>> documentsList = new List<Dictionary<string, string>>();
135 string folderPath = Path.GetDirectoryName(HttpContext.Current.Server.MapPath("/Files/Files/" + designName+"/Products/" + imagePatternName + ".jpg"));
136 string warrantyFolderPath = Path.GetDirectoryName(HttpContext.Current.Server.MapPath("/Files/Files/" + designName+"/Documents/"));
137 // Favorites
138 string productRemoveFromList = "/Default.aspx?Id="+currentPageId+ "&ProductID=" + productId +"&CCRemoveFromMyLists="+productId+"&CCRemoveFromListVariantID="+variantId+"&CCRemoveFromListLanguageID="+productLanguage;
139 string productAddToList = "/Default.aspx?Id="+currentPageId+ "&ProductID=" + productId +"&CCAddToMyLists="+productId+"&CCAddToListVariantID="+variantId+"&CCAddToListLanguageID="+productLanguage;
140 string favoriteUrl = productIsFavorite ? productRemoveFromList : productAddToList;
141 // Downloads
142 string downloadsFilter = "Products contains 'p_"+productId+",' or Products contains 'p_"+productId+":' or Products ends with 'p_"+productId+"'";
143 // Reviews
144 string subject = (areaItem["Subject"] ?? Translate("newReview","New review")).ToString();
145 string senderName = (areaItem["SenderName"] ?? (areaItem["CompanyName"] ?? "").ToString()).ToString();
146 string senderEmail = (areaItem["SenderEmail"] ?? (areaItem["Email"] ?? "").ToString()).ToString();
147 string notifyEmail = (areaItem["NotifyEmail"] ?? (areaItem["Email"] ?? "").ToString()).ToString();
148 Dictionary<string, string> iconFiles = new Dictionary<string, string>();
149 iconFiles.Add("pdf", "fa-file-pdf-o");
150 iconFiles.Add("jpg", "fa-picture-o");
151 iconFiles.Add("png", "fa-picture-o");
152 iconFiles.Add("zip", "fa-file-archive-o");
153 iconFiles.Add("rar", "fa-file-archive-o");
154 // Loops
155 List<LoopItem> loopVariantCombinations = GetLoop("VariantCombinations");
156 List<LoopItem> loopVariantGroups = GetLoop("VariantGroups");
157 List<LoopItem> loopProdPrices = GetLoop("Product.Prices");
158 List<LoopItem> loopDetails = GetLoop("Details");
159
160 string currentDomain = Pageview.GlobalTags.GetTagByName("Global:Request.Scheme").Value.ToString() + "://" + Pageview.GlobalTags.GetTagByName("Global:Request.Host").Value.ToString();
161
162 string findStore = areaItem["FindAStore"].ToString();
163
164 // Get Images from folder
165 if (Directory.Exists(folderPath))
166 {
167 string temp = @"\";
168 foreach (string file in Directory.GetFiles(folderPath, pattern).Concat(Directory.GetFiles(folderPath, pattern2)))
169 {
170 Dictionary<string, string> dct_image = new Dictionary<string, string>();
171 image = "/Files/Files/"+designName+"/Products/" + file.Substring((file.LastIndexOf(@temp) + 1), (file.Length - file.LastIndexOf(@temp) - 1));
172 string metafield = "title";
173 var metadata = Dynamicweb.Content.Files.Metadata.EditorFactory.GetMetadataForFile(image);
174 title = metadata != null ? metadata.GetValue(metafield).ToString() : productName;
175 dct_image.Add(titleKey, title);
176 dct_image.Add(imageKey, image);
177 imagesList.Add(dct_image);
178 }
179 }
180
181 // Get Warranty from folder
182 if (Directory.Exists(warrantyFolderPath))
183 {
184 string temp = @"\";
185 string brandDocName = brand.Replace(" ", "00000");
186 brandDocName = string.Concat(brandDocName.Where(char.IsLetterOrDigit)).Replace("00000", " ");
187 string[] brandsParts = brandDocName.Split(' ');
188
189 foreach (string file in Directory.GetFiles(warrantyFolderPath, "*.pdf"))
190 {
191 Dictionary<string, string> dct_file = new Dictionary<string, string>();
192 string fileName = file.Substring((file.LastIndexOf(@temp) + 1), (file.Length - file.LastIndexOf(@temp) - 1));
193 bool hasFile = brandsParts.Any(x => fileName.Contains(x) && !string.IsNullOrEmpty(x));
194
195 if (hasFile)
196 {
197 document = "/Files/Files/" + designName + "/Documents/" + fileName;
198 string metafield = "title";
199 var metadata = Dynamicweb.Content.Files.Metadata.EditorFactory.GetMetadataForFile(document);
200 title = metadata != null ? metadata.GetValue(metafield).ToString() : fileName;
201 dct_file.Add(titleKey, title);
202 dct_file.Add(documentKey, document);
203 documentsList.Add(dct_file);
204 }
205 }
206
207 }
208 }
209 @using System;
210 @using System.Collections.Generic;
211 @using System.Web.Script.Serialization;
212 @{
213 Dictionary<string, Dictionary<string, Dictionary<string, string>>> product = new Dictionary<string, Dictionary<string, Dictionary<string, string>>>();
214 Dictionary<string, Dictionary<string, string>> variants = new Dictionary<string, Dictionary<string, string>>();
215 string productJSON = "";
216
217 if(loopVariantCombinations.Count > 0){
218 foreach (LoopItem variant in loopVariantCombinations){
219 string variantHref = "/"+ variant.GetString("Ecom:VariantCombination.Link.Clean") + "?PID=" + Dynamicweb.Frontend.PageView.Current().CurrentParagraph.ID.ToString(),
220 productNumberVariant = variant.GetString("Ecom:Product.Number"),
221 price = variant.GetString("Ecom:Product.Price"),
222 stock = variant.GetString("Ecom:Product.AvailableAmount"),
223 smallImage = variant.GetString("Ecom:Product.ImageSmall.Clean"),
224 id = variant.GetString("Ecom:VariantCombination.VariantID"),
225 variantName = variant.GetString("Ecom:VariantCombination.VariantText"),
226 variantShortDescription = variant.GetString("Ecom:VariantCombination.VariantText");
227 Dictionary<string, string> variantDict = new Dictionary<string, string>();
228
229 variantDict.Add("name", variantName);
230 variantDict.Add("id", id);
231 variantDict.Add("number", productNumberVariant);
232 variantDict.Add("price", price);
233 variantDict.Add("stock", stock);
234 variantDict.Add("smallImage", smallImage);
235 variantDict.Add("productIsFavorite", variant.GetString("Ecom:Product.IsProductInFavoriteList"));
236 variantDict.Add("addToList", variant.GetString("Ecom:Product.AddToFavorites"));
237 variantDict.Add("removeFromList", variant.GetString("Ecom:Product.RemoveFromFavorites"));
238
239 variants.Add(id, variantDict);
240 }
241 product.Add("product", variants);
242
243 }
244 productJSON = new JavaScriptSerializer().Serialize(product);
245
246 }
247
248
249 <div id="product-container" data-amountrequired='@Translate("amountIsRequired","Amount is required.")' data-pageId="@currentPageId" data-productId="@productId" data-variantId="@variantId" data-errorCombination1='@Translate("combinationNotAvailable","Combination not available")' >
250 <article id="product-description" class="col-xs-12 noPadding">
251 <div id="product-images" class="col-sm-6 col-xs-12 noPadding">
252 <div id="product-lg-image" class="col-xs-12 noPaddingLeft">
253 <figure class="text-center">
254 <img class="img-responsive" src="@productGetImage" alt="@productName" title="@productName" />
255 <div class="hidden" id="videoContainer">
256 <a id="playPause" href="#"><i class="fa fa-play"></i></a>
257 <video id="video" width="100%" src="">
258 Your browser does not support the video tag.
259 </video>
260 </div>
261 </figure>
262 </div>
263
264 <div id="imgThumbs" class="col-xs-12">
265 <ul>
266 @foreach (Dictionary<String, String> imageStr in imagesList)
267 {
268 bool isAnImage = imageStr["image"].Contains(".jpg");
269 string getimageImg = GetImage(imageStr["image"], 0, 150);
270 string getimageDataImgLarge = isAnImage ? GetImage(imageStr["image"], 800, 800) : imageStr["image"].ToString();
271 string getimageDataImg = isAnImage ? GetImage(imageStr["image"], 600, 600) : imageStr["image"].ToString();
272 string liClass = imagesList.IndexOf(imageStr) == 0 ? "active" : "";
273
274 try
275 {
276 string replaced = imageStr["image"].Substring(imageStr["image"].LastIndexOf('/') + 1).Replace(productNumber, "").Replace(".jpg", "").Replace(".mp4", "");
277
278 <li data-type='@replaced' class="@liClass">
279 @if (isAnImage)
280 {
281 <img data-large="@getimageDataImgLarge" data-image="@getimageDataImg" class="img-responsive" src="@getimageImg" title="@imageStr["title"]" alt="@imageStr["title"]"/>
282 }
283 else
284 {
285 <video data-image="@getimageDataImg" width="100%" src="@getimageDataImg">Your browser does not support the video tag.</video>
286 <i class="fa fa-play-circle-o videoPlayIcon"></i>
287 }
288 </li>
289 }
290 catch (Exception e)
291 {
292 // e.Message
293 }
294
295 }
296 </ul>
297 </div>
298
299 </div>
300 <div id="product-info-wrapper" class="col-sm-6 col-xs-12">
301 <p>@brand</p>
302 <h2 class="product-title padding-bottom">@productName</h2>
303 <div class="col-xs-12 noPadding productDetail">
304 @if (!string.IsNullOrEmpty(productIntro))
305 {
306 <div class="col-xs-12 noPadding productIntroduction">@productIntro</div>
307 }
308 @if (!string.IsNullOrEmpty(productNumber))
309 {
310 <span>@Translate("item", "Item #"):</span>
311 @productNumber
312 }
313 </div>
314
315 <div class="col-xs-12 noPadding details">
316 <p>@Translate("features","Features")</p>
317 @productDetails
318 </div>
319
320 <div class="col-xs-12 noPadding findStore">
321 @{
322 string brandFilter = brand.Replace(" ", "00000");
323 brandFilter = string.Concat(brandFilter.Where(char.IsLetterOrDigit)).Replace("00000", " ");
324
325 findStore = findStore + "&brand=" + brandFilter;
326
327 }
328 <a class="btn-primary" href="@findStore">@Translate("findStore", "Find a Store*")</a>
329 <p>@Translate("doesNotGuaranteeInventory", "*Does not guarantee inventory")</p>
330 </div>
331
332 <div class="col-xs-12 noPadding">
333 <div class="shareIcons">
334 <span>@Translate("share", "Share:")</span>
335 <ul id="socialMedia">
336 @foreach (string socialId in (areaItem["SocialNetworks"] ?? "").ToString().Split(','))
337 {
338 Item item = ItemManager.Storage.GetById("SocialLinks", socialId);
339 string domain = "https://" + System.Web.HttpContext.Current.Request.Url.Host;
340 if (item != null && !string.IsNullOrEmpty((item["ShareURL"] ?? "").ToString()))
341 {
342 string socialName = item["Name"].ToString();
343 string socialImage = item["Icon"].ToString();
344 string socialLink = item["ShareURL"].ToString() + domain + HttpContext.Current.Request.RawUrl;
345
346 //START CUSTOM CODE
347 if (socialName == "TikTok")
348 {
349 var iconLink = "/Files" + socialImage;
350 <li>
351 <a title="@socialName" class="fa" target="_blank" href="@socialLink">
352 <div style="background-color: white;mask: url('@iconLink') no-repeat center / contain; -webkit-mask: url('@iconLink') no-repeat center / contain; width:30px;height: 18.5px;"></div>
353 </a>
354 </li>
355 }
356 else
357 {
358 <li><a title="@socialName" class="@socialImage fa" target="_blank" href="@socialLink"></a></li>
359 }
360 //END CUSTOM CODE
361 }
362 }
363 </ul>
364 </div>
365 </div>
366
367 @*@if(!isGiftCard)
368 {
369 <div class="product-price inlineBlock">
370 @productPrice
371 </div>
372 }
373 <!-- Quantity prices -->
374 @if(loopProdPrices.Any() && showQuantity){
375 <div id="pricesContainer" class="col-xs-12 noPadding">
376 <h2>
377 @Translate("quantityPrices", "Quantity prices")
378 </h2>
379
380 <div id="quantityContainer" class="col-xs-12 noPadding">
381 <ul>
382 @foreach(LoopItem price in loopProdPrices) {
383 int quantity = price.GetInteger("Ecom:Product.Prices.Quantity");
384 string priceProd = price.GetString("Ecom:Product.Prices.PriceWithoutVATFormatted");
385
386 <li>
387 <span class="col-xs-6">@Translate("qty", "Qty") > @quantity</span>
388 <b class="col-xs-6 text-right">(@priceProd)</b>
389 </li>
390 }
391 </ul>
392 </div>
393
394 </div>
395 }*@
396
397 @*<div class="order-now">
398 <form name="addToCart" class="add-to-cart form-fields" action="@Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl((areaItem["MiniCart"] ?? "").ToString())" method="post" data-outofstock='@Translate("outOfStock", "Out of stock")'>
399 <input type="hidden" name="cartcmd" value="add"/>
400 <input type="hidden" name="redirect" value="false"/>
401 <input type="hidden" name="productID" value="@productId"/>
402 <input type="hidden" name="variantID" id="variantID" value="@variantId" @((string.IsNullOrEmpty(variantId)) ? "disabled='disabled'":"") />
403
404 @if(loopVariantGroups.Any()){
405 <div id="variantsContainer" class="col-xs-12 noPadding">
406 @foreach(LoopItem variantGroup in loopVariantGroups){
407 string variantGroupName = variantGroup.GetString("Ecom:VariantGroup.Name");
408 string variantGroupId = variantGroup.GetString("Ecom:VariantGroup.ID");
409 List<LoopItem> loopAvailableOptions = variantGroup.GetLoop("VariantAvailableOptions");
410
411 if(loopAvailableOptions.Any()){
412 <fieldset class="col-sm-6 col-xs-12 noPadding">
413 <label class="text-left" for="@variantGroupId">@variantGroupName</label>
414 <select class="full-width-input" name="@(variantGroupId)_options" id="@variantGroupId">
415 @foreach(LoopItem option in loopAvailableOptions){
416 string optionId = option.GetString("Ecom:VariantOption.ID");
417 string optionName = option.GetString("Ecom:VariantOption.Name");
418 bool optionSelected = option.GetBoolean("Ecom:VariantOption.Selected");
419
420 <option value="@optionId" @((optionSelected) ? "selected":"") >@optionName</option>
421 }
422 </select>
423 </fieldset>
424 }
425 }
426 </div>
427 }
428
429 @if(!isGiftCard)
430 {
431 <div id="stockStatus" class="col-xs-12 noPadding"><i class="fa @stockStatus"></i> @Translate("stock", "Stock")</div>
432 }
433 @if(pointPrice != "0") {
434 <div id="prodLoyaltyPoints" class="col-xs-12 noPadding"><i class="fa fa-gift"></i> @Translate("buyNowFor", "Buy now for") @pointPrice @Translate("loyaltyPoints", "loyalty points")</div>
435 }
436
437 <div class="col-xs-12 grayBox">
438 <div class="highlight-content text-right">
439 @if (showQuantity)
440 {
441 <fieldset class="quantity-container pull-left">
442 <label for="quantity">@Translate("quantity", "Quantity")</label>
443 <input data-outofstock='@Translate("outOfStock", "Out of stock")' data-stocktranslate='@Translate("currentStock", "The current stock is")' class="hidden quantity quantityInput" data-stock='@GetString("Ecom:Product.Stock")' maxlength="5" id="quantity" name="quantity" type="number" value="1"/>
444
445 <select data-width="25%" name="quantitySelect">
446
447 @if (loopVariantGroups.Any())
448 {
449 for (int num = 1; (num < 10); num++)
450 {
451 <option value="@num">@num</option>
452 }
453 }
454 else
455 {
456 for (int num = 1; (num < 10) && num <= productStock; num++)
457 {
458 <option value="@num">@num</option>
459 }
460 }
461
462 @if (productStock >= 10 || loopVariantGroups.Any())
463 {
464 <option value="10+">10+</option>
465 }
466
467 </select>
468
469 </fieldset>
470 }
471 else
472 {
473 <input data-outofstock='@Translate("outOfStock", "Out of stock")' data-stocktranslate='@Translate("currentStock", "The current stock is")' class="hidden quantity quantityInput" data-stock='@GetString("Ecom:Product.Stock")' maxlength="5" id="quantity" name="quantity" type="number" value="1"/>
474 }
475
476
477 @if( isGiftCard )
478 {
479 <fieldset class="pull-left giftCardAmount">
480 <label class="hidden" for="Amount">@Translate("amount", "Amount")</label>
481 <span>@GetString("Ecom:Product.Price.Currency.Symbol")</span>
482 <input placeholder="@Translate("amount")" type="number" name="Amount" step="0.01" min="0.01" value="@GetString("Ecom:Product.Price.Price")" />
483 </fieldset>
484 }
485
486 <a class="btn btn-bg" id="addToCartSubmit">
487 <i class="fa fa-shopping-cart"></i> <span data-add='@Translate("addToCart", "Add to cart")' data-added='@Translate("added", "Added")'>@Translate("addToCart", "Add to Cart")</span>
488 </a>
489 @if(GetBoolean("Ecom:Product.CanBuyForPoints")) {
490 <a class="btn btn-bg" id="addToCartPointsSubmit">
491 <i class="fa fa-shopping-cart"></i> <span data-add='@Translate("addWithPoints", "Add with points")' data-added='@Translate("added", "Added")'>@Translate("addWithPoints", "Add with points")</span>
492 </a>
493 }
494 </div>
495 </div>
496 <div class="col-xs-12 noPadding">
497 @if(isLoggedIn && isFrontEnd){
498 string icon = productIsFavorite ? "fa-heart" : "fa-heart-o" ;
499 <p>
500 <a class="btn-gold-outline" data-favorite="@productIsFavorite" id="favorite" data-user="@Dynamicweb.Security.UserManagement.User.IsExtranetUserLoggedIn()" data-addText='@Translate("addToWishlist","Add to Wish list")' data-removeText='@Translate("removeFromWishlist","Remove from Wish list")' href="@favoriteUrl"><i class="fa @icon"></i> @Translate(productIsFavorite ? "removeFromWishlist" : "addToWishlist")</a>
501 </p>
502 }
503
504 @if(!string.IsNullOrEmpty(productDetails)){
505 <div id="longDescription">
506 <b class="lead">@Translate("details", "Details")</b>
507 @productDetails
508 </div>
509 }
510 @{
511 string socialMedia = (areaItem["SocialNetworks"] ?? "").ToString();
512
513 if(!string.IsNullOrEmpty(socialMedia)){
514 <div class="shareIcons">
515 <span>@Translate("share", "Share")</span>
516 <ul>
517 @foreach (var socialID in socialMedia.Split(','))
518 {
519 var item = Dynamicweb.Content.Items.ItemManager.Storage.GetById("SocialLinks", socialID);
520 if (item["ShareURL"] != null && !string.IsNullOrEmpty(item["ShareURL"].ToString()))
521 {
522 string socialLink = (item["ShareURL"] ?? "").ToString();
523 string socialName = (item["Name"] ?? "").ToString();
524 string className = (item["Icon"] ?? "").ToString() ;
525
526 <li>
527 <a class="fa @className" target="_blank" href="@socialLink@GetCurrentUrl()"><span>@socialName</span></a>
528 </li>
529 }
530
531 }
532 </ul>
533 </div>
534 }
535 }
536 </div>
537 <input class="hidden" type="submit" value='@Translate("addToCart", "Add to Cart")' />
538 </form>
539 </div>*@
540 </div>
541
542 @* TABS / Long description / Product custom field(example) / Downloads (items) *@
543 <div id="tabsContainer" class="col-xs-12 noPadding">
544 <ul class="col-xs-12 noPadding">
545 @if(!string.IsNullOrEmpty(productDescription)){
546 <li class="active">
547 <a href="#description_tab">@Translate("description", "Description")</a>
548 </li>
549 }
550 @if(documentsList.Any()){
551 <li>
552 <a href="#warraty_tab">@Translate("warranty", "Warranty")</a>
553 </li>
554 }
555 @RenderSnippet("downloadItem")
556 @if(loopDetails.Any()) {
557 <li>
558 <a href="#productDdownloads_tab">@Translate("downloads", "Downloads") (product)</a>
559 </li>
560 }
561 </ul>
562
563 @if(!string.IsNullOrEmpty(productDescription)){
564 <div class="active col-xs-12" id="description_tab">@productDescription</div>
565 }
566 @if (documentsList.Any())
567 {
568 <div class="col-xs-12" id="warraty_tab">
569 <ul>
570 @foreach (Dictionary<String, String> doc in documentsList)
571 {
572 <li>
573 <a class="downloadFile" href="@doc["document"]"><i class='fa fa-file-pdf-o'></i> @doc["title"]</a>
574 </li>
575 }
576 </ul>
577 </div>
578 }
579
580 @if(areaItem["ProductDownloads"] != null && !string.IsNullOrWhiteSpace(areaItem["ProductDownloads"].ToString()))
581 {
582 RenderItemList(new
583 {
584 ItemType = "ProductDownloads",
585 ListSourceType = "Page",
586 ListSourcePage = Pageview.Area.Item["ProductDownloads"],
587 ItemFieldsList = "*",
588 ListTemplate = "ItemPublisher/List/ProductDownloads.cshtml",
589 ListPageSize = 99,
590 IncludeParagraphItems = true,
591 Filter = downloadsFilter
592 });
593 }
594 @if(loopDetails.Any()) {
595 <div class="col-xs-12" id="productDdownloads_tab">
596 <ul>
597
598 @foreach (LoopItem detail in loopDetails){
599 string file = detail.GetString("Ecom:Product:Detail.Image.Clean");
600 var metadata = Dynamicweb.Content.Files.Metadata.EditorFactory.GetMetadataForFile(file);
601 string temp = @".",
602 metafield = "title",
603 fileTitle = metadata != null ? metadata.GetValue(metafield).ToString() : Translate("download", "Download"),
604 substringFile = file.Substring((file.LastIndexOf(temp) + 1), (file.Length - file.LastIndexOf(temp) - 1)),
605 icon = iconFiles.ContainsKey(substringFile) ? iconFiles[substringFile] : "fa-file-pdf-o" ;
606
607 <li>
608 <a class="downloadFile" href="@file"><i class='fa @icon'></i> @fileTitle</a>
609 </li>
610 }
611 </ul>
612 </div>
613 }
614 </div>
615
616 </article>
617
618 @* Related Products *@
619 @if(GetLoop("ProductRelatedGroups").Any()){
620 <div class="col-xs-12 noPadding" id="relatedContainer">
621 @foreach (LoopItem group in GetLoop("ProductRelatedGroups")){
622 List<LoopItem> relatedProducts = group.GetLoop("RelatedProducts");
623
624 if(relatedProducts.Any()){
625 <div class="col-xs-12 noPadding relatedContainer">
626 <h2 class="productTitles">@group.GetString("Ecom:Product:RelatedGroup.Name")</h2>
627
628 <ul class="relatedList row">
629 @foreach (LoopItem productItem in relatedProducts.Take(4))
630 {
631 string relatedProductName = productItem.GetString("Ecom:Product.Name");
632 string relatedProductNumber = productItem.GetString("Ecom:Product.Number");
633 string relatedProductLink = productItem.GetString("Ecom:Product.PrimaryOrCurrentPageID") != Pageview.Page.ID.ToString() ? "/Default.aspx?ID=" + productItem.GetString("Ecom:Product.PrimaryOrCurrentPageID") + "&ProductID=" + productItem.GetString("Ecom:Product.ID") : "/Default.aspx?ID=" + Pageview.Page.ID.ToString() + "&ProductID=" + productItem.GetString("Ecom:Product.ID");
634 string relatedImage = (!string.IsNullOrEmpty(productItem.GetString("Ecom:Product.ImageSmall.Clean"))) ? productItem.GetString("Ecom:Product.ImageSmall.Clean") : "/Files/Files/"+designName+"/Products/Images/" + relatedProductNumber + ".jpg";
635
636 <li class="col-md-3 col-sm-6 col-xs-12">
637 <figure class="col-xs-12 noPadding">
638 <a href="@relatedProductLink">
639 <img src="@GetImage(relatedImage, 400, 0, 0, 0, 0, 0, "jpg")" alt="@relatedProductName" title="@relatedProductName" class="img-responsive" />
640 </a>
641 </figure>
642 <div class="col-xs-12 noPadding">
643 @*<div class="relatedProdRatingContainer">
644 @Rating(productItem.GetDouble("Ecom:Product.Rating"))
645 </div>*@
646 <h3 class=" h2 col-xs-12 noPadding text-center"><a href="@relatedProductLink">@relatedProductName</a>
647 </h3>
648 @*<span class="listPrice" itemprop="price">@productItem.GetString("Ecom:Product.Price")</span>*@
649 </div>
650 </li>
651 }
652 </ul>
653 </div>
654 }
655 }
656 </div>
657 }
658
659 @* Reviews *@
660 @*<div class="col-xs-12 noPadding" id="reviewsContainer">
661 <h2 class="productTitles">@Translate("reviews", "Reviews")</h2>
662 <div id="reviewWithSuccess" class="hidden">
663 <b>@Translate("Review submited successfully!")</b><br/>
664 @Translate("Your review needs to be activated to be displayed at the website")
665 </div>
666 @{
667 var comments = GetLoop("Comments.Newfirst");
668 string langId = GetString("Ecom:Product.LanguageID");
669 string pageViewUrl = string.Format("{0}#reviewsContainer", GetGlobalValue("Global:Pageview.Url"));
670 string accessUserName = GetGlobalValue("Global:Extranet.Name");
671 string accessUserEmail = GetGlobalValue("Global:Extranet.Email");
672
673 if (comments.Any())
674 {
675 <ul id="productReviews" class="col-xs-12 noPadding">
676 @foreach (LoopItem comment in comments)
677 {
678 DateTime dat_date = comment.GetDate("CreatedDate");
679 string dateAndName = string.Format("{0} {1}, {2}, {3}", dat_date.ToString("MMM"), dat_date.Day.ToString(), dat_date.Year.ToString(), comment.GetString("Name"));
680 string email = comment.GetString("Email");
681 string website = comment.GetString("Website");
682
683 <li id="comment@(comment.GetString("ID"))" class="col-xs-12 noPadding">
684 <div class="col-xs-12 col-sm-4 noPaddingLeft">
685 @Rating(comment.GetDouble("Rating"))
686 <span class="dateAndName">@dateAndName</span>
687 <span class="email"><a href="mailto:@email">@email</a></span>
688 @if(!string.IsNullOrWhiteSpace(website))
689 {
690 <span class="website"><a href="@website">@website.Replace("http://", "").Replace("https://", "")</a></span>
691 }
692 </div>
693 <div class="col-xs-12 col-sm-8 noPaddingRight">
694 @comment.GetString("Text")
695 </div>
696 </li>
697 }
698 </ul>
699 }
700
701 <div class="col-xs-12 noPadding" id="reviewFormContainer">
702 <h2>@Translate("addYourReview", "Add your review")</h2>
703 <form class="DMForms col-xs-12 noPadding" method="post" action="/Default.aspx?ID=@currentPageId" id="commentform">
704 <input type="hidden" name="_sys_to_email" value="bot@dynamicweb.com">
705 <input type="hidden" name="Comment.Command" id="Comment.Command" value="create"/>
706 <input type="hidden" name="Comment.Active" value="false"/>
707 <input type="hidden" name="Comment.ItemType" value="ecomProduct"/>
708 <input type="hidden" name="Comment.ItemID" value="@productId"/>
709 <input type="hidden" name="Comment.LangID" value="@langId"/>
710 <input type="hidden" name="Comment.Continue" value="@pageViewUrl"/>
711 <input type="hidden" name="Comment.ParentID" id="Comment.ParentID" value="0"/>
712
713 $1$ Notify #1#
714 <input type="hidden" name="Comment.Notify" value="true"/>
715 <input type="hidden" name="Comment.NotifyTemplate" value="Comments/Notify.cshtml"/>
716 <input type="hidden" name="Comment.NotifySubject" id="Comment.NotifySubject" value="@subject"/>
717 <input type="hidden" name="Comment.NotifySenderEmail" value="@senderEmail"/>
718 <input type="hidden" name="Comment.NotifySenderName" value="@senderName"/>
719 <input type="hidden" name="Comment.NotifyEmail" value="@notifyEmail"/>
720
721 <fieldset>
722 <label>@Translate("Rating")</label>
723 <ul id="commentRating">
724 <li><input type="radio" name="Comment.Rating" value="5"/><i class="fa fa-star"></i></li>
725 <li><input type="radio" name="Comment.Rating" value="4"/><i class="fa fa-star"></i></li>
726 <li><input type="radio" name="Comment.Rating" value="3"/><i class="fa fa-star"></i></li>
727 <li><input type="radio" name="Comment.Rating" value="2"/><i class="fa fa-star"></i></li>
728 <li><input type="radio" name="Comment.Rating" value="1"/><i class="fa fa-star"></i></li>
729 </ul>
730 </fieldset>
731 <fieldset class="TextInput mandatory">
732 <label for="Comment.Name">@Translate("name", "Name")</label>
733 <input type="text" name="Comment.Name" id="Comment.Name" value="@accessUserName"/>
734 </fieldset>
735 <fieldset class="TextInput">
736 <label for="Comment.Email">@Translate("email", "E-mail")</label>
737 <input type="text" name="Comment.Email" id="Comment.Email" value="@accessUserEmail"/>
738 <span class="inputNote">@Translate("addYourEmailToBeNotifiedWhenYourReviewIsApproved", "Add your email to be notified when your review is approved.")</span>
739 </fieldset>
740 <fieldset class="Textarea mandatory">
741 <label for="Comment.Text">@Translate("comment", "Comment")</label>
742 <textarea name="Comment.Text" id="Comment.Text" rows="10" cols="50"></textarea>
743 </fieldset>
744
745 <input class="btn btn-bg" type="submit" value="@(Translate("submit", "Submit"))"/>
746 </form>
747 </div>
748
749 }
750 </div>*@
751 </div>
752
753 @SnippetStart("OGMeta")
754 <meta property="og:title" content='@productName' />
755 <meta property="og:image" content='@Pageview.GlobalTags.GetTagByName("Global:Request.Scheme").Value.ToString()://@Pageview.GlobalTags.GetTagByName("Global:Request.Host").Value.ToString()@imagePattern' />
756 <meta property="og:site_name" content='@areaItem["CompanyName"]' />
757 <meta property="og:url" content='@Pageview.GlobalTags.GetTagByName("Global:Request.Scheme").Value.ToString()://@Pageview.GlobalTags.GetTagByName("Global:Request.Host").Value.ToString()@Pageview.GlobalTags.GetTagByName("Global:Pageview.Url").Value.ToString()' />
758 <meta property="og:description" content='@StripHtml(productIntro)' />
759 <meta property="og:type" content="product" />
760 <meta property="og:locale" content='@Pageview.GlobalTags.GetTagByName("Global:Area.LongLang").Value.ToString().Replace("-", "_")' />
761 @SnippetEnd("OGMeta")
762
763 @SnippetStart("jsOnLoad")
764 onLoadProductDetail({obj_product:@productJSON});
765 @SnippetEnd("jsOnLoad")
766
767 @functions {
768 public static string StripHtml(string source)
769 {
770 return Regex.Replace(source, "<.*?>", string.Empty);
771 }
772 }
773 @helper Rating(double rating)
774 {
775 string starClass = string.Empty;
776 string halfStar = string.Empty;
777
778 <ul class="rating">
779 @for(int s=5;s>0;s--){
780 if(s == Math.Ceiling(rating)){
781 starClass = "class='star'";
782 halfStar = !(rating - Math.Round(rating) == 0) ? "fa-star-half-o" : "fa-star" ;
783 }else{
784 starClass = "";
785 halfStar = "fa-star";
786 }
787
788 <li data-star="@s" @starClass><i class="fa @halfStar"></i></li>
789 }
790 </ul>
791 }