Endpoint dedie `PUT Section/{id}/visibility` : passer par `Update` aurait
reconstruit le sous-type via SectionFactory, donc efface le contenu specifique
de la section.
Le logo des e-mails est servi par le service lui-meme (wwwroot + UseStaticFiles)
plutot que par le manager deploye en face, dont il ne doit pas dependre.
130 lines
5.8 KiB
C#
130 lines
5.8 KiB
C#
using System;
|
|
|
|
namespace ManagerService.EmailTemplates
|
|
{
|
|
/// <summary>
|
|
/// Shared HTML shell for all transactional emails. Palette taken from the
|
|
/// MyInfoMate platform deck: navy #0a1222, cyan #0df2df, teal #0e8f8a.
|
|
/// </summary>
|
|
public static class EmailLayout
|
|
{
|
|
/// <summary>Absolute URL of the logo shown in the header band. Empty = wordmark only.</summary>
|
|
public static string LogoUrl { get; private set; } = "";
|
|
|
|
/// <summary>Public site linked from the footer. Empty = no link.</summary>
|
|
public static string LandingUrl { get; private set; } = "";
|
|
|
|
/// <summary>Called once at startup from configuration (see Startup.cs).</summary>
|
|
public static void Configure(string logoUrl, string landingUrl)
|
|
{
|
|
// Une URL relative afficherait une image cassée dans la boîte de
|
|
// réception : mieux vaut le bandeau sans logo que ça.
|
|
LogoUrl = logoUrl != null && logoUrl.StartsWith("http") ? logoUrl : "";
|
|
LandingUrl = landingUrl ?? "";
|
|
}
|
|
|
|
public static string Render(string title, string bodyHtml, string ctaText = null, string ctaUrl = null)
|
|
{
|
|
var hasCta = !string.IsNullOrEmpty(ctaText) && !string.IsNullOrEmpty(ctaUrl);
|
|
|
|
// Le texte de pré-en-tête est ce que la boîte de réception affiche à
|
|
// côté de l'objet : sans lui elle recopie le début du HTML.
|
|
var preheader = StripTags(bodyHtml);
|
|
if (preheader.Length > 140) preheader = preheader.Substring(0, 140) + "…";
|
|
|
|
var logoHtml = string.IsNullOrEmpty(LogoUrl)
|
|
? ""
|
|
: $@"<img src=""{LogoUrl}"" width=""44"" height=""42"" alt="""" style=""display:block; border:0;"">";
|
|
|
|
var ctaHtml = "";
|
|
if (hasCta)
|
|
{
|
|
ctaHtml = $@"
|
|
<table role=""presentation"" cellpadding=""0"" cellspacing=""0"" border=""0"" style=""margin:32px 0 0;"">
|
|
<tr>
|
|
<td align=""center"" bgcolor=""#0df2df"" style=""border-radius:10px;"">
|
|
<a href=""{ctaUrl}"" style=""display:block; padding:16px 34px; font-family:Helvetica,Arial,sans-serif; font-size:16px; font-weight:bold; color:#0a1222; text-decoration:none; letter-spacing:.2px;"">{ctaText}</a>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<p style=""margin:20px 0 0; font-family:Helvetica,Arial,sans-serif; font-size:12.5px; line-height:1.6; color:#94a3b8;"">
|
|
Le bouton ne fonctionne pas ? Copiez ce lien dans votre navigateur :<br>
|
|
<span style=""color:#0e8f8a; word-break:break-all;"">{ctaUrl}</span>
|
|
</p>";
|
|
}
|
|
|
|
var landingHtml = string.IsNullOrEmpty(LandingUrl)
|
|
? ""
|
|
: $@" · <a href=""{LandingUrl}"" style=""color:#0e8f8a; text-decoration:none; font-weight:bold;"">myinfomate.be</a>";
|
|
|
|
return $@"<!DOCTYPE html>
|
|
<html lang=""fr"">
|
|
<head>
|
|
<meta charset=""utf-8"">
|
|
<meta name=""viewport"" content=""width=device-width, initial-scale=1.0"">
|
|
<meta name=""color-scheme"" content=""light"">
|
|
<title>{title}</title>
|
|
</head>
|
|
<body style=""margin:0; padding:0; background:#f5f7fa;"">
|
|
<div style=""display:none; max-height:0; overflow:hidden; opacity:0;"">{preheader}</div>
|
|
|
|
<table role=""presentation"" width=""100%"" cellpadding=""0"" cellspacing=""0"" border=""0"" style=""background:#f5f7fa;"">
|
|
<tr>
|
|
<td align=""center"" style=""padding:40px 16px;"">
|
|
|
|
<table role=""presentation"" width=""600"" cellpadding=""0"" cellspacing=""0"" border=""0"" style=""width:600px; max-width:100%; background:#ffffff; border-radius:18px; overflow:hidden; box-shadow:0 2px 12px rgba(10,18,34,.07);"">
|
|
|
|
<tr>
|
|
<td bgcolor=""#0a1222"" style=""padding:30px 40px;"">
|
|
<table role=""presentation"" cellpadding=""0"" cellspacing=""0"" border=""0"">
|
|
<tr>
|
|
<td style=""padding-right:14px;"">{logoHtml}</td>
|
|
<td style=""font-family:Helvetica,Arial,sans-serif; font-size:21px; font-weight:bold; color:#ffffff; letter-spacing:-.3px;"">MyInfoMate</td>
|
|
</tr>
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td height=""4"" bgcolor=""#0df2df"" style=""height:4px; line-height:4px; font-size:0;""> </td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td style=""padding:44px 40px 48px;"">
|
|
<h1 style=""margin:0 0 20px; font-family:Helvetica,Arial,sans-serif; font-size:26px; line-height:1.25; font-weight:bold; color:#0a1222; letter-spacing:-.4px;"">{title}</h1>
|
|
<div style=""font-family:Helvetica,Arial,sans-serif; font-size:15.5px; line-height:1.75; color:#3b4754;"">{bodyHtml}</div>
|
|
{ctaHtml}
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td bgcolor=""#f5f7fa"" style=""padding:26px 40px; border-top:1px solid #d6dde5; font-family:Helvetica,Arial,sans-serif; font-size:12.5px; line-height:1.7; color:#64748b;"">
|
|
<strong style=""color:#0a1222;"">MyInfoMate</strong> — la plateforme de contenu des lieux culturels.<br>
|
|
© {DateTime.UtcNow.Year} Unov{landingHtml}
|
|
</td>
|
|
</tr>
|
|
|
|
</table>
|
|
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</body>
|
|
</html>";
|
|
}
|
|
|
|
private static string StripTags(string html)
|
|
{
|
|
if (string.IsNullOrEmpty(html)) return "";
|
|
var sb = new System.Text.StringBuilder(html.Length);
|
|
var inTag = false;
|
|
foreach (var c in html)
|
|
{
|
|
if (c == '<') inTag = true;
|
|
else if (c == '>') inTag = false;
|
|
else if (!inTag) sb.Append(c);
|
|
}
|
|
return sb.ToString().Replace(" ", " ").Trim();
|
|
}
|
|
}
|
|
}
|