| | | 1 | | @using OzonDomains.Models |
| | | 2 | | @using OzonOrdersWeb.Areas.Studio2.ViewModels.Grid |
| | | 3 | | @model List<EmailRoutingRule> |
| | | 4 | | @{ |
| | 0 | 5 | | ViewData["Title"] = "Правила импорта из почты"; |
| | 0 | 6 | | Layout = "~/Views/Shared/_Layout.cshtml"; |
| | 0 | 7 | | var rows = Model.Select(r => new |
| | 0 | 8 | | { |
| | 0 | 9 | | id = r.Id, |
| | 0 | 10 | | name = r.Name, |
| | 0 | 11 | | isActive = r.IsActive, |
| | 0 | 12 | | priority = r.Priority, |
| | 0 | 13 | | allowedSenders = r.AllowedSenders, |
| | 0 | 14 | | subjectPattern = r.SubjectPattern, |
| | 0 | 15 | | fileNamePattern = r.FileNamePattern, |
| | 0 | 16 | | dropboxFolderTemplate = r.DropboxFolderTemplate, |
| | 0 | 17 | | conflictPolicy = r.ConflictPolicy.ToString(), |
| | 0 | 18 | | onlyFirstFile = r.ProcessOnlyFirstMatchedAttachment |
| | 0 | 19 | | }); |
| | | 20 | | } |
| | | 21 | | |
| | 0 | 22 | | @await Html.PartialAsync("_BsxGridShell") |
| | | 23 | | |
| | | 24 | | <div class="container-fluid py-3 bsx-surface"> |
| | | 25 | | <div class="app-section-hero app-section-hero--import d-flex flex-wrap justify-content-between align-items-start gap |
| | | 26 | | <div> |
| | | 27 | | <h1><i class="bi bi-envelope-arrow-up text-primary me-2"></i>Правила импорта из почты</h1> |
| | | 28 | | <div class="subtitle">Условия обработки писем и загрузки заказов в систему</div> |
| | | 29 | | <div class="subtitle-help"> |
| | | 30 | | Правило определяет письма и вложения поставщика, а также сопоставление, по которому из файла создаются з |
| | | 31 | | Правила применяются по возрастанию приоритета (меньше число — выше приоритет); если совпало несколько, |
| | | 32 | | применяется только первое (если не настроен multiMatch). Паттерны — регулярные выражения. |
| | | 33 | | </div> |
| | | 34 | | <div class="app-section-hero__quick-links"> |
| | | 35 | | <a asp-area="Studio2" asp-controller="EmailRoutingResults" asp-action="Index"><i class="bi bi-list-check |
| | | 36 | | <a asp-area="Studio2" asp-controller="EmailRoutingScheduler" asp-action="Index"><i class="bi bi-clock">< |
| | | 37 | | <a asp-area="Studio2" asp-controller="ColumnMappings" asp-action="Index"><i class="bi bi-columns-gap"></ |
| | | 38 | | </div> |
| | | 39 | | </div> |
| | | 40 | | <div class="d-flex flex-wrap gap-2 align-items-center"> |
| | | 41 | | <div class="bsx-dir-stats"> |
| | 0 | 42 | | <span class="bsx-dir-stat">Всего <b>@Model.Count</b></span> |
| | 0 | 43 | | <span class="bsx-dir-stat">Активных <b>@Model.Count(r => r.IsActive)</b></span> |
| | | 44 | | </div> |
| | | 45 | | <form asp-action="DryRun" method="post"> |
| | 0 | 46 | | @Html.AntiForgeryToken() |
| | | 47 | | <button type="submit" class="btn btn-sm btn-outline-warning"><i class="bi bi-play-circle me-1"></i>Тесто |
| | | 48 | | </form> |
| | | 49 | | <a asp-action="Create" class="btn btn-primary btn-sm"><i class="bi bi-plus-circle me-1"></i>Новое правило</a |
| | | 50 | | </div> |
| | | 51 | | </div> |
| | | 52 | | |
| | 0 | 53 | | @if (TempData["TransactionResult"] != null) |
| | | 54 | | { |
| | | 55 | | <div class="alert alert-info alert-dismissible fade show" role="alert"> |
| | 0 | 56 | | <i class="bi bi-info-circle-fill me-1"></i>@TempData["TransactionResult"] |
| | | 57 | | <button type="button" class="btn-close" data-bs-dismiss="alert"></button> |
| | | 58 | | </div> |
| | | 59 | | } |
| | | 60 | | |
| | 0 | 61 | | @await Html.PartialAsync("_BsxDirectoryGrid", new BsxDirectoryGridViewModel("emailRule", "Правила", "fa-envelope-ope |
| | 0 | 62 | | "Двойной клик — редактирование правила.")) |
| | | 63 | | </div> |
| | | 64 | | |
| | | 65 | | @section Scripts { |
| | | 66 | | <script src="~/js/Studio2/Grid/bsx-directory.js" asp-append-version="true"></script> |
| | | 67 | | <script> |
| | | 68 | | (function () { |
| | | 69 | | const D = window.BsxDirectory; |
| | 0 | 70 | | const base = '@Url.Action("Index", "EmailRoutingRules", new { area = "Studio2" })'; |
| | | 71 | | const url = (action, id) => base + '/' + action + '/' + id; |
| | | 72 | | const CONFLICT = { |
| | | 73 | | Overwrite: ['Замена', 'warning', 'Перезаписать файл'], |
| | | 74 | | SkipIfExists: ['Пропуск', 'muted', 'Пропустить, если файл существует'], |
| | | 75 | | VersionedName: ['Версия', 'info', 'Добавить суффикс к имени'] |
| | | 76 | | }; |
| | | 77 | | const mono = p => p.value ? `<span class="bsx-code">${BsxGrid.esc(p.value)}</span>` : '<span class="bsx-muted">— |
| | | 78 | | |
| | | 79 | | D.grid({ |
| | | 80 | | key: 'dirEmailRule', |
| | | 81 | | prefix: 'emailRule', |
| | 0 | 82 | | rows: @Json.Serialize(rows), |
| | | 83 | | rowUrl: r => url('Edit', r.id), |
| | | 84 | | rowClassRules: { 'bsx-row-muted': p => p.data && !p.data.isActive }, |
| | | 85 | | columnDefs: [ |
| | | 86 | | D.numCol({ field: 'priority', headerName: 'Приоритет', headerTooltip: 'Меньше — выше', width: 110, sort: |
| | | 87 | | { field: 'name', headerName: 'Название', flex: 1, minWidth: 220, |
| | | 88 | | cellRenderer: p => `<span class="fw-semibold">${BsxGrid.esc(p.value)}</span>${p.data.onlyFirstFile ? ' |
| | | 89 | | D.boolCol({ field: 'isActive', headerName: 'Статус', width: 130, filterParams: { labels: { 'true': 'Акти |
| | | 90 | | cellRenderer: p => D.yesNo(p.value, 'Активно', 'Выключено') }), |
| | | 91 | | { field: 'allowedSenders', headerName: 'Отправители', width: 220, tooltipField: 'allowedSenders', valueF |
| | | 92 | | { field: 'subjectPattern', headerName: 'Паттерн темы', width: 170, tooltipField: 'subjectPattern', cellR |
| | | 93 | | { field: 'fileNamePattern', headerName: 'Паттерн файла', width: 170, tooltipField: 'fileNamePattern', ce |
| | | 94 | | { field: 'dropboxFolderTemplate', headerName: 'Шаблон импорта', width: 220, tooltipField: 'dropboxFolder |
| | | 95 | | D.setCol({ field: 'conflictPolicy', headerName: 'Конфликт', width: 120, |
| | | 96 | | filterParams: { labels: Object.fromEntries(Object.entries(CONFLICT).map(([k, v]) => [k, v[0]])) }, |
| | | 97 | | cellRenderer: p => { const c = CONFLICT[p.value]; return c ? `<span title="${c[2]}">${D.tone(c[0], c[1 |
| | | 98 | | D.numCol({ field: 'id', headerName: '#', width: 70, hide: true }), |
| | | 99 | | D.actionsCol(r => [ |
| | | 100 | | { icon: 'fa-pencil-alt', title: 'Редактировать', href: url('Edit', r.id) }, |
| | | 101 | | { icon: r.isActive ? 'fa-pause' : 'fa-play', title: r.isActive ? 'Деактивировать' : 'Активировать', |
| | | 102 | | { icon: 'fa-trash', title: 'Удалить', kind: 'danger', post: true, href: url('Delete', r.id), confirm |
| | | 103 | | ], { width: 130 }) |
| | | 104 | | ] |
| | | 105 | | }); |
| | | 106 | | })(); |
| | | 107 | | </script> |
| | | 108 | | } |