Error executing template "Designs/Dwsimple/eCom/Product/Product-LiveIntegration-ListeFabrik.cshtml"
System.Data.SqlClient.SqlException (0x80131904): Transaction (Process ID 59) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
at System.Data.SqlClient.SqlDataReader.TryHasMoreRows(Boolean& moreRows)
at System.Data.SqlClient.SqlDataReader.TryReadInternal(Boolean setTimeout, Boolean& more)
at System.Data.SqlClient.SqlDataReader.TryNextResult(Boolean& more)
at System.Data.SqlClient.SqlDataReader.NextResult()
at Pims.Dal.Table.MY(PXmlQuery T, DbTransaction A, PXmlMethod V)
at Pims.Dal.Table.UN.Q()
at Pims.NullLongJobInformer.InformOnOperation(String name, String information, Action operation)
at Pims.Dal.Table.ExecuteQuery(PXmlQuery query)
at Perfion.Api.PerfionApi.ExecuteQuery(PXmlQuery query)
at Perfion.Api.PerfionApi.ExecuteQueryAsXml(PXmlQuery query)
at Perfion.Api.PerfionApi.ExecuteQueryAsXml(String queryAsXml)
at ListeFabrik.CustomModules.Classes.Perfion.PerfionTasks.ExecuteQueryAsXml(String query)
at ListeFabrik.CustomModules.Classes.Perfion.PerfionTasks.FillFeatures(PerfionProduct& perfionProduct, String perfionId, String view, Boolean display)
at ListeFabrik.CustomModules.Classes.Perfion.PerfionTasks.GetPerfionProductById(String perfionId)
at CompiledRazorTemplates.Dynamic.RazorEngine_8c25264a1e804127a7ea964f57441e77.Execute() in C:\inetpub\Dynamicweb\KBH ListeFabrik\Files\Templates\Designs\Dwsimple\eCom\Product\Product-LiveIntegration-ListeFabrik.cshtml:line 275
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.b__0(TextWriter writer)
at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter)
at Dynamicweb.Rendering.Template.RenderRazorTemplate()
ClientConnectionId:a376d92f-08fb-406f-8107-6da52419efff
Error Number:1205,State:56,Class:13
1 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>>
2 @using System;
3 @using System.Web;
4 @using ListeFabrik.CustomModules;
5 @using ListeFabrik.CustomModules.Classes;
6 @using ListeFabrik.CustomModules.Classes.Perfion;
7 @using ListeFabrik.CustomModules.Classes.Perfion.XmlAbstractions;
8 @using System.Web.Helpers;
9 @using Dynamicweb.Security.UserManagement;
10
11 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>>
12 @using System;
13 @using System.Web;
14 @using ListeFabrik.CustomModules;
15 @using ListeFabrik.CustomModules.Classes;
16
17 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>>
18 @using System;
19 @using System.Web;
20 @using System.Text.RegularExpressions
21
22
23 @functions{
24 public class WrapMethods
25 {
26 //Gets the contrasting color
27 public static string getContrastYIQ(string hexcolor)
28 {
29 if (hexcolor != "")
30 {
31 hexcolor = Regex.Replace(hexcolor, "[^0-9a-zA-Z]+", "");
32
33 int r = Convert.ToByte(hexcolor.Substring(0, 2), 16);
34 int g = Convert.ToByte(hexcolor.Substring(2, 2), 16);
35 int b = Convert.ToByte(hexcolor.Substring(4, 2), 16);
36 int yiq = ((r * 299) + (g * 587) + (b * 114)) / 1000;
37
38 if (yiq >= 128)
39 {
40 return "black";
41 }
42 else
43 {
44 return "white";
45 }
46 }
47 else
48 {
49 return "black";
50 }
51 }
52
53
54 //Truncate text
55 public static string Truncate (string value, int count, bool strip=true)
56 {
57 if (strip == true){
58 value = StripHtmlTagByCharArray(value);
59 }
60
61 if (value.Length > count)
62 {
63 value = value.Substring(0, count - 1) + "...";
64 }
65
66 return value;
67 }
68
69
70 //Strip text from HTML
71 public static string StripHtmlTagByCharArray(string htmlString)
72 {
73 char[] array = new char[htmlString.Length];
74 int arrayIndex = 0;
75 bool inside = false;
76
77 for (int i = 0; i < htmlString.Length; i++)
78 {
79 char let = htmlString[i];
80 if (let == '<')
81 {
82 inside = true;
83 continue;
84 }
85 if (let == '>')
86 {
87 inside = false;
88 continue;
89 }
90 if (!inside)
91 {
92 array[arrayIndex] = let;
93 arrayIndex++;
94 }
95 }
96 return new string(array, 0, arrayIndex);
97 }
98
99 //Make the correct count of columns
100 public static string ColumnMaker(int Col, string ScreenSize)
101 {
102 string Columns = "";
103
104 switch (Col)
105 {
106 case 1:
107 Columns = "col-"+ScreenSize+"-12";
108 break;
109
110 case 2:
111 Columns = "col-"+ScreenSize+"-6";
112 break;
113
114 case 3:
115 Columns = "col-"+ScreenSize+"-4";
116 break;
117
118 case 4:
119 Columns = "col-"+ScreenSize+"-3";
120 break;
121
122 default:
123 Columns = "col-"+ScreenSize+"-3";
124 break;
125 }
126
127 return Columns;
128 }
129
130
131 private string Custom(string firstoption, string secondoption)
132 {
133 if (firstoption == "custom")
134 {
135 return secondoption;
136 }
137 else
138 {
139 return firstoption;
140 }
141 }
142 }
143 }
144
145
146 @helper GetProductList(dynamic Loop, int ColMD = 3, int ColSM = 3, int ColXS = 1)
147 {
148 var area = Dynamicweb.Services.Areas.GetArea(Pageview.Area.ID);
149
150 string searchWords = HttpContext.Current.Request.QueryString["search"];
151 bool isSearch = (!string.IsNullOrWhiteSpace(searchWords)) ? true : false;
152
153 int Count = 0;
154
155 string ColumnsMD = WrapMethods.ColumnMaker(ColMD, "md");
156 string ColumnsSM = WrapMethods.ColumnMaker(ColSM, "sm");
157 string ColumnsXS = WrapMethods.ColumnMaker(ColXS, "xs");
158
159
160 foreach (LoopItem product in Loop)
161 {
162 var standardPrice = product.GetDouble("Ecom:Product.DBPrice");
163 var customerPrice = product.GetDouble("Ecom:Product.Price.Price");
164 string perUnitText = "/" + product.GetString("Ecom:Product:Field.ProductUnit");
165 bool soldByLength = perUnitText == "/M";
166 var currency = product.GetString("Ecom:Product.Price.Currency.Code");
167 string Image = product.GetString("Ecom:Product:Field.MainProductImage");
168 string Picto = product.GetString("Ecom:Product:Field.ProductPictogram");
169 string GroupLink = product.GetString("Ecom:Product.LinkGroup.Clean");
170 string Name = product.GetString("Ecom:Product.Name");
171 string Description = product.GetString("Ecom:Product.ShortDescription");
172 string Discount = product.GetString("Ecom:Product.Discount.Price");
173 string Price = product.GetString("Ecom:Product.Price");
174 string RawPrice = product.GetString("Ecom:Product.Price.PricePIP");
175 string Filters = product.GetString("Ecom:Product:Field.FilterValues");
176 string filterClasses = string.Empty;
177 string imagealttext = product.GetString("Ecom:Product:Field.ProductImageAltText");
178
179 if (!string.IsNullOrWhiteSpace(Filters))
180 {
181 filterClasses = "filter-" + Filters.Trim().Replace(",", " filter-");
182 }
183
184 if (isSearch)
185 {
186 // If the primary group is not in the current shop, we have to take the group link to the first group that's in the shop
187 // Otherwise DW takes the first group regardless if it belongs to the area or not
188 bool isPrimaryGroupInShop = false;
189
190 string primaryGroupID = product.GetString("Ecom:Product.PrimaryGroupID");
191
192 if (!string.IsNullOrEmpty(primaryGroupID))
193 {
194 var primaryGroup = Dynamicweb.Ecommerce.Products.Group.GetGroupById(primaryGroupID);
195 isPrimaryGroupInShop = primaryGroup.Shops.Any(x => x.Id == area.EcomShopId);
196 }
197
198 if (!isPrimaryGroupInShop)
199 {
200 foreach (var loopGroup in product.GetLoop("AssociatedGroups"))
201 {
202 var group = Dynamicweb.Ecommerce.Products.Group.GetGroupById(loopGroup.GetString("Ecom:Group.ID"));
203 if (group.ShopId == area.EcomShopId)
204 {
205 GroupLink = loopGroup.GetString("Ecom:Group.Link.Clean") + "&ProductID=" + product.GetString("Ecom:Product.ID.UrlEncoded");
206 break;
207 }
208 }
209 }
210 }
211
212 <div class="productlist grid-item @ColumnsMD @ColumnsSM @ColumnsXS @filterClasses"
213 data-name="@HttpUtility.HtmlEncode(Name.ToLower())"
214 data-price="@RawPrice"
215 data-filter-classes="@filterClasses">
216
217 <div class="boxproduct wp-block product">
218 <div class="listproductright">
219 <a href="@GroupLink" title="@HttpUtility.HtmlEncode(Name)">
220 <figure style="" class="productfigure">
221 @if (!string.IsNullOrEmpty(Image))
222 {
223 <img alt="@HttpUtility.HtmlEncode(imagealttext)" src="@PIMCommerceUtilities.GetPerfionImageUrl(Image,"250x250")" class="img-responsive img-center">
224 }
225 </figure>
226 @if (!string.IsNullOrEmpty(Picto))
227 {
228 <span class="product-picto"><img alt="" src="@PIMCommerceUtilities.GetPerfionImageUrl(Picto, "50x50")" /></span>
229 }
230 </a>
231 </div>
232 <div class="extracolumn">
233 <p class="product-title"><a href="@GroupLink">@Name.Replace("/", " / ")</a></p>
234 <p>@Translate("Product number", "Product number"): <span>@product.GetString("Ecom:Product.Number")</span></p>
235 </div>
236 <div class="listproductleft wp-block-footer">
237 @if (customerPrice < standardPrice)
238 {
239 <span class="productprice price pull-right" style=" font-size: 16px !important" content="@product.GetString("Ecom:Product.Price.Price").Replace(",", ".")"><strong>@product.GetString("Ecom:Product.Price.Price") @currency@perUnitText</strong></span><span> </span>
240 <span class="productpricebr"></span>
241 <p class="productoldprice price" style="margin-top: -15px !important; padding-top: 0px !important; color: #AAAAAA !important; font-size: 12px !important; text-align: right; text-decoration: line-through">@standardPrice.ToString("F") @currency@perUnitText</p>
242 }
243 else
244 {
245 <span class="productprice price pull-right" style="font-size: 16px !important" content="@product.GetString("Ecom:Product.Price.Price").Replace(",", ".")"><strong>@product.GetString("Ecom:Product.Price.Price") @currency@perUnitText</strong></span><span> </span>
246 }
247 </div>
248 </div>
249
250 </div>
251
252 Count++;
253
254 if (Count == ColMD)
255 {
256 <div class="row"></div>
257 Count = 0;
258 }
259 }
260 }
261
262
263 @{
264 string image = "";
265 string imageBig = "";
266 var grouplink = "";
267 string productname = "";
268 var pid = GetValue("Ecom:Product.ID");
269
270 var pageid = GetValue("Ecom:Product:Page.ID");
271 var productid = GetValue("Ecom:Product.ID");
272
273 bool hasVariants = GetInteger("Ecom:Product.VariantCount") > 0;
274
275 PerfionProduct perfionProduct = PerfionTasks.GetPerfionProductById(GetString("Ecom:Product:Field.PerfionID"));
276 var productfiles = perfionProduct.GetFiles();
277 var productreports = perfionProduct.GetReports(GetString("Ecom:Product.PrimaryOrFirstGroupID"));
278 var featureGroups = perfionProduct.GetFilledFeatureGroups();
279 var ProductGroupText = perfionProduct.FirstOrDefault(pp => pp.Name == "VareGruppe")?.Text;
280 bool RenderWhitePaintedText = ProductGroupText?.Equals("1840") ?? false;
281 bool RenderPrimedText = ProductGroupText?.Equals("1841") ?? false;
282
283 string availableLengthsField = GetString("Ecom:Product:Field.AvailableLengths");
284 List<string> availableLengths = new List<string>();
285 if (!string.IsNullOrWhiteSpace(availableLengthsField))
286 {
287 availableLengths = availableLengthsField.Split(',').OrderBy(x => int.Parse(x)).ToList();
288 }
289
290 string perUnitText = "/" + GetString("Ecom:Product:Field.ProductUnit");
291 bool soldByLength = perUnitText == "/M";
292 int perLengthLines = 3;
293 }
294
295 @if (hasVariants)
296 {
297 //Reload page on back button press (variants)
298 <input type="hidden" id="refreshed" value="no">
299 <script type="text/javascript">
300 onload = function () {
301 var e = document.getElementById("refreshed");
302 if (e.value == "no") e.value = "yes";
303 else { e.value = "no"; location.reload(); }
304 }
305 </script>
306 }
307
308 <script type="text/javascript">
309 /* CLASSES */
310 function VariantGroup(id, name) { this.Id = id; this.Name = name; this.Options = []; }
311 function VariantOption(id, name) { this.Id = id; this.Name = name; }
312 function VariantCombination(id) { this.Id = id; }
313 function VariantSelector() { this.Groups = []; this.Combinations = []; }
314
315 /* FUNCTIONS */
316 function ByGroupOrder(varid) {
317 var vars = [];
318 for (g = 0; g < Selector.Groups.length; g++) {
319 for (o = 0; o < Selector.Groups[g].Options.length; o++) {
320 for (v = 0; v < varid.length; v++) {
321 if (Selector.Groups[g].Options[o].Id == varid[v]) {
322 vars.push(varid[v]);
323 }
324 }
325 }
326 }
327 return vars;
328 }
329
330 function PresetCombo(combono, value) {
331 document.getElementById('COMBO' + combono).value = value;
332 UpdateCombo(combono);
333 }
334
335 function CombinationExist(query) {
336 found = false;
337 for (ci = 0; ci < Selector.Combinations.length; ci++) {
338 combis = Selector.Combinations[ci].Id.split(".");
339 queryfoundincombination = true;
340 for (q = 0; q < query.length; q++) {
341 queryitemfoundincombination = false;
342 for (cs = 0; cs < combis.length; cs++) {
343 if (combis[cs] == query[q]) queryitemfoundincombination = true;
344 }
345 if (!queryitemfoundincombination) queryfoundincombination = false;
346 }
347 if (queryfoundincombination) found = true;
348 }
349 return found;
350 }
351
352 function FillCombo(combono) {
353
354 ClearCombo(combono);
355
356 @{
357 var selectiontext = @Translate("Choose variant", "Choose variant");
358 }
359
360 var op = document.createElement("option");
361 op.text = "@selectiontext";
362 op.value = "";
363 document.getElementById('COMBO' + combono).options.add(op);
364
365 for (i = 0; i < Selector.Groups[combono].Options.length; i++) {
366
367 option = Selector.Groups[combono].Options[i];
368 includeoption = true;
369
370 curcombination = [];
371 for (g = 0; g < combono; g++) {
372 curcombination.push(document.getElementById('COMBO' + g).value);
373 }
374 curcombination.push(option.Id);
375
376 includeoption = CombinationExist(curcombination);
377
378
379 if (includeoption) {
380 var op = document.createElement("option");
381 op.text = option.Name;
382 op.value = option.Id;
383 document.getElementById('COMBO' + combono).options.add(op);
384 document.getElementById('COMBO' + combono).disabled = false;
385 }
386
387 }
388 }
389
390 function ClearCombo(combono) {
391 while (document.getElementById('COMBO' + combono).options.length > 0) {
392 document.getElementById('COMBO' + combono).options[0] = null;
393 }
394 document.getElementById('COMBO' + combono).disabled = true;
395 }
396
397 function SetSpinner(){
398 var opts = {
399 lines: 9, // The number of lines to draw
400 length: 0, // The length of each line
401 width: 10, // The line thickness
402 radius: 18, // The radius of the inner circle
403 corners: 1, // Corner roundness (0..1)
404 rotate: 0, // The rotation offset
405 direction: 1, // 1: clockwise, -1: counterclockwise
406 color: '#000', // #rgb or #rrggbb or array of colors
407 speed: 1, // Rounds per second
408 trail: 35, // Afterglow percentage
409 shadow: false, // Whether to render a shadow
410 hwaccel: false, // Whether to use hardware acceleration
411 className: 'spinner', // The CSS class to assign to the spinner
412 zIndex: 2e9, // The z-index (defaults to 2000000000)
413 top: '50%', // Top position relative to parent
414 left: '50%' // Left position relative to parent
415 };
416
417 var target = document.getElementById('productinfo');
418 spinner = new Spinner(opts).spin(target);
419 }
420
421 function UpdateCombo(combono) {
422 if (combono < Selector.Groups.length - 1) {
423
424 if (document.getElementById('COMBO' + combono).value != "") FillCombo((combono + 1));
425
426 if (combono > -1) {
427 fromcombo = (document.getElementById('COMBO' + combono).value == "") ? combono + 1 : combono + 2;
428 for (c = fromcombo; c < Selector.Groups.length; c++) {
429 ClearCombo(c);
430 }
431 }
432 }
433 else {
434 if (!presetting && (document.getElementById('COMBO' + (Selector.Groups.length - 1)).value != "")) {
435 id = "";
436 for (c = 0; c < Selector.Groups.length; c++) {
437 id += (c == 0) ? document.getElementById('COMBO' + c).value : "." + document.getElementById('COMBO' + c).value;
438 }
439
440 //Spinner
441 SetSpinner();
442
443 var groupid = '';
444 if ('@GetString("Ecom:Group.ID")' != '') {
445 groupid = '&GroupID=@GetString("Ecom:Group.ID")';
446 }
447
448 location.href = '/Default.aspx?ID=@pageid' + groupid + '&ProductID=@productid&VariantID=' + id;
449 }
450 }
451 }
452
453 function UpdateCart() {
454 document.getElementById('minipagecart').className = " dw-minicart-update";
455 }
456 </script>
457
458 @{
459 string imagesize = "";
460 string infosize = "";
461
462 switch (Pageview.Area.Item["EcommerceProductcardImageSize"].ToString())
463 {
464 case "small":
465 imagesize = "4";
466 infosize = "8";
467 break;
468
469 case "medium":
470 imagesize = "6";
471 infosize = "6";
472 break;
473
474 case "large":
475 imagesize = "12";
476 infosize = "12";
477 break;
478 }
479 }
480
481 <div class="col-md-12 col-sm-12 col-xs-12">
482 <div class="row product">
483 <div class="col-md-@imagesize col-sm-6 col-xs-12">
484 <div class="product-gallery">
485 <!-- Discount sticker -->
486 @if (GetString("Ecom:Product.Discount.Price") != GetString("Ecom:Product.Price"))
487 {
488 if (@Pageview.Area.Item["EcommerceStickerType"].ToString() == "ribbon")
489 {
490 <span class="ribbon base">@Translate("On sale!", "On sale!")</span>
491 }
492 if (@Pageview.Area.Item["EcommerceStickerType"].ToString() == "ball")
493 {
494 <span class="ball">@Translate("On sale!", "On sale!")</span>
495 }
496 }
497
498 @{
499 var productPerfionImages = perfionProduct.GetGalleryImages();
500 image = GetString("Ecom:Product:Field.MainProductImage");
501 }
502
503 <div id="primary-image">
504 <img id="imageresource"
505 src="@PIMCommerceUtilities.GetPerfionImageUrl(image, "500x500")"
506 class="img-responsive"
507 alt="@GetString("Ecom:Product:Field.ProductImageAltText")"
508 title="@GetString("Ecom:Product:Field.ProductImageAltText")"
509 data-image="@PIMCommerceUtilities.GetPerfionImageUrl(image, "700x700")" />
510 </div>
511
512 <div>
513 <div>
514 @if (productPerfionImages.Count > 0)
515 {
516 <div class="thumbnail-images">
517 @if (!productPerfionImages.Any(x => x.Text == image))
518 {
519 <div class="image-thumbnail">
520 <img src="@PIMCommerceUtilities.GetPerfionImageUrl(image, "75x75")"
521 alt="@GetString("Ecom:Product:Field.ProductImageAltText")"
522 title="@GetString("Ecom:Product:Field.ProductImageAltText")"
523 data-image="@PIMCommerceUtilities.GetPerfionImageUrl(image, "500x500")"
524 data-imagezoom="@PIMCommerceUtilities.GetPerfionImageUrl(image, "700x700")" />
525 </div>
526 }
527 @foreach (var imageFeature in productPerfionImages)
528 {
529 image = imageFeature.Text;
530 <div class="image-thumbnail">
531 <img src="@PIMCommerceUtilities.GetPerfionImageUrl(image, "75x75")"
532 alt="@GetString("Ecom:Product:Field.ProductImageAltText")"
533 title="@GetString("Ecom:Product:Field.ProductImageAltText")"
534 data-image="@PIMCommerceUtilities.GetPerfionImageUrl(image, "500x500")"
535 data-imagezoom="@PIMCommerceUtilities.GetPerfionImageUrl(image, "700x700")" />
536 </div>
537 }
538 </div>
539 }
540 </div>
541 </div>
542 </div>
543 </div>
544
545 <div class="col-md-@infosize col-sm-6 col-xs-12">
546 <form name="@pid" id="@pid" method="post" action="/Default.aspx">
547 @GetValue("Ecom:Product.Form.Clean")
548 <div class="product-info" vocab="http://schema.org/" typeof="Product" id="productinfo">
549 <h1><span property="name">@GetString("Ecom:Product.Name")</span> @GetString("Ecom:Product.SelectedVariantComboName")</h1>
550 <hr />
551 <h2 style="font-size:18px;">@GetString("Ecom:Product:Field.ProductTextH2")</h2>
552 <span class="clearfix"></span>
553
554 <div property="description" id="description">
555 @GetString("Ecom:Product.ShortDescription")
556 </div>
557
558 <span class="clearfix"></span>
559
560 <!-- DYNAMIC VARIANT OPTION -->
561 <div id="productvariants">
562 <!-- SELECTOR MAIN -->
563 <script type="text/javascript">
564 var presetting = true;
565 var VariantID = "@GetValue("Ecom:Product.SelectedVariantComboID")";
566 var VariantOptions = VariantID.split('.');
567 var Page = "/Default.aspx?ID=@pageid&ProductID=@productid";
568
569 var Selector = new VariantSelector();
570 </script>
571
572 <script type="text/javascript">
573 @foreach (LoopItem variantgroup in GetLoop("VariantGroups"))
574 {
575 var variantgroupid = variantgroup.GetValue("Ecom:VariantGroup.ID");
576 var variantgroupname = variantgroup.GetString("Ecom:VariantGroup.Label");
577
578 <text>group = new VariantGroup("@variantgroupid", "@variantgroupname");</text>
579 foreach (LoopItem variantoption in variantgroup.GetLoop("VariantOptions"))
580 {
581 var variantoptionid = variantoption.GetValue("Ecom:VariantOption.ID");
582 var variantoptionname = variantoption.GetString("Ecom:VariantOption.Name");
583 <text>group.Options.push(new VariantOption("@variantoptionid", "@variantoptionname"));</text>
584 }
585 <text>Selector.Groups.push(group);</text>
586 }
587 </script>
588
589 <script type="text/javascript">
590 @foreach (LoopItem variantcomb in GetLoop("VariantCombinations"))
591 {
592
593 var variantcombid = variantcomb.GetValue("Ecom:VariantCombination.VariantID");
594 <text>Selector.Combinations.push(new VariantCombination("@variantcombid"));</text>
595
596 }
597 </script>
598
599 <script type="text/javascript">
600 if (Selector.Groups.length > 0) {
601 for (g = 0; g < Selector.Groups.length; g++) {
602 document.write("<br><b>" + Selector.Groups[g].Name + "</b><br>");
603 document.write("<select id='COMBO" + g + "' style='width:40%' onchange=\"UpdateCombo(" + g + ");\">\n</select><br>\n");
604 }
605
606 FillCombo(0);
607 for (vo = 0; vo < VariantOptions.length; vo++) {
608 PresetCombo(vo, VariantOptions[vo]);
609 }
610 presetting = false;
611 }
612 </script>
613 </div>
614
615
616 <div property="offers" typeof="Offer">
617 <div class="row">
618 <span class="clearfix"></span>
619 <div class="product-short-info" style="display: flex;">
620 @if (!string.IsNullOrWhiteSpace(GetString("Ecom:Product:Stock.Text")))
621 {
622
623 image = GetString("Ecom:Product:Stock.Image.Clean");
624
625 <div class="col-md-6 col-xs-12">
626 <p><small>@Translate("Availability", "Availability"): <span property="availability">@GetString("Ecom:Product:Stock.Text")</span>: </small><img src="@image" alt="@GetString("ecom:product:stock.text")" style="width:7px !important; height:7px !important" /></p>
627 </div>
628 <div class="col-md-6 col-xs-12">
629 <p><small>@Translate("Delivery", "Delivery"): @GetString("Ecom:Product:Stock.DeliveryText") @GetString("Ecom:Product:Stock.DeliveryUnit")</small></p>
630 </div>
631 }
632 <div class="col-md-5 col-sm-5 col-xs-5">
633 <div>
634 @{
635 string diameter = GetString("Ecom:Product:Field.Diameter");
636 }
637 @if (!string.IsNullOrEmpty(diameter))
638 {
639 <p class="dimension1"><span class="dimension-title">@Translate("Diameter", "Diameter : ")</span><span class="dimension-value">@diameter@Translate("DiameterUnit", "mm")</span></p>
640 }
641 else
642 {
643 string dimension1 = GetString("Ecom:Product:Field.ProductDimension1");
644 string dimension2 = GetString("Ecom:Product:Field.ProductDimension2");
645 string dimension3 = GetString("Ecom:Product:Field.ProductDimension3");
646
647 <p class="dimension1"><span class="dimension-title">@Translate("Dimension1", "Dimension1 : ")</span><span class="dimension-value">@dimension1@Translate("DimensionUnit", "mm")</span></p>
648 <p class="dimension2"><span class="dimension-title">@Translate("Dimension2", "Dimension2 : ")</span><span class="dimension-value">@dimension2@Translate("DimensionUnit", "mm")</span></p>
649 if (!string.IsNullOrEmpty(dimension3))
650 {
651 <p class="dimension3"><span class="dimension-title">@Translate("Dimension3", "Dimension3 : ")</span><span class="dimension-value">@dimension3@Translate("DimensionUnit", "mm")</span></p>
652 }
653 }
654 </div>
655
656 <div class="">
657 <p class="description-1">@GetString("Ecom:Product:Field.ProductDescription1")</p>
658 <p class="description-2">@GetString("Ecom:Product:Field.ProductDescription2")</p>
659 </div>
660
661
662
663 <div class="">
664 <p><strong>@Translate("Product number", "Product number"): <span property="identifier">@GetString("Ecom:Product.Number")</span></strong></p>
665 </div>
666 </div>
667 <div class="col-md-7 col-sm-7 col-xs-7" style="align-content:flex-end">
668
669 @if (RenderWhitePaintedText)
670 {
671 int renderPageId = Dynamicweb.Context.Current.Request.Url.Host.Contains("test.kbhlistefabrik") ? 9569 : 9936;
672 <div class="important-green">
673 @RenderPageContent(renderPageId)
674 </div>
675 }
676 else if (RenderPrimedText)
677 {
678 int renderPageId = Dynamicweb.Context.Current.Request.Url.Host.Contains("test.kbhlistefabrik") ? 9570 : 9937;
679 <div class="important-green">
680 @RenderPageContent(renderPageId)
681 </div>
682 }
683
684 @{
685 var currency = GetString("Ecom:Product.Price.Currency.Code");
686 var standardPrice = GetDouble("Ecom:Product.DBPrice") * (1 + (GetDouble("Ecom:Product.Price.VATPercent") / 100));
687 var customerPrice = GetDouble("Ecom:Product.Price.Price");
688 }
689
690 <div class="" style="display: flex; justify-content: right;">
691 <meta property="priceCurrency" content="@currency" />
692
693 @if (customerPrice < standardPrice)
694 {
695
696 <p style="margin-top: 0px !important; padding-top: 10px !important; color: #AAAAAA !important; font-size: 14px !important; float: right; width: 100%; text-align: right;">
697 (<strong>@standardPrice.ToString("F") @currency@perUnitText</strong>)
698 </p>
699 <span> </span>
700 <span class="price pull-right" style="font-size: 28px !important" property="price">
701 @GetString("Ecom:Product.Price.Price") @currency@perUnitText
702 </span>
703
704 }
705 else
706 {
707 <span class="price pull-right" style="font-size: 24px !important; margin-top:4px !important " property="price">
708 @GetString("Ecom:Product.Price.Price") @currency@perUnitText
709 </span>
710 }
711
712 </div>
713 </div>
714 @if (GetLoop("BOMProducts").Count > 0)
715 {
716 <div class="col-md-6 col-sm-12 col-xs-12" id="includingproducts">
717 @*<hr />*@
718 <h3 class="section-title">@Translate("Including products", "Including products")</h3>
719
720 @foreach (LoopItem bomproduct in GetLoop("BOMProducts"))
721 {
722 var bomimage = bomproduct.GetString("Ecom:Product.ImageSmall.Clean");
723
724 <ul>
725 <li class="bomlist">
726 <a href="@bomproduct.GetString("Ecom:Product.Link.Clean.PID")">
727 <img src="/Admin/Public/GetImage.ashx?width=50&image=@bomimage&Compression=99" alt="">
728 > @bomproduct.GetString("Ecom:Product.Name")
729 </a>
730 </li>
731 </ul>
732 }
733
734 <table cellspacing="0" cellpadding="0" border="0">
735
736 @foreach (LoopItem bomconfig in GetLoop("BOMConfigurators"))
737 {
738 <tr>
739 <td>
740 <b>@bomconfig.GetString("Ecom:Product.Configurator.Name")</b><br>
741 <select name="@bomconfig.GetString("Ecom:Product.Configurator.ID")">
742 @foreach (LoopItem configproduct in GetLoop("ConfiguratorProducts"))
743 {
744 <option value="@configproduct.GetString("Ecom:Product.ID")" @configproduct.GetString("Ecom:Product.Configurator.Selected")> @configproduct.GetString("Ecom:Product.Name") ( @configproduct.GetString("Ecom:Product.ActualPrice")" ) </option>
745 }
746 </select>
747 </td>
748 </tr>
749 }
750 </table>
751 </div>
752 }
753
754
755 @if (!soldByLength)
756 {
757 bool defaultVariant = GetInteger("Ecom:Product.VariantCount") > 0 && string.IsNullOrEmpty(GetString("Ecom:Product.VariantID"));
758 string disabled = defaultVariant ? "disabled" : string.Empty;
759
760 <div class="col-md-6 col-sm-12 col-xs-12">
761 <div class="add-to-cart-inputs">
762
763 <input type="number" name="Quantity" value="1" class="pull-left" style="width:60px; text-align:center; margin-right:15px !important; height:34px;" @disabled>
764 <button type="submit" name="submit" onclick="UpdateCart();" class="btn btn-dw-cart pull-right " @disabled><strong>@Translate("Add to cart", "Add to cart")</strong></button>
765 @if (defaultVariant)
766 {
767 <span class="choose-variant">@Translate("ChooseVariant", "Choose a variant")</span>
768 }
769 </div>
770 </div>
771 }
772
773
774 </div>
775 @*<hr />*@
776 </div>
777 </div>
778 </div>
779 </form>
780
781
782
783 @if (Dynamicweb.Security.Licensing.LicenseManager.LicenseHasFeature("LoyaltyPoints"))
784 {
785 @* Buy with loyalty points start *@
786
787 var productPoints = GetDouble("Ecom:Product.PointPrice");
788
789 if (productPoints > 0)
790 {
791 <div class="col-md-6 col-sm-12 col-xs-12">
792
793 <span class="price pull-left" style="font-size: 22px !important; margin-top:4px !important">@productPoints @Translate("Points", "Points")</span>
794
795 @{var user = Dynamicweb.Security.UserManagement.User.GetCurrentUser(Dynamicweb.Security.UserManagement.PagePermissionLevels.Frontend);}
796 @if (user == null)
797 {
798 <div class="alert alert-info">@Translate("Sign in to buy this product using points")</div>
799 }
800 else
801 {
802 var availablePoints = user != null ? user.PointBalance : 0;
803 var cart = Dynamicweb.Ecommerce.Common.Context.Cart;
804 var pointsUsedInCart = cart != null ? cart.TotalPoints : 0;
805
806 if (availablePoints < productPoints + pointsUsedInCart)
807 {
808 <div class="alert alert-danger">@string.Format(Translate("You don't have enough points to buy this product using points ({0:0.00}/{1:0.00})"), availablePoints, productPoints + pointsUsedInCart)</div>
809 }
810 else
811 {
812 var ProductID = GetValue("Ecom:Product.ID");
813
814 <form method="post" role="form">
815 <input type="hidden" name="ProductID" value="@ProductID" />
816 <button type="submit" onclick="UpdateCart();" class="btn btn-dw-secondary pull-right" name="CartCmd" value="addWithPoints">@Translate("Buy for") @productPoints @Translate("points")</button>
817 </form>
818 }
819 }
820
821 </div>
822 <div class="col-md-6 col-sm-12 col-xs-12">
823 <hr />
824 </div>
825
826 }
827
828 @* Buy with loyalty points end *@
829 }
830 </div>
831 <div class="col-md-@infosize col-sm-12 col-xs-12 pull-right">
832 <div class="row">
833 <div class="col-md-12 col-sm-12 col-xs-12 productdescription pull-left">
834
835
836 <div class="row">
837
838 @if (soldByLength)
839 {
840 <div style=" width:100%; padding:0 15px 15px 15px;"><hr /></div>
841 <div class="wishlenghinfo"><p>@Translate("WishLength", "Ønskelængder: Her skrifter du dine ønskelængder. ")</p></div>
842 <div class="col-md-5 col-sm-5 col-xs-12 pull-left" id="addtocart-bylength-multiple">
843 <div class="addtocart-bylength-header">
844 <input type="radio" name="orderType" value="multiple" checked="checked" id="orderType-multiple">
845 <span>@Translate("Quantity", "Quantity")</span>
846 <span>@Translate("Length", "Length")</span>
847 </div>
848 <div id="addtocart-bylength-lines">
849 @for (int i = 1; i < perLengthLines + 1; i++)
850 {
851 <div id="addtocart-bylength-@i" class="addtocart-bylength ">
852 <form name="addMulti@(i)" id="addMulti@(i)" method="post" action="/Default.aspx" data-index="@(i)">
853 <input type="hidden" name="ProductURL" id="ProductURL@(i)" value="" />
854 <input type="hidden" name="CartCmd" id="CartCmd@(i)" value="add" />
855 <input type="hidden" name="ProductID" id="ProductID@(i)" value="@GetString("Ecom:Product.ID")" />
856 <input type="hidden" name="VariantID" id="VariantID@(i)" value="" />
857 <input type="hidden" name="UnitID" id="UnitID@(i)" value="" />
858 <input type="hidden" name="wishListID" id="wishListID@(i)" value="0" />
859
860 <input type="number" min="0" pattern="\d*" step="1" class="addtocart-bylength-quantity" name="Quantity" id="Quantity@(i)" value="0" />
861 <select class="addtocart-bylength-length" name="EcomOrderLineFieldInput_SelectedLength" id="EcomOrderLineFieldInput_SelectedLength@(i)">
862 @foreach (var length in availableLengths)
863 {
864 <option value="@length">@length@Translate("LengthUnit", "cm")</option>
865 }
866 </select>
867 </form>
868 @if (i == perLengthLines)
869 {
870 <input type="button" id="addtocart-bylength-addline" title="@Translate("AddLine", "Add a new line")" value="+" class="btn" />
871 }
872 </div>
873 }
874 </div>
875 </div>
876
877 <div class="col-md-7 col-sm-7 col-xs-12" id="addtocart-bylength-specificlength">
878 <input type="radio" name="orderType" value="specific" id="orderType-specific"> <span>@Translate("SpecificLengthOrder", "Or order a specific length : ")</span>
879 <form name="addSpecific" id="addSpecific" method="get">
880 <input type="hidden" name="ProductURL" id="ProductURL" value="" />
881 <input type="hidden" name="CartCmd" id="CartCmd" value="add" />
882 <input type="hidden" name="ProductID" id="ProductID" value="@GetString("Ecom:Product.ID")" />
883 <input type="hidden" name="VariantID" id="VariantID" value="" />
884 <input type="hidden" name="UnitID" id="UnitID" value="" />
885 <input type="hidden" name="wishListID" id="wishListID" value="0" />
886
887 <input type="hidden" name="Quantity" id="Quantity" value="1" />
888 <input type="hidden" name="EcomOrderLineFieldInput_SelectedLength" id="EcomOrderLineFieldInput_SelectedLength" value="0" />
889 <input type="number" class="addtocart-bylength-specificlength disabled" pattern="\d*" step="1" min="0" lang="nb" /> @Translate("MeterLengthUnit", "m")
890 </form>
891 <div class="alert alert-danger" id="invalid-length-error" style="display:none">
892 @Translate("InvalidLengthError", "The length must be an integer number")
893 </div>
894 </div>
895 <div class="col-md-7 col-sm-7 col-xs-12">
896 <div class="important">
897 <p>@Translate("Important", "VIGTIGT! Vi afkorter ikke listerne")</p>
898 </div>
899 </div>
900
901
902 <div class="col-md-12 col-sm-12 col-xs-12 addtocart-bylength-footer">
903 <div><p class="price">@Translate("Total", "Total") : <span id="total-length">0</span>@Translate("LengthUnit", "cm") × @GetString("Ecom:Product.Discount.Price.Price") @currency@perUnitText = <span id="total-price">0.0</span>@currency</p></div>
904 <div><input type="button" onclick="SetSpinner();UpdateCart();AddToCartByLength();" class="btn btn-dw-cart" value="@HttpUtility.HtmlEncode(Translate("Add to cart", "Add to cart"))" /></div>
905 </div>
906
907 <div style="display:none" id="by-length-line-template">
908 <div id="addtocart-bylength-{i}" class="addtocart-bylength ">
909 <form name="addMulti{i}" id="addMulti{i}" method="post" action="/Default.aspx" data-index="{i}">
910 <input type="hidden" name="ProductURL" id="ProductURL{i}" value="" />
911 <input type="hidden" name="CartCmd" id="CartCmd{i}" value="add" />
912 <input type="hidden" name="ProductID" id="ProductID{i}" value="@GetString("Ecom:Product.ID")" />
913 <input type="hidden" name="VariantID" id="VariantID{i}" value="" />
914 <input type="hidden" name="UnitID" id="UnitID{i}" value="" />
915 <input type="hidden" name="wishListID" id="wishListID{i}" value="0" />
916
917 <input type="number" min="0" pattern="\d*" step="1" class="addtocart-bylength-quantity" name="Quantity" id="Quantity{i}" value="0" />
918 <select class="addtocart-bylength-length" name="EcomOrderLineFieldInput_SelectedLength" id="EcomOrderLineFieldInput_SelectedLength{i}">
919 @foreach (var length in availableLengths)
920 {
921 <option value="@length">@length@Translate("LengthUnit", "cm")</option>
922 }
923 </select>
924 </form>
925 </div>
926 </div>
927 }
928 </div>
929 @if (!string.IsNullOrEmpty(GetString("Ecom:Product.LongDescription")))
930 {
931 <div class="row productdescription2">
932 <strong>@Translate("Varebeskrivelse", "Varebeskrivelse")</strong>
933 @GetString("Ecom:Product.LongDescription")
934 </div>
935 }
936 </div>
937 </div>
938 </div>
939 @*---*@
940 </div>
941
942 <div class="row">
943 <div class="col-md-12 col-sm-12 col-xs-12">
944 <div class="row">
945
946
947 <div class="col-md-12 extra-products">
948
949 <hr />
950
951 <!-- RELATED PRODUCTS -->
952 @if (Pageview.Area.Item["RelatedProducts"].ToString() == "True")
953 {
954 if (GetString("Ecom:Product.RelatedCount") != "0")
955 {
956 <div class="row">
957 <div class="col-md-12 col-sm-12 col-xs-12">
958
959 <h3 class="dw-section-title"><span>@Translate("Related products", "Related products")</span></h3>
960 </div>
961 </div>
962
963 foreach (LoopItem relatedgroup in GetLoop("ProductRelatedGroups"))
964 {
965 <div class="row">
966 @{
967 var relatedproductloop = relatedgroup.GetLoop("RelatedProducts").OrderByDescending(g => g.GetString("Ecom:Product.LoopCounter")).Take(4).ToList();
968 }
969
970 @GetProductList(relatedproductloop, 4, 3, 1)
971 </div>
972 <hr />
973 }
974 }
975 }
976
977 @if (Pageview.Area.Item["CustomersAlsoSaw"].ToString() == "True")
978 {
979 if (GetString("eCom:Related.CustomersWhoSawThisAlsoSaw.Count") != "0")
980 {
981 <div class="row">
982 <div class="col-md-12 col-sm-12 col-xs-12">
983 <h3 class="dw-section-title"><span>@Translate("Other costumers also saw", "Other costumers also saw")</span></h3>
984 </div>
985 </div>
986 <div class="row">
987 @{
988 var alsoproductgroup = GetLoop("eCom:Related.CustomersWhoSawThisAlsoSaw").OrderByDescending(g => g.GetString("Ecom:Product.LoopCounter")).Take(4).ToList();
989 }
990
991 @GetProductList(alsoproductgroup, 4, 3, 1)
992 </div>
993 <hr />
994 }
995 }
996
997 @if (Pageview.Area.Item["YourLastSeenProducts"].ToString() == "True")
998 {
999 if (GetString("eCom:Related.YouHaveSeenTheseProducts.Count") != "0")
1000 {
1001 <div class="row">
1002 <div class="col-md-12 col-sm-12 col-xs-12">
1003 <h3 class="dw-section-title"><span>@Translate("Recently viewed items", "Recently viewed items")</span></h3>
1004 </div>
1005 </div>
1006 <div class="row">
1007 @{
1008 var recentproductgroup = GetLoop("eCom:Related.YouHaveSeenTheseProducts").OrderByDescending(g => g.GetString("Ecom:Product.LoopCounter")).Take(4).ToList();
1009 }
1010
1011 @GetProductList(recentproductgroup, 4, 3, 1)
1012
1013 </div>
1014 <hr />
1015 }
1016 }
1017
1018 @if (Pageview.Area.Item["ProductsFromCategory"].ToString() == "True")
1019 {
1020 if (GetString("eCom:Related.WhatAboutTheseProducts.Count") != "0")
1021 {
1022 <div class="row">
1023 <div class="col-md-12 col-sm-12 col-xs-12">
1024 <h3 class="dw-section-title"><span>@Translate("Other great products in the same category", "Other great products in the same category")</span></h3>
1025 </div>
1026 </div>
1027 <div class="row">
1028 @{
1029 var aboutproductgroup = GetLoop("eCom:Related.WhatAboutTheseProducts").OrderByDescending(g => g.GetString("Ecom:Product.LoopCounter")).Take(4).ToList();
1030 }
1031
1032 @GetProductList(aboutproductgroup, 4, 3, 1)
1033 </div>
1034 <hr />
1035 }
1036 }
1037 <div class="row"><div class="col-md-12 col-sm-12 col-xs-12"> </div></div>
1038 </div>
1039
1040 </div>
1041 </div>
1042 </div>
1043
1044 <div class="modal fade productimagelarge" id="imagezoommodal" tabindex="-1" role="dialog" aria-labelledby="Image Zoom" aria-hidden="true">
1045 <div class="modal-dialog">
1046 <div class="modal-content">
1047 <div class="modal-header">
1048 <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
1049 </div>
1050 <div class="modal-body">
1051 <img src="" id="imagepreview">
1052 </div>
1053 </div>
1054 </div>
1055 </div>
1056
1057 </div>
1058
1059 <script>
1060 @{
1061 string banner = string.Empty;
1062
1063 if(!string.IsNullOrWhiteSpace(GetString("Ecom:Group:Field.Banner")))
1064 {
1065 banner = PIMCommerceUtilities.GetPerfionImageUrl(GetString("Ecom:Group:Field.Banner"));
1066 }
1067 }
1068
1069 ProductPageSettings = {
1070 AvailableLengths: [@string.Join(",", availableLengths.ToArray())]
1071 ,AddToCartByLengthLineCount : @perLengthLines.ToString()
1072 ,GroupBanner: '@banner'
1073 ,HasVariants: @hasVariants.ToString().ToLower()
1074 ,SoldByLength : @soldByLength.ToString().ToLower()
1075 ,UnitPrice: @Json.Encode(GetDouble("Ecom:Product.Discount.Price.Price"))
1076 };
1077 </script>
1078
1079 <script src="/Files/Templates/Designs/Dwsimple/js/pages/product.js?v=1.1" defer="defer"></script>
1080