@juice-js/audit 1.0.0-alpha.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/{juice-js-audit-access-logs.page-qVBQLq2K.mjs → juice-js-audit-access-logs.page-BWEIcVKa.mjs} +3 -3
- package/fesm2022/{juice-js-audit-access-logs.page-qVBQLq2K.mjs.map → juice-js-audit-access-logs.page-BWEIcVKa.mjs.map} +1 -1
- package/fesm2022/juice-js-audit.mjs +1 -1
- package/package.json +1 -1
- package/styles/_audit.scss +3 -0
|
@@ -197,7 +197,7 @@ var AccessLogsPage = class AccessLogsPage {
|
|
|
197
197
|
</mat-select>
|
|
198
198
|
</mat-form-field>
|
|
199
199
|
<mat-form-field subscriptSizing="dynamic" class="ja-field-sm"><mat-label>App</mat-label><input matInput name="app" [(ngModel)]="form().app"></mat-form-field>
|
|
200
|
-
<mat-form-field subscriptSizing="dynamic" class="ja-field-
|
|
200
|
+
<mat-form-field subscriptSizing="dynamic" class="ja-field-sm"><mat-label>Slower than (ms)</mat-label><input matInput type="number" min="0" name="minMs" [(ngModel)]="form().minMs"></mat-form-field>
|
|
201
201
|
<mat-checkbox name="restricted" [(ngModel)]="form().restricted">Restricted only</mat-checkbox>
|
|
202
202
|
<button mat-flat-button type="submit">Search</button>
|
|
203
203
|
@if (filtered()) { <button mat-button type="button" (click)="clear()">Clear</button> }
|
|
@@ -485,7 +485,7 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
485
485
|
</mat-select>
|
|
486
486
|
</mat-form-field>
|
|
487
487
|
<mat-form-field subscriptSizing="dynamic" class="ja-field-sm"><mat-label>App</mat-label><input matInput name="app" [(ngModel)]="form().app"></mat-form-field>
|
|
488
|
-
<mat-form-field subscriptSizing="dynamic" class="ja-field-
|
|
488
|
+
<mat-form-field subscriptSizing="dynamic" class="ja-field-sm"><mat-label>Slower than (ms)</mat-label><input matInput type="number" min="0" name="minMs" [(ngModel)]="form().minMs"></mat-form-field>
|
|
489
489
|
<mat-checkbox name="restricted" [(ngModel)]="form().restricted">Restricted only</mat-checkbox>
|
|
490
490
|
<button mat-flat-button type="submit">Search</button>
|
|
491
491
|
@if (filtered()) { <button mat-button type="button" (click)="clear()">Clear</button> }
|
|
@@ -585,4 +585,4 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
585
585
|
});
|
|
586
586
|
export { AccessLogsPage };
|
|
587
587
|
|
|
588
|
-
//# sourceMappingURL=juice-js-audit-access-logs.page-
|
|
588
|
+
//# sourceMappingURL=juice-js-audit-access-logs.page-BWEIcVKa.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"juice-js-audit-access-logs.page-qVBQLq2K.mjs","names":[],"sources":["../../../../projects/juice-js/audit/src/lib/pages/access-logs.page.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, computed, inject, input, linkedSignal } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { MatButtonModule } from '@angular/material/button';\nimport { MatCheckboxModule } from '@angular/material/checkbox';\nimport { MatInputModule } from '@angular/material/input';\nimport { MatProgressBarModule } from '@angular/material/progress-bar';\nimport { MatSelectModule } from '@angular/material/select';\nimport { AuditApiService } from '../core/api.service';\nimport { AuditContextService } from '../core/context.service';\nimport { problemText } from '../shared/format';\nimport { cursorList } from '../shared/paging';\nimport { AccessLogTable, AuditContextBar } from '../shared/ui';\n\n/**\n * The access records in the window, newest first: who did what, with what outcome and how long it took. The filters\n * are in the URL, so a filtered list is a link to share.\n */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [FormsModule, MatButtonModule, MatCheckboxModule, MatInputModule, MatProgressBarModule, MatSelectModule,\n AuditContextBar, AccessLogTable],\n template: `\n <ja-context-bar><h1>Access records</h1></ja-context-bar>\n <form class=\"ja-filter-form\" (ngSubmit)=\"apply()\">\n <mat-form-field subscriptSizing=\"dynamic\" class=\"ja-field-sm\"><mat-label>User</mat-label><input matInput name=\"user\" [(ngModel)]=\"form().user\"></mat-form-field>\n <mat-form-field subscriptSizing=\"dynamic\" class=\"ja-field-sm\"><mat-label>Action</mat-label><input matInput name=\"action\" [(ngModel)]=\"form().action\"></mat-form-field>\n <mat-form-field subscriptSizing=\"dynamic\" class=\"ja-field-sm\"><mat-label>Path</mat-label><input matInput name=\"path\" [(ngModel)]=\"form().path\"></mat-form-field>\n <mat-form-field subscriptSizing=\"dynamic\" class=\"ja-field-xs\">\n <mat-label>Method</mat-label>\n <mat-select name=\"method\" [(ngModel)]=\"form().method\">\n <mat-option value=\"\">Any</mat-option>\n @for (m of methods; track m) { <mat-option [value]=\"m\">{{ m }}</mat-option> }\n </mat-select>\n </mat-form-field>\n <mat-form-field subscriptSizing=\"dynamic\" class=\"ja-field-xs\">\n <mat-label>Status</mat-label>\n <mat-select name=\"status\" [(ngModel)]=\"form().status\">\n <mat-option value=\"\">Any</mat-option>\n <mat-option value=\"error\">Failed (4xx, 5xx)</mat-option>\n @for (s of statuses; track s) { <mat-option [value]=\"s\">{{ s }}</mat-option> }\n </mat-select>\n </mat-form-field>\n <mat-form-field subscriptSizing=\"dynamic\" class=\"ja-field-sm\"><mat-label>App</mat-label><input matInput name=\"app\" [(ngModel)]=\"form().app\"></mat-form-field>\n <mat-form-field subscriptSizing=\"dynamic\" class=\"ja-field-xs\"><mat-label>Slower than (ms)</mat-label><input matInput type=\"number\" min=\"0\" name=\"minMs\" [(ngModel)]=\"form().minMs\"></mat-form-field>\n <mat-checkbox name=\"restricted\" [(ngModel)]=\"form().restricted\">Restricted only</mat-checkbox>\n <button mat-flat-button type=\"submit\">Search</button>\n @if (filtered()) { <button mat-button type=\"button\" (click)=\"clear()\">Clear</button> }\n </form>\n\n @if (logs.first.isLoading()) { <mat-progress-bar mode=\"indeterminate\" /> }\n @if (logs.first.error()) { <p class=\"ja-error\">{{ error() }}</p> }\n @if (logs.first.hasValue()) {\n @if (logs.items().length === 0) { <p class=\"ja-muted\">No access records match in this window.</p> }\n @else {\n <ja-access-log-table [rows]=\"logs.items()\" />\n <div class=\"ja-more\">\n <span class=\"ja-muted\">{{ logs.items().length }} record{{ logs.items().length === 1 ? '' : 's' }}{{ logs.hasMore() ? ', newest first' : '' }}</span>\n @if (logs.hasMore()) {\n <button mat-button (click)=\"logs.more()\" [disabled]=\"logs.loadingMore()\">{{ logs.loadingMore() ? 'Loading…' : 'Older records' }}</button>\n }\n @if (logs.moreError()) { <span class=\"ja-error\">{{ moreError() }}</span> }\n </div>\n }\n }`,\n})\nexport class AccessLogsPage {\n private readonly api = inject(AuditApiService);\n protected readonly ctx = inject(AuditContextService);\n\n readonly user = input<string>();\n readonly action = input<string>();\n readonly path = input<string>();\n readonly method = input<string>();\n readonly status = input<string>();\n readonly app = input<string>();\n readonly minMs = input<string>();\n readonly restricted = input<string>();\n readonly traceId = input<string>();\n\n protected readonly methods = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'MESSAGE', 'REQUEST', 'NOTIFICATION'];\n protected readonly statuses = ['2xx', '3xx', '4xx', '5xx'];\n\n private readonly filters = computed(() => ({\n user: this.user() ?? '', action: this.action() ?? '', path: this.path() ?? '', method: this.method() ?? '',\n status: this.status() ?? '', app: this.app() ?? '', minMs: this.minMs() ?? '', restricted: this.restricted() === 'true',\n traceId: this.traceId() ?? '',\n }));\n /** The form, reset to the URL's filters whenever they change. */\n protected readonly form = linkedSignal(() => ({ ...this.filters() }));\n protected readonly filtered = computed(() => Object.values(this.filters()).some(v => v !== '' && v !== false));\n\n protected readonly logs = cursorList(\n () => ({ filters: this.filters(), range: this.ctx.range(), abs: this.ctx.absolute() }),\n p => ({ ...this.ctx.window(), ...p.filters, restricted: p.filters.restricted ? true : null, limit: 50 }),\n q => this.api.accessLogs(q));\n protected readonly error = computed(() => problemText(this.logs.first.error()));\n protected readonly moreError = computed(() => problemText(this.logs.moreError()));\n\n apply() {\n const f = this.form();\n this.ctx.filter({\n user: f.user.trim() || null, action: f.action.trim() || null, path: f.path.trim() || null, method: f.method || null,\n status: f.status || null, app: f.app.trim() || null, minMs: String(f.minMs ?? '').trim() || null,\n restricted: f.restricted ? 'true' : null, traceId: f.traceId.trim() || null,\n });\n }\n\n clear() {\n this.ctx.filter({ user: null, action: null, path: null, method: null, status: null, app: null, minMs: null, restricted: null, traceId: null });\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"juice-js-audit-access-logs.page-BWEIcVKa.mjs","names":[],"sources":["../../../../projects/juice-js/audit/src/lib/pages/access-logs.page.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, computed, inject, input, linkedSignal } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { MatButtonModule } from '@angular/material/button';\nimport { MatCheckboxModule } from '@angular/material/checkbox';\nimport { MatInputModule } from '@angular/material/input';\nimport { MatProgressBarModule } from '@angular/material/progress-bar';\nimport { MatSelectModule } from '@angular/material/select';\nimport { AuditApiService } from '../core/api.service';\nimport { AuditContextService } from '../core/context.service';\nimport { problemText } from '../shared/format';\nimport { cursorList } from '../shared/paging';\nimport { AccessLogTable, AuditContextBar } from '../shared/ui';\n\n/**\n * The access records in the window, newest first: who did what, with what outcome and how long it took. The filters\n * are in the URL, so a filtered list is a link to share.\n */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [FormsModule, MatButtonModule, MatCheckboxModule, MatInputModule, MatProgressBarModule, MatSelectModule,\n AuditContextBar, AccessLogTable],\n template: `\n <ja-context-bar><h1>Access records</h1></ja-context-bar>\n <form class=\"ja-filter-form\" (ngSubmit)=\"apply()\">\n <mat-form-field subscriptSizing=\"dynamic\" class=\"ja-field-sm\"><mat-label>User</mat-label><input matInput name=\"user\" [(ngModel)]=\"form().user\"></mat-form-field>\n <mat-form-field subscriptSizing=\"dynamic\" class=\"ja-field-sm\"><mat-label>Action</mat-label><input matInput name=\"action\" [(ngModel)]=\"form().action\"></mat-form-field>\n <mat-form-field subscriptSizing=\"dynamic\" class=\"ja-field-sm\"><mat-label>Path</mat-label><input matInput name=\"path\" [(ngModel)]=\"form().path\"></mat-form-field>\n <mat-form-field subscriptSizing=\"dynamic\" class=\"ja-field-xs\">\n <mat-label>Method</mat-label>\n <mat-select name=\"method\" [(ngModel)]=\"form().method\">\n <mat-option value=\"\">Any</mat-option>\n @for (m of methods; track m) { <mat-option [value]=\"m\">{{ m }}</mat-option> }\n </mat-select>\n </mat-form-field>\n <mat-form-field subscriptSizing=\"dynamic\" class=\"ja-field-xs\">\n <mat-label>Status</mat-label>\n <mat-select name=\"status\" [(ngModel)]=\"form().status\">\n <mat-option value=\"\">Any</mat-option>\n <mat-option value=\"error\">Failed (4xx, 5xx)</mat-option>\n @for (s of statuses; track s) { <mat-option [value]=\"s\">{{ s }}</mat-option> }\n </mat-select>\n </mat-form-field>\n <mat-form-field subscriptSizing=\"dynamic\" class=\"ja-field-sm\"><mat-label>App</mat-label><input matInput name=\"app\" [(ngModel)]=\"form().app\"></mat-form-field>\n <mat-form-field subscriptSizing=\"dynamic\" class=\"ja-field-sm\"><mat-label>Slower than (ms)</mat-label><input matInput type=\"number\" min=\"0\" name=\"minMs\" [(ngModel)]=\"form().minMs\"></mat-form-field>\n <mat-checkbox name=\"restricted\" [(ngModel)]=\"form().restricted\">Restricted only</mat-checkbox>\n <button mat-flat-button type=\"submit\">Search</button>\n @if (filtered()) { <button mat-button type=\"button\" (click)=\"clear()\">Clear</button> }\n </form>\n\n @if (logs.first.isLoading()) { <mat-progress-bar mode=\"indeterminate\" /> }\n @if (logs.first.error()) { <p class=\"ja-error\">{{ error() }}</p> }\n @if (logs.first.hasValue()) {\n @if (logs.items().length === 0) { <p class=\"ja-muted\">No access records match in this window.</p> }\n @else {\n <ja-access-log-table [rows]=\"logs.items()\" />\n <div class=\"ja-more\">\n <span class=\"ja-muted\">{{ logs.items().length }} record{{ logs.items().length === 1 ? '' : 's' }}{{ logs.hasMore() ? ', newest first' : '' }}</span>\n @if (logs.hasMore()) {\n <button mat-button (click)=\"logs.more()\" [disabled]=\"logs.loadingMore()\">{{ logs.loadingMore() ? 'Loading…' : 'Older records' }}</button>\n }\n @if (logs.moreError()) { <span class=\"ja-error\">{{ moreError() }}</span> }\n </div>\n }\n }`,\n})\nexport class AccessLogsPage {\n private readonly api = inject(AuditApiService);\n protected readonly ctx = inject(AuditContextService);\n\n readonly user = input<string>();\n readonly action = input<string>();\n readonly path = input<string>();\n readonly method = input<string>();\n readonly status = input<string>();\n readonly app = input<string>();\n readonly minMs = input<string>();\n readonly restricted = input<string>();\n readonly traceId = input<string>();\n\n protected readonly methods = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'MESSAGE', 'REQUEST', 'NOTIFICATION'];\n protected readonly statuses = ['2xx', '3xx', '4xx', '5xx'];\n\n private readonly filters = computed(() => ({\n user: this.user() ?? '', action: this.action() ?? '', path: this.path() ?? '', method: this.method() ?? '',\n status: this.status() ?? '', app: this.app() ?? '', minMs: this.minMs() ?? '', restricted: this.restricted() === 'true',\n traceId: this.traceId() ?? '',\n }));\n /** The form, reset to the URL's filters whenever they change. */\n protected readonly form = linkedSignal(() => ({ ...this.filters() }));\n protected readonly filtered = computed(() => Object.values(this.filters()).some(v => v !== '' && v !== false));\n\n protected readonly logs = cursorList(\n () => ({ filters: this.filters(), range: this.ctx.range(), abs: this.ctx.absolute() }),\n p => ({ ...this.ctx.window(), ...p.filters, restricted: p.filters.restricted ? true : null, limit: 50 }),\n q => this.api.accessLogs(q));\n protected readonly error = computed(() => problemText(this.logs.first.error()));\n protected readonly moreError = computed(() => problemText(this.logs.moreError()));\n\n apply() {\n const f = this.form();\n this.ctx.filter({\n user: f.user.trim() || null, action: f.action.trim() || null, path: f.path.trim() || null, method: f.method || null,\n status: f.status || null, app: f.app.trim() || null, minMs: String(f.minMs ?? '').trim() || null,\n restricted: f.restricted ? 'true' : null, traceId: f.traceId.trim() || null,\n });\n }\n\n clear() {\n this.ctx.filter({ user: null, action: null, path: null, method: null, status: null, app: null, minMs: null, restricted: null, traceId: null });\n }\n}\n"],"mappings":"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"}
|
|
@@ -275,7 +275,7 @@ function page(path, title, load) {
|
|
|
275
275
|
}
|
|
276
276
|
const AUDIT_ROUTES = [
|
|
277
277
|
page("", "Overview", () => import("./juice-js-audit-overview.page-DnP722u2.mjs").then((m) => m.OverviewPage)),
|
|
278
|
-
page("access-logs", "Access records", () => import("./juice-js-audit-access-logs.page-
|
|
278
|
+
page("access-logs", "Access records", () => import("./juice-js-audit-access-logs.page-BWEIcVKa.mjs").then((m) => m.AccessLogsPage)),
|
|
279
279
|
page("access-logs/:id", "Access record", () => import("./juice-js-audit-access-log.page-CrH7ib4K.mjs").then((m) => m.AccessLogPage)),
|
|
280
280
|
page("data-changes", "Data changes", () => import("./juice-js-audit-data-changes.page-C-k_Shce.mjs").then((m) => m.DataChangesPage)),
|
|
281
281
|
page("data-changes/:id", "Data change", () => import("./juice-js-audit-data-change.page-CuI9ccJb.mjs").then((m) => m.DataChangePage)),
|
package/package.json
CHANGED
package/styles/_audit.scss
CHANGED
|
@@ -79,6 +79,9 @@
|
|
|
79
79
|
.ja-lookup { display: flex; align-items: center; gap: 4px; border: 1px solid var(--ja-border); border-radius: 6px; padding: 2px 8px; background: var(--ja-surface);
|
|
80
80
|
input { border: 0; outline: 0; background: transparent; color: inherit; width: 260px; font: inherit; padding: 6px 0; }
|
|
81
81
|
mat-icon { color: var(--ja-muted); font-size: 18px; height: 18px; width: 18px; } }
|
|
82
|
+
// The filters, the context bar and every other field the pages size label each field. An app theme denser than -1 hides a fill field's label (and
|
|
83
|
+
// these fields have no placeholder to fall back on), so keep them at -1 whatever the app's density.
|
|
84
|
+
.ja-context, .ja-filter-form, mat-form-field[class*='ja-field-'] { @include mat.form-field-density(-1); }
|
|
82
85
|
.ja-filter-form { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-bottom: 12px; }
|
|
83
86
|
|
|
84
87
|
.ja-card { display: block; background: var(--ja-surface); border: 1px solid var(--ja-border); border-radius: 8px; padding: 12px 16px; margin-bottom: 12px; }
|