Files
hrynco-notification-service/HrynCo.NotificationService.Web/Views/AdminTemplates/Index.cshtml
T
agrynco aba4173827 feat(templates): add localized push templates and actions
Share template keys across email and push with independent editors and revisions. Render localized actions and preserve version-one delivery.

Ref: IT-1627
2026-10-31 09:38:05 +02:00

110 lines
6.1 KiB
Plaintext

@using HrynCo.NotificationService.Web.Controllers.Admin.ViewModels
@model ServiceTemplatesViewModel
@{
ViewData["Title"] = Model.Service.Name;
var serviceId = Model.Service.Id;
var keyFilter = Model.KeyFilter;
}
<nav aria-label="Breadcrumb" class="service-template-breadcrumbs"><ol class="breadcrumb"><li class="breadcrumb-item"><a href="/admin/services">Services</a></li><li class="breadcrumb-item active" aria-current="page">@Model.Service.Name</li></ol></nav>
<div class="page-header">
<h2 class="service-template-service-name">@Model.Service.Name</h2>
<a href="/admin/services/@serviceId/edit" class="btn btn-outline-primary">Edit Service</a>
</div>
<div class="service-template-catalog mb-3" aria-label="Configured service languages">
<span class="fw-semibold">Configured languages:</span>
@if (Model.Service.Languages.Count == 0)
{
<span>No languages configured for this service.</span>
}
else
{
@foreach (var language in Model.Service.Languages)
{
<span class="service-template-language-code">@language.Code</span>
}
}
</div>
<div class="page-header">
<h3 class="h4">Templates</h3>
<a asp-action="Create" asp-route-serviceId="@serviceId" asp-route-keyFilter="@keyFilter" class="btn btn-primary">Create template</a>
</div>
<div asp-validation-summary="All" class="text-danger mb-3" role="alert"></div>
<div class="table-responsive"><table class="table table-hover admin-data-table service-template-grid"><thead><tr>
<th scope="col">
<form method="get" action="/admin/services/@serviceId" class="template-key-filter">
<label for="key" class="form-label fw-semibold">Template Key</label>
<div class="template-key-filter-controls">
<input id="key" name="key" value="@keyFilter" class="form-control form-control-sm" placeholder="Filter by key" />
<button type="submit" class="btn btn-primary btn-sm">Filter</button>
<a href="/admin/services/@serviceId" class="btn btn-outline-secondary btn-sm">Clear</a>
</div>
</form>
</th>
<th scope="col">Email</th>
<th scope="col">Push</th>
<th scope="col" class="template-actions">Action</th>
</tr></thead><tbody>
@if (Model.Definitions.Count == 0 && Model.PushDefinitions.Count == 0)
{
<tr><td colspan="4"><div class="empty-state">
@if (!ViewData.ModelState.IsValid)
{
<p class="mb-0">Templates are unavailable. Review the error and try again.</p>
}
else if (!string.IsNullOrWhiteSpace(keyFilter))
{
<i class="bi bi-search" aria-hidden="true"></i><p class="mt-2 mb-0">No templates match this key.</p><a href="/admin/services/@serviceId" class="btn btn-primary btn-sm mt-3">Clear filter</a>
}
else
{
<i class="bi bi-envelope" aria-hidden="true"></i><p class="mt-2 mb-0">No templates for this service yet.</p><a asp-action="Create" asp-route-serviceId="@serviceId" class="btn btn-primary btn-sm mt-3">Create First Template</a>
}
</div></td></tr>
}
@foreach (var templateKey in Model.Definitions.Select(d => d.Key).Concat(Model.PushDefinitions.Select(d => d.Key)).Distinct(StringComparer.Ordinal).OrderBy(k => k, StringComparer.Ordinal))
{
var email = Model.Definitions.SingleOrDefault(d => d.Key == templateKey);
var push = Model.PushDefinitions.SingleOrDefault(d => d.Key == templateKey);
var editUrl = email is null ? Url.Action("Edit", "AdminPushTemplates", new { serviceId, key = templateKey, keyFilter }) : Url.Action("Edit", "AdminTemplates", new { serviceId, definitionId = email.Id, keyFilter });
var presentCodes = email?.Languages.Select(l => l.LanguageCode).ToHashSet(StringComparer.Ordinal) ?? [];
<tr>
<td>@templateKey</td>
<td>
@if (email is null) { <span>Not configured</span> }
else if (Model.Service.Languages.Count == 0)
{
<span>No configured languages</span>
}
else
{
<ul class="template-language-statuses">
@foreach (var language in Model.Service.Languages)
{
var present = presentCodes.Contains(language.Code);
<li class="template-language-status @(present ? "template-language-present" : "template-language-missing")" data-language-code="@language.Code" data-state="@(present ? "present" : "missing")">
<span>@language.Code:</span><span>@(present ? "Present" : "Missing")</span>
</li>
}
</ul>
}
</td>
<td>
@if (push is null) { <span>Not configured</span> }
else if (Model.Service.Languages.Count == 0) { <span>No configured languages</span> }
else {
var pushCodes = push.Languages.Select(l => l.LanguageCode).ToHashSet(StringComparer.Ordinal);
<ul class="template-language-statuses">
@foreach (var language in Model.Service.Languages) {
var present = pushCodes.Contains(language.Code);
<li class="template-language-status @(present ? "template-language-present" : "template-language-missing")" data-language-code="@language.Code" data-state="@(present ? "present" : "missing")"><span>@language.Code:</span><span>@(present ? "Present" : "Missing")</span></li>
}
</ul>
}
</td>
<td class="template-actions"><div class="list-action-links"><a href="@editUrl" class="btn btn-outline-primary btn-sm" aria-label="Edit template @templateKey">Edit</a>@if (email is not null) { <a asp-action="ConfirmDefinitionDelete" asp-route-serviceId="@serviceId" asp-route-definitionId="@email.Id" asp-route-keyFilter="@keyFilter" class="btn btn-outline-danger btn-sm" aria-label="Delete Email template @templateKey">Delete</a> }
@if (push is not null) { <a asp-action="ConfirmDelete" asp-controller="AdminPushTemplates" asp-route-serviceId="@serviceId" asp-route-key="@templateKey" asp-route-keyFilter="@keyFilter" class="btn btn-outline-danger btn-sm">Delete Push</a> }
</div></td>
</tr>
}
</tbody></table></div>