| | | 1 | | @{ |
| | 0 | 2 | | var f = ViewBag.F as Dictionary<string, string?> ?? new(); |
| | 0 | 3 | | var legacyParams = f.Where(kv => !string.IsNullOrWhiteSpace(kv.Value)).ToDictionary(kv => kv.Key, kv => kv.Value); |
| | | 4 | | } |
| | | 5 | | |
| | | 6 | | <section class="admin-hero"> |
| | | 7 | | <h1>Журнал аудита</h1> |
| | | 8 | | <p class="subtitle">История изменений прав, ролей и конфигурации доступа.</p> |
| | | 9 | | <p class="subtitle-help">Фильтры колонок, сортировка и поиск работают по всему журналу.</p> |
| | | 10 | | </section> |
| | | 11 | | |
| | | 12 | | <nav class="admin-quick-links"> |
| | | 13 | | <a asp-area="Admin" asp-controller="Users" asp-action="Index"><i class="bi bi-people"></i>Пользователи</a> |
| | | 14 | | <a asp-area="Admin" asp-controller="Roles" asp-action="Index"><i class="bi bi-person-badge"></i>Роли</a> |
| | | 15 | | <a asp-area="Admin" asp-controller="Home" asp-action="Index"><i class="bi bi-speedometer2"></i>Обзор</a> |
| | | 16 | | </nav> |
| | | 17 | | |
| | | 18 | | <section class="admin-intro"> |
| | | 19 | | <i class="bi bi-info-circle"></i> |
| | | 20 | | <div>Показываются записи действий администраторов. Двойной клик по строке — детали операции со старым и новым значен |
| | | 21 | | </section> |
| | | 22 | | |
| | 0 | 23 | | @if (legacyParams.Count > 0) |
| | | 24 | | { |
| | | 25 | | <div class="admin-toolbar admin-surface"> |
| | | 26 | | <div class="bsx-dir-stats"> |
| | 0 | 27 | | @foreach (var (key, value) in legacyParams) |
| | | 28 | | { |
| | 0 | 29 | | <span class="bsx-dir-stat">@(key switch { "action" => "Действие", "entity" => "Сущность", _ => "Пользова |
| | | 30 | | } |
| | | 31 | | </div> |
| | | 32 | | <a asp-action="Index" class="btn btn-sm btn-outline-secondary"><i class="bi bi-x-lg"></i> Весь журнал</a> |
| | | 33 | | </div> |
| | | 34 | | } |
| | | 35 | | |
| | 0 | 36 | | @await Html.PartialAsync("~/Areas/Studio2/Views/Shared/_BsxDirectoryGrid.cshtml", new BsxDirectoryGridViewModel("admAudi |
| | | 37 | | |
| | | 38 | | @section Scripts { |
| | | 39 | | <script> |
| | | 40 | | (function () { |
| | | 41 | | const D = window.BsxDirectory, BG = window.BsxGrid; |
| | 0 | 42 | | const details = id => '@Url.Action("Details")/' + id; |
| | 0 | 43 | | const legacyParams = @Html.Raw(System.Text.Json.JsonSerializer.Serialize(legacyParams)); |
| | | 44 | | const facet = (colId, headerName, extra) => D.setCol(Object.assign({ |
| | | 45 | | colId: colId, field: colId, headerName: headerName, minWidth: 150, flex: 1, |
| | | 46 | | filterParams: { facets: true } |
| | | 47 | | }, extra || {})); |
| | | 48 | | D.serverGrid({ |
| | | 49 | | key: 'admAudit', prefix: 'admAudit', |
| | 0 | 50 | | url: '@Url.Action("Grid")', facetsUrl: '@Url.Action("GridFacets")', |
| | | 51 | | params: () => legacyParams, |
| | | 52 | | rowUrl: r => details(r.id), |
| | | 53 | | columnDefs: [ |
| | | 54 | | D.numCol({ colId: 'id', field: 'id', headerName: '#', width: 90, hide: true }), |
| | | 55 | | { |
| | | 56 | | colId: 'timestamp', field: 'timestamp', headerName: 'Время', width: 170, |
| | | 57 | | filter: 'agDateColumnFilter', filterParams: { maxNumConditions: 1, inRangeInclusive: true }, |
| | | 58 | | valueFormatter: p => p.data ? BG.fmtUtc(p.value) : '' |
| | | 59 | | }, |
| | | 60 | | facet('actorUserName', 'Пользователь'), |
| | | 61 | | facet('action', 'Действие', { cellRenderer: p => p.value ? D.tone(p.value, 'info') : '' }), |
| | | 62 | | facet('entityType', 'Сущность'), |
| | | 63 | | { colId: 'entityId', field: 'entityId', headerName: 'ID', width: 130 }, |
| | | 64 | | { colId: 'ipAddress', field: 'ipAddress', headerName: 'IP', width: 140 }, |
| | | 65 | | { colId: 'comment', field: 'comment', headerName: 'Комментарий', minWidth: 200, flex: 2, tooltipFiel |
| | | 66 | | D.actionsCol(r => [{ icon: 'fa-eye', title: 'Детали записи', kind: 'view', href: details(r.id) }], { |
| | | 67 | | ] |
| | | 68 | | }); |
| | | 69 | | })(); |
| | | 70 | | </script> |
| | | 71 | | } |