Skip to content

Commit e52c7fa

Browse files
committed
Liquid template engine (work in progress)
1 parent 63964be commit e52c7fa

10 files changed

Lines changed: 316 additions & 119 deletions

File tree

src/Libraries/SmartStore.Services/Common/AddressExtentions.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ public static Address FindAddress(
8686
/// <summary>
8787
/// Returns the full name of the address.
8888
/// </summary>
89-
public static string GetFullName(this Address address)
89+
public static string GetFullName(this Address address, bool withCompanyName = true)
9090
{
9191
if (address == null)
9292
return null;
@@ -97,7 +97,7 @@ public static string GetFullName(this Address address)
9797
result = string.Format("{0} {1}", address.FirstName, address.LastName).Trim();
9898
}
9999

100-
if (address.Company.HasValue())
100+
if (withCompanyName && address.Company.HasValue())
101101
{
102102
result = string.Concat(result, result.HasValue() ? ", " : "", address.Company);
103103
}

src/Libraries/SmartStore.Services/Messages/New/MessageModelProvider.OrderParts.cs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,8 @@ protected virtual object CreateModelPart(Order part, MessageContext messageConte
6262

6363
d.ID = part.Id;
6464
d.Billing = CreateModelPart(part.BillingAddress, messageContext);
65-
d.Shipping = CreateModelPart(part.BillingAddress ?? new Address(), messageContext);
66-
d.CustomerFullName = part.BillingAddress.GetFullName();
65+
d.Shipping = part.ShippingAddress == null ? null : CreateModelPart(part.ShippingAddress, messageContext);
66+
//d.CustomerFullName = part.BillingAddress.GetFullName();
6767
d.CustomerEmail = part.BillingAddress.Email;
6868
d.CustomerComment = part.CustomerOrderComment;
6969
d.Disclaimer = GetTopic("Disclaimer", messageContext);
@@ -211,7 +211,7 @@ protected virtual object CreateOrderTotalsPart(Order order, MessageContext messa
211211
}).ToArray();
212212

213213
// Reward Points
214-
m.RedeemedRewardPoints = order.RedeemedRewardPointsEntry != null ? null : new
214+
m.RedeemedRewardPoints = order.RedeemedRewardPointsEntry == null ? null : new
215215
{
216216
Title = T("Messages.Order.RewardPoints", language.Id, -order.RedeemedRewardPointsEntry.Points),
217217
Amount = FormatPrice(-order.RedeemedRewardPointsEntry.UsedAmount, order, messageContext)
@@ -266,17 +266,23 @@ protected virtual object CreateModelPart(OrderItem part, MessageContext messageC
266266

267267
var productAttributeParser = _services.Resolve<IProductAttributeParser>();
268268
var downloadService = _services.Resolve<IDownloadService>();
269-
269+
var order = part.Order;
270+
var isNet = order.CustomerTaxDisplayType == TaxDisplayType.ExcludingTax;
270271
var product = part.Product;
271272
product.MergeWithCombination(part.AttributesXml, productAttributeParser);
272273

273274
var m = new Dictionary<string, object>
274275
{
275276
{ "DownloadUrl", !downloadService.IsDownloadAllowed(part) ? "" : BuildActionUrl("GetDownload", "Download", new { id = part.OrderItemGuid, area = "" }, messageContext) },
276277
{ "AttributeDescription", part.AttributeDescription },
278+
{ "Weight", part.ItemWeight },
279+
{ "TaxRate", part.TaxRate },
280+
{ "Qty", part.Quantity },
281+
{ "UnitPrice", FormatPrice(isNet ? part.UnitPriceExclTax : part.UnitPriceInclTax, part.Order, messageContext) },
282+
{ "LineTotal", FormatPrice(isNet ? part.PriceExclTax : part.PriceInclTax, part.Order, messageContext) },
277283
{ "Product", CreateModelPart(product, messageContext, part.AttributesXml) }
278284
};
279-
285+
280286
PublishModelPartCreatedEvent<OrderItem>(part, m);
281287

282288
return m;

src/Libraries/SmartStore.Services/Messages/New/MessageModelProvider.Utils.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
using SmartStore.Services.Media;
1212
using SmartStore.Services.Directory;
1313
using SmartStore.Core.Domain.Orders;
14+
using System.Text;
15+
using SmartStore.Core.Domain.Common;
1416

1517
namespace SmartStore.Services.Messages
1618
{

src/Libraries/SmartStore.Services/Messages/New/MessageModelProvider.cs

Lines changed: 57 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
using SmartStore.Services.Directory;
3535
using SmartStore.Services.Media;
3636
using SmartStore.Core.Domain.Directory;
37+
using System.Text;
3738

3839
namespace SmartStore.Services.Messages
3940
{
@@ -279,12 +280,12 @@ protected virtual object CreateThemeModelPart(MessageContext messageContext)
279280
dynamic model = new ExpandoObject();
280281

281282
// TODO: (mc) Liquid > make theme variables (?)
282-
model.FontFamily = "Arial, 'Helvetica Neue', Helvetica, sans-serif";
283+
model.FontFamily = "-apple-system, system-ui, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif";
283284
model.BodyBg = "#f2f4f6";
284285
model.BodyColor = "#74787e";
285286
model.TitleColor = "#2f3133";
286287
model.ContentBg = "#fff";
287-
model.ShadeColor = "#edeff2";
288+
model.ShadeColor = "#e2e2e2";
288289
model.LinkColor = "#3869D4";
289290
model.BrandPrimary = "#3f51b5";
290291
model.BrandSuccess = "#4caf50";
@@ -697,19 +698,67 @@ protected virtual object CreateModelPart(Address part, MessageContext messageCon
697698
Guard.NotNull(messageContext, nameof(messageContext));
698699
Guard.NotNull(part, nameof(part));
699700

700-
var disallow = new[] { nameof(part.CreatedOnUtc), nameof(part.StateProvinceId), nameof(part.CountryId), };
701+
//var disallow = new[] { nameof(part.CreatedOnUtc), nameof(part.StateProvinceId), nameof(part.CountryId), };
701702

702-
var m = new HybridExpando(part, disallow, MemberOptMethod.Disallow);
703+
//var m = new HybridExpando(part, disallow, MemberOptMethod.Disallow);
704+
705+
//m["FullSalutation"] = part.GetFullSalutaion();
703706

704-
m["FullSalutation"] = part.GetFullSalutaion();
707+
//// Overrides
708+
//m.Properties["StateProvince"] = part.StateProvince?.GetLocalized(x => x.Name, messageContext.Language.Id).EmptyNull();
709+
//m.Properties["Country"] = part.Country?.GetLocalized(x => x.Name, messageContext.Language.Id).EmptyNull();
705710

706-
// Overrides
707-
m.Properties["StateProvince"] = part.StateProvince?.GetLocalized(x => x.Name, messageContext.Language.Id).EmptyNull();
708-
m.Properties["Country"] = part.Country?.GetLocalized(x => x.Name, messageContext.Language.Id).EmptyNull();
711+
var settings = _services.Resolve<AddressSettings>();
712+
713+
var m = new Dictionary<string, object>
714+
{
715+
{ "Title", part.Title },
716+
{ "Salutation", part.Salutation },
717+
{ "FullSalutation", part.GetFullSalutaion() },
718+
{ "FullName", part.GetFullName(false) },
719+
{ "Company", settings.CompanyEnabled ? part.Company : "" },
720+
{ "FirstName", part.FirstName },
721+
{ "LastName", part.LastName },
722+
{ "Address1", settings.StreetAddressEnabled ? part.Address1 : "" },
723+
{ "Address2", settings.StreetAddress2Enabled ? part.Address2 : "" },
724+
{ "Country", settings.CountryEnabled ? part.Country?.GetLocalized(x => x.Name, messageContext.Language.Id).EmptyNull() : "" },
725+
{ "State", settings.StateProvinceEnabled ? part.StateProvince?.GetLocalized(x => x.Name, messageContext.Language.Id).EmptyNull() : "" },
726+
{ "City", settings.CityEnabled ? part.City : "" },
727+
{ "ZipCode", settings.ZipPostalCodeEnabled ? part.ZipPostalCode : "" },
728+
{ "Email", part.Email },
729+
{ "Phone", settings.PhoneEnabled ? part.PhoneNumber : "" },
730+
{ "Fax", settings.FaxEnabled ? part.FaxNumber : "" }
731+
};
732+
733+
m["FullCity"] = GetFullCity();
709734

710735
PublishModelPartCreatedEvent<Address>(part, m);
711736

712737
return m;
738+
739+
string GetFullCity()
740+
{
741+
var zip = m["ZipCode"] as string;
742+
var city = m["City"] as string;
743+
744+
var sb = new StringBuilder();
745+
746+
if (city.HasValue())
747+
{
748+
sb.Append(city);
749+
if (zip.HasValue())
750+
{
751+
sb.Append(", ");
752+
}
753+
}
754+
755+
if (zip.HasValue())
756+
{
757+
sb.Append(zip);
758+
}
759+
760+
return sb.ToString();
761+
}
713762
}
714763

715764
protected virtual object CreateModelPart(RewardPointsHistory part, MessageContext messageContext)

src/Presentation/SmartStore.Web/Administration/Controllers/New/MessageTemplateController.cs

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
using System;
22
using System.IO;
33
using System.Linq;
4+
using System.Linq.Expressions;
45
using System.Web.Mvc;
56
using System.Xml;
67
using SmartStore.Admin.Models.Messages;
78
using SmartStore.Collections;
89
using SmartStore.ComponentModel;
10+
using SmartStore.Core;
911
using SmartStore.Core.Domain.Messages;
12+
using SmartStore.Core.Domain.Orders;
1013
using SmartStore.Services;
1114
using SmartStore.Services.Localization;
1215
using SmartStore.Services.Media;
@@ -130,7 +133,6 @@ public ActionResult SaveInFile(MessageTemplateModel model)
130133
return RedirectToAction("Edit2", model.Id);
131134
}
132135

133-
134136
private MessageTemplate GetTemplateFromFile(string messageTemplateName)
135137
{
136138
string path = Path.Combine(CommonHelper.MapPath("~/App_Data/EmailTemplates/de"), messageTemplateName + ".xml");
@@ -153,7 +155,44 @@ private MessageTemplate GetTemplateFromFile(string messageTemplateName)
153155
return tpl;
154156
}
155157

158+
[FormValueRequired("send-test-mail"), ActionName("Edit2")]
159+
public ActionResult SendTestMail()
160+
{
161+
var svc = Services.Resolve<IWorkflowMessageService>();
162+
163+
var order = GetRandomEntity<Order>(x => !x.Deleted) as Order;
164+
165+
var id = svc.SendOrderPlacedCustomerNotification(order, order.CustomerLanguageId);
166+
var qe = Services.Resolve<IQueuedEmailService>().GetQueuedEmailById(id);
167+
168+
return Content(qe.Body, "text/html");
169+
}
170+
171+
private object GetRandomEntity<T>(Expression<Func<T, bool>> predicate) where T : BaseEntity, new()
172+
{
173+
var dbSet = Services.DbContext.Set<T>().AsNoTracking();
174+
175+
var query = dbSet.Where(predicate);
156176

177+
// Determine how many entities match the given predicate
178+
var count = query.Count();
179+
180+
object result;
181+
182+
if (count > 0)
183+
{
184+
// Fetch a random one
185+
var skip = new Random().Next(count - 1);
186+
result = query.OrderBy(x => x.Id).Skip(skip).FirstOrDefault();
187+
}
188+
else
189+
{
190+
// No entity macthes the predicate. Provide a fallback test entity
191+
result = Activator.CreateInstance<T>();
192+
}
193+
194+
return result;
195+
}
157196

158197

159198
public ActionResult EditTest()

src/Presentation/SmartStore.Web/Administration/Views/MessageTemplate/Edit2.cshtml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
<div class="options">
2424
@{ Html.RenderWidget("admin_button_toolbar_before"); }
2525

26+
<button type="submit" name="send-test-mail" value="send-test-mail" class="btn btn-default"><i class="fa fa-envelope-o"></i>&nbsp;Testmail senden</button>
2627
<button type="submit" name="save-in-file" value="save-in-file" class="btn btn-default"><i class="fa fa-floppy-o"></i>&nbsp;In Datei speichern</button>
2728
<button type="submit" name="save" value="save" class="btn btn-primary"><i class="fa fa-check"></i>&nbsp;@T("Admin.Common.Save")</button>
2829

0 commit comments

Comments
 (0)