@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.
@@ -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-xs"><mat-label>Slower than (ms)</mat-label><input matInput type="number" min="0" name="minMs" [(ngModel)]="form().minMs"></mat-form-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-xs"><mat-label>Slower than (ms)</mat-label><input matInput type="number" min="0" name="minMs" [(ngModel)]="form().minMs"></mat-form-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-qVBQLq2K.mjs.map
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":";;;;;;;;;;;;;;;;;AAiEA,IAAa,iBAAb,MAAa,eAAc;CACR,MAAM,OAAO,eAAe;CAC1B,MAAM,OAAO,mBAAmB;CAE1C,OAAO,MAAe,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;CACtB,SAAS,MAAe,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,SAAA,CAAA,+BAAA,CAAA,CAAA;CACxB,OAAO,MAAe,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;CACtB,SAAS,MAAe,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,SAAA,CAAA,+BAAA,CAAA,CAAA;CACxB,SAAS,MAAe,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,SAAA,CAAA,+BAAA,CAAA,CAAA;CACxB,MAAM,MAAe,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,MAAA,CAAA,+BAAA,CAAA,CAAA;CACrB,QAAQ,MAAe,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CACvB,aAAa,MAAe,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,aAAA,CAAA,+BAAA,CAAA,CAAA;CAC5B,UAAU,MAAe,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;CAEf,UAAU;EAAC;EAAO;EAAQ;EAAO;EAAS;EAAU;EAAW;EAAW;CAAc;CACxF,WAAW;EAAC;EAAO;EAAO;EAAO;CAAK;CAExC,UAAU,gBAAgB;EACzC,MAAM,KAAK,KAAI,KAAM;EAAI,QAAQ,KAAK,OAAM,KAAM;EAAI,MAAM,KAAK,KAAI,KAAM;EAAI,QAAQ,KAAK,OAAM,KAAM;EACxG,QAAQ,KAAK,OAAM,KAAM;EAAI,KAAK,KAAK,IAAG,KAAM;EAAI,OAAO,KAAK,MAAK,KAAM;EAAI,YAAY,KAAK,WAAU,MAAO;EACjH,SAAS,KAAK,QAAO,KAAM;CAC5B,IAAE,GAAA,YAAA,CAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;CAEgB,OAAO,oBAAoB,EAAE,GAAG,KAAK,QAAO,EAAE,IAAI,GAAA,YAAA,CAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;CAClD,WAAW,eAAe,OAAO,OAAO,KAAK,QAAO,CAAE,CAAC,CAAC,MAAK,MAAK,MAAM,MAAM,MAAM,KAAK,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,WAAA,CAAA,+BAAA,CAAA,CAAA;CAE3F,OAAO,kBACjB;EAAE,SAAS,KAAK,QAAO;EAAI,OAAO,KAAK,IAAI,MAAK;EAAI,KAAK,KAAK,IAAI,SAAQ;CAAE,KACnF,OAAM;EAAE,GAAG,KAAK,IAAI,OAAM;EAAI,GAAG,EAAE;EAAS,YAAY,EAAE,QAAQ,aAAa,OAAO;EAAM,OAAO;CAAE,KACrG,MAAK,KAAK,IAAI,WAAW,CAAC,CAAC;CACV,QAAQ,eAAe,YAAY,KAAK,KAAK,MAAM,MAAK,CAAE,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CAC5D,YAAY,eAAe,YAAY,KAAK,KAAK,UAAS,CAAE,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,YAAA,CAAA,+BAAA,CAAA,CAAA;CAEjF,QAAK;EACH,MAAM,IAAI,KAAK,KAAI;EACnB,KAAK,IAAI,OAAO;GACd,MAAM,EAAE,KAAK,KAAI,KAAM;GAAM,QAAQ,EAAE,OAAO,KAAI,KAAM;GAAM,MAAM,EAAE,KAAK,KAAI,KAAM;GAAM,QAAQ,EAAE,UAAU;GAC/G,QAAQ,EAAE,UAAU;GAAM,KAAK,EAAE,IAAI,KAAI,KAAM;GAAM,OAAO,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC,KAAI,KAAM;GAC5F,YAAY,EAAE,aAAa,SAAS;GAAM,SAAS,EAAE,QAAQ,KAAI,KAAM;EACxE,CAAA;CACH;CAEA,QAAK;EACH,KAAK,IAAI,OAAO;GAAE,MAAM;GAAM,QAAQ;GAAM,MAAM;GAAM,QAAQ;GAAM,QAAQ;GAAM,KAAK;GAAM,OAAO;GAAM,YAAY;GAAM,SAAS;EAAI,CAAE;CAC/I;CA5CW,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAc,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAd,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAc,cAAA;EAAA,UAAA;EAAA,QAAA;GAAA,MAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,QAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,MAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,QAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,QAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,KAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,OAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,YAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,SAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;EAAA;EAAA,UAAA;EAAA,UA5Cf;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA0CN,UAAA;EAAA,cAAA;GAAA;IAAA,MAAA;IAAA,MA5CM;GAAW;GAAA;IAAA,MAAA;IAAA,MAAA,GAAA;IAAA,UAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAA,GAAA;IAAA,UAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAA,GAAA;IAAA,UAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAA,GAAA;IAAA,UAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAA,GAAA;IAAA,UAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAA,GAAA;IAAA,UAAA;IAAA,QAAA,CAAA,KAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAA,GAAA;IAAA,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;IAAA;IAAA,SAAA,CAAA,eAAA;IAAA,UAAA,CAAA,SAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAA,GAAA;IAAA,UAAA;IAAA,QAAA,CAAA,eAAA;IAAA,SAAA,CAAA,UAAA;IAAA,UAAA,CAAA,QAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAE;GAAe;GAAA;IAAA,MAAA;IAAA,MAAA,GAAA;IAAA,UAAA;IAAA,QAAA,CAAA,WAAA;IAAA,UAAA,CAAA,aAAA,WAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAE;GAAiB;GAAA;IAAA,MAAA;IAAA,MAAA,GAAA;IAAA,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;IAAA;IAAA,SAAA,CAAA,UAAA,qBAAA;IAAA,UAAA,CAAA,aAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAE;GAAc;GAAA;IAAA,MAAA;IAAA,MAAA,GAAA;IAAA,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;IAAA;IAAA,UAAA,CAAA,UAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAA,GAAA;IAAA,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;IAAA;IAAA,UAAA,CAAA,cAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAA,GAAA;IAAA,UAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAE;GAAoB;GAAA;IAAA,MAAA;IAAA,MAAA,GAAA;IAAA,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;IAAA;IAAA,SAAA,CAAA,cAAA;IAAA,UAAA,CAAA,gBAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAE;GAAe;GAAA;IAAA,MAAA;IAAA,MAAA,GAAA;IAAA,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;IAAA;IAAA,SAAA;KAAA;KAAA;KAAA;KAAA;KAAA;IAAA;IAAA,UAAA,CAAA,WAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAA,GAAA;IAAA,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;IAAA;IAAA,SAAA,CAAA,mBAAA;IAAA,UAAA,CAAA,WAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAC9G;IAAe,UAAA;IAAA,QAAA,CAAA,WAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAE;IAAc,UAAA;IAAA,QAAA,CAAA,QAAA,SAAA;GAAA;EAAA;EAAA,iBAAA,GAAA,wBAAA;CAAA,CAAA;;AA6CtB,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAc,YAAA,CAAA;EAhD1B,MAAA;EAAU,MAAA,CAAA;GACT,iBAAiB,wBAAwB;GACzC,SAAS;IAAC;IAAa;IAAiB;IAAmB;IAAgB;IAAsB;IAC/F;IAAiB;GAAc;GACjC,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA2CX,CAAA"}
@@ -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-qVBQLq2K.mjs").then((m) => m.AccessLogsPage)),
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juice-js/audit",
3
- "version": "1.0.0-alpha.1",
3
+ "version": "1.0.0",
4
4
  "description": "Juice Audit pages (overview, access records, data changes, trace) for an Angular app on juice-layout",
5
5
  "author": "jack@creatorflow.io",
6
6
  "license": "MIT",
@@ -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; }