@happyvertical/smrt-svelte 0.55.4 → 0.55.6
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/dist/components/audit/AuditList.svelte +51 -10
- package/dist/components/audit/AuditList.svelte.d.ts +13 -1
- package/dist/components/audit/AuditList.svelte.d.ts.map +1 -1
- package/dist/components/audit/RecordHistory.svelte +168 -10
- package/dist/components/audit/RecordHistory.svelte.d.ts +11 -1
- package/dist/components/audit/RecordHistory.svelte.d.ts.map +1 -1
- package/dist/components/audit/index.d.ts +1 -1
- package/dist/components/audit/index.d.ts.map +1 -1
- package/dist/components/audit/types.d.ts +18 -0
- package/dist/components/audit/types.d.ts.map +1 -1
- package/package.json +15 -15
|
@@ -4,7 +4,14 @@ import { useI18n } from '@happyvertical/smrt-ui/i18n';
|
|
|
4
4
|
import { Button } from '@happyvertical/smrt-ui/ui';
|
|
5
5
|
import { M } from '../../i18n/strings.audit.js';
|
|
6
6
|
import RecordHistory from './RecordHistory.svelte';
|
|
7
|
-
import type {
|
|
7
|
+
import type {
|
|
8
|
+
AuditEntryLabel,
|
|
9
|
+
AuditFieldLabel,
|
|
10
|
+
AuditHistoryEntry,
|
|
11
|
+
AuditListFilter,
|
|
12
|
+
AuditResourceHref,
|
|
13
|
+
AuditValueFormatter,
|
|
14
|
+
} from './types.js';
|
|
8
15
|
|
|
9
16
|
interface Props {
|
|
10
17
|
/** Authorized data only. For server paging use onfilter to reload the authorized page. */
|
|
@@ -15,8 +22,31 @@ interface Props {
|
|
|
15
22
|
error?: string | null;
|
|
16
23
|
/** Requests an authorized server page for the submitted filters instead of filtering locally. */
|
|
17
24
|
onfilter?: (filter: AuditListFilter) => void;
|
|
25
|
+
/** Shows the built-in person, record and date filters. */
|
|
26
|
+
showFilters?: boolean;
|
|
27
|
+
/** Resolves friendly resource text for each authorized entry. */
|
|
28
|
+
resourceLabel?: AuditEntryLabel;
|
|
29
|
+
/** Resolves an already-authorized local or HTTP(S) destination for each entry. */
|
|
30
|
+
resourceHref?: AuditResourceHref;
|
|
31
|
+
/** Resolves friendly action text for each authorized entry. */
|
|
32
|
+
actionLabel?: AuditEntryLabel;
|
|
33
|
+
/** Resolves friendly field text for each authorized entry change. */
|
|
34
|
+
fieldLabel?: AuditFieldLabel;
|
|
35
|
+
/** Formats before/after values as escaped text. */
|
|
36
|
+
formatValue?: AuditValueFormatter;
|
|
18
37
|
}
|
|
19
|
-
let {
|
|
38
|
+
let {
|
|
39
|
+
entries,
|
|
40
|
+
loading = false,
|
|
41
|
+
error = null,
|
|
42
|
+
onfilter,
|
|
43
|
+
showFilters = true,
|
|
44
|
+
resourceLabel,
|
|
45
|
+
resourceHref,
|
|
46
|
+
actionLabel,
|
|
47
|
+
fieldLabel,
|
|
48
|
+
formatValue,
|
|
49
|
+
}: Props = $props();
|
|
20
50
|
const { t } = useI18n();
|
|
21
51
|
let profileId = $state('');
|
|
22
52
|
let resourceId = $state('');
|
|
@@ -51,14 +81,25 @@ function apply() {
|
|
|
51
81
|
</script>
|
|
52
82
|
|
|
53
83
|
<section aria-label={t(M['ui.audit.list'])}>
|
|
54
|
-
|
|
55
|
-
<
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
84
|
+
{#if showFilters}
|
|
85
|
+
<Form onsubmit={apply} class="smrt-audit-filters">
|
|
86
|
+
<FormGroup label={t(M['ui.audit.person'])}><Input bind:value={profileId} /></FormGroup>
|
|
87
|
+
<FormGroup label={t(M['ui.audit.record'])}><Input bind:value={resourceId} /></FormGroup>
|
|
88
|
+
<FormGroup label={t(M['ui.audit.from'])}><Input type="date" bind:value={from} max={to || undefined} /></FormGroup>
|
|
89
|
+
<FormGroup label={t(M['ui.audit.to'])}><Input type="date" bind:value={to} min={from || undefined} /></FormGroup>
|
|
90
|
+
<Button type="submit" disabled={loading}>{t(M['ui.audit.filter'])}</Button>
|
|
91
|
+
</Form>
|
|
92
|
+
{/if}
|
|
93
|
+
<RecordHistory
|
|
94
|
+
entries={visible}
|
|
95
|
+
{loading}
|
|
96
|
+
{error}
|
|
97
|
+
{resourceLabel}
|
|
98
|
+
{resourceHref}
|
|
99
|
+
{actionLabel}
|
|
100
|
+
{fieldLabel}
|
|
101
|
+
{formatValue}
|
|
102
|
+
/>
|
|
62
103
|
</section>
|
|
63
104
|
|
|
64
105
|
<style>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AuditHistoryEntry, AuditListFilter } from './types.js';
|
|
1
|
+
import type { AuditEntryLabel, AuditFieldLabel, AuditHistoryEntry, AuditListFilter, AuditResourceHref, AuditValueFormatter } from './types.js';
|
|
2
2
|
interface Props {
|
|
3
3
|
/** Authorized data only. For server paging use onfilter to reload the authorized page. */
|
|
4
4
|
entries: AuditHistoryEntry[];
|
|
@@ -8,6 +8,18 @@ interface Props {
|
|
|
8
8
|
error?: string | null;
|
|
9
9
|
/** Requests an authorized server page for the submitted filters instead of filtering locally. */
|
|
10
10
|
onfilter?: (filter: AuditListFilter) => void;
|
|
11
|
+
/** Shows the built-in person, record and date filters. */
|
|
12
|
+
showFilters?: boolean;
|
|
13
|
+
/** Resolves friendly resource text for each authorized entry. */
|
|
14
|
+
resourceLabel?: AuditEntryLabel;
|
|
15
|
+
/** Resolves an already-authorized local or HTTP(S) destination for each entry. */
|
|
16
|
+
resourceHref?: AuditResourceHref;
|
|
17
|
+
/** Resolves friendly action text for each authorized entry. */
|
|
18
|
+
actionLabel?: AuditEntryLabel;
|
|
19
|
+
/** Resolves friendly field text for each authorized entry change. */
|
|
20
|
+
fieldLabel?: AuditFieldLabel;
|
|
21
|
+
/** Formats before/after values as escaped text. */
|
|
22
|
+
formatValue?: AuditValueFormatter;
|
|
11
23
|
}
|
|
12
24
|
declare const AuditList: import("svelte").Component<Props, {}, "">;
|
|
13
25
|
type AuditList = ReturnType<typeof AuditList>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuditList.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/audit/AuditList.svelte.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"AuditList.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/audit/AuditList.svelte.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EACV,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,mBAAmB,EACpB,MAAM,YAAY,CAAC;AAGpB,UAAU,KAAK;IACb,0FAA0F;IAC1F,OAAO,EAAE,iBAAiB,EAAE,CAAC;IAC7B,sFAAsF;IACtF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,0DAA0D;IAC1D,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,iGAAiG;IACjG,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,IAAI,CAAC;IAC7C,0DAA0D;IAC1D,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,iEAAiE;IACjE,aAAa,CAAC,EAAE,eAAe,CAAC;IAChC,kFAAkF;IAClF,YAAY,CAAC,EAAE,iBAAiB,CAAC;IACjC,+DAA+D;IAC/D,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B,qEAAqE;IACrE,UAAU,CAAC,EAAE,eAAe,CAAC;IAC7B,mDAAmD;IACnD,WAAW,CAAC,EAAE,mBAAmB,CAAC;CACnC;AAuED,QAAA,MAAM,SAAS,2CAAwC,CAAC;AACxD,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC;AAC9C,eAAe,SAAS,CAAC"}
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { useI18n } from '@happyvertical/smrt-ui/i18n';
|
|
3
3
|
import { M } from '../../i18n/strings.audit.js';
|
|
4
|
-
import type {
|
|
4
|
+
import type {
|
|
5
|
+
AuditEntryLabel,
|
|
6
|
+
AuditFieldLabel,
|
|
7
|
+
AuditHistoryEntry,
|
|
8
|
+
AuditResourceHref,
|
|
9
|
+
AuditValueFormatter,
|
|
10
|
+
} from './types.js';
|
|
5
11
|
|
|
6
12
|
interface Props {
|
|
7
13
|
/** Authorized entries. This component never fetches or authorizes records. */
|
|
@@ -16,6 +22,16 @@ interface Props {
|
|
|
16
22
|
error?: string | null;
|
|
17
23
|
/** Overrides the translated accessible label for the history section. */
|
|
18
24
|
label?: string;
|
|
25
|
+
/** Resolves friendly resource text for each authorized entry. */
|
|
26
|
+
resourceLabel?: AuditEntryLabel;
|
|
27
|
+
/** Resolves an already-authorized local or HTTP(S) destination for each entry. */
|
|
28
|
+
resourceHref?: AuditResourceHref;
|
|
29
|
+
/** Resolves friendly action text for each authorized entry. */
|
|
30
|
+
actionLabel?: AuditEntryLabel;
|
|
31
|
+
/** Resolves friendly field text for each authorized entry change. */
|
|
32
|
+
fieldLabel?: AuditFieldLabel;
|
|
33
|
+
/** Formats before/after values as escaped text. */
|
|
34
|
+
formatValue?: AuditValueFormatter;
|
|
19
35
|
}
|
|
20
36
|
let {
|
|
21
37
|
entries,
|
|
@@ -24,6 +40,11 @@ let {
|
|
|
24
40
|
loading = false,
|
|
25
41
|
error = null,
|
|
26
42
|
label,
|
|
43
|
+
resourceLabel,
|
|
44
|
+
resourceHref,
|
|
45
|
+
actionLabel,
|
|
46
|
+
fieldLabel,
|
|
47
|
+
formatValue,
|
|
27
48
|
}: Props = $props();
|
|
28
49
|
const { locale, t } = useI18n();
|
|
29
50
|
const visible = $derived(
|
|
@@ -35,8 +56,87 @@ const visible = $derived(
|
|
|
35
56
|
)
|
|
36
57
|
.toSorted((a, b) => Date.parse(b.occurredAt) - Date.parse(a.occurredAt)),
|
|
37
58
|
);
|
|
38
|
-
function
|
|
39
|
-
|
|
59
|
+
function defaultDisplay(value: unknown): string {
|
|
60
|
+
if (typeof value === 'string') return value;
|
|
61
|
+
try {
|
|
62
|
+
return JSON.stringify(value) ?? '';
|
|
63
|
+
} catch {
|
|
64
|
+
try {
|
|
65
|
+
return String(value);
|
|
66
|
+
} catch {
|
|
67
|
+
return '';
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function entryLabel(
|
|
72
|
+
resolver: AuditEntryLabel | undefined,
|
|
73
|
+
entry: AuditHistoryEntry,
|
|
74
|
+
fallback: string,
|
|
75
|
+
): string {
|
|
76
|
+
if (!resolver) return fallback;
|
|
77
|
+
try {
|
|
78
|
+
const resolved = resolver(entry);
|
|
79
|
+
return typeof resolved === 'string' && resolved.trim()
|
|
80
|
+
? resolved
|
|
81
|
+
: fallback;
|
|
82
|
+
} catch {
|
|
83
|
+
return fallback;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function changedFieldLabel(field: string, entry: AuditHistoryEntry): string {
|
|
87
|
+
if (!fieldLabel) return field;
|
|
88
|
+
try {
|
|
89
|
+
const resolved = fieldLabel(field, entry);
|
|
90
|
+
return typeof resolved === 'string' && resolved.trim() ? resolved : field;
|
|
91
|
+
} catch {
|
|
92
|
+
return field;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function display(
|
|
96
|
+
value: unknown,
|
|
97
|
+
entry: AuditHistoryEntry,
|
|
98
|
+
field: string,
|
|
99
|
+
side: 'before' | 'after',
|
|
100
|
+
): string {
|
|
101
|
+
if (formatValue) {
|
|
102
|
+
try {
|
|
103
|
+
const resolved = formatValue(value, { entry, field, side });
|
|
104
|
+
if (typeof resolved === 'string') return resolved;
|
|
105
|
+
} catch {
|
|
106
|
+
// Presentation callbacks cannot make an authorized history list fail.
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return defaultDisplay(value);
|
|
110
|
+
}
|
|
111
|
+
function hasUrlControlCharacter(value: string): boolean {
|
|
112
|
+
return Array.from(value).some((character) => {
|
|
113
|
+
const codePoint = character.codePointAt(0) ?? 0;
|
|
114
|
+
return codePoint <= 0x1f || codePoint === 0x7f;
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
function safeResourceHref(entry: AuditHistoryEntry): string | null {
|
|
118
|
+
if (!resourceHref) return null;
|
|
119
|
+
let resolved: unknown;
|
|
120
|
+
try {
|
|
121
|
+
resolved = resourceHref(entry);
|
|
122
|
+
} catch {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
if (typeof resolved !== 'string') return null;
|
|
126
|
+
const href = resolved.trim();
|
|
127
|
+
if (
|
|
128
|
+
!href ||
|
|
129
|
+
href.startsWith('//') ||
|
|
130
|
+
href.includes('\\') ||
|
|
131
|
+
hasUrlControlCharacter(href)
|
|
132
|
+
)
|
|
133
|
+
return null;
|
|
134
|
+
try {
|
|
135
|
+
const url = new URL(href, 'https://smrt.invalid');
|
|
136
|
+
return url.protocol === 'http:' || url.protocol === 'https:' ? href : null;
|
|
137
|
+
} catch {
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
40
140
|
}
|
|
41
141
|
function date(value: string): string {
|
|
42
142
|
const parsed = new Date(value);
|
|
@@ -50,17 +150,27 @@ function date(value: string): string {
|
|
|
50
150
|
{#if error}<p role="alert">{error}</p>{/if}
|
|
51
151
|
{#if loading}<p role="status">{t(M['ui.audit.loading'])}</p>{/if}
|
|
52
152
|
{#if !loading && visible.length === 0}<p>{t(M['ui.audit.empty'])}</p>{/if}
|
|
53
|
-
<ol>
|
|
153
|
+
<ol role="list">
|
|
54
154
|
{#each visible as entry (entry.id)}
|
|
155
|
+
{@const resolvedResourceLabel = entryLabel(resourceLabel, entry, `${entry.resourceType} / ${entry.resourceId}`)}
|
|
156
|
+
{@const resolvedResourceHref = safeResourceHref(entry)}
|
|
55
157
|
<li>
|
|
56
|
-
<p
|
|
158
|
+
<p>
|
|
159
|
+
<strong>{entry.actorLabel ?? entry.profileId}</strong>
|
|
160
|
+
· {entryLabel(actionLabel, entry, entry.action)} ·
|
|
161
|
+
{#if resolvedResourceHref}<a href={resolvedResourceHref}>{resolvedResourceLabel}</a>{:else}{resolvedResourceLabel}{/if}
|
|
162
|
+
</p>
|
|
57
163
|
<time datetime={entry.occurredAt}>{date(entry.occurredAt)}</time>
|
|
58
164
|
{#if entry.onBehalfOfId}<p>{t(M['ui.audit.behalf'], { actor: entry.onBehalfOfId })}</p>{/if}
|
|
59
165
|
{#if entry.reason}<p>{t(M['ui.audit.reason'], { reason: entry.reason })}</p>{/if}
|
|
60
166
|
{#if entry.changes && Object.keys(entry.changes).length}
|
|
61
|
-
<ul>
|
|
167
|
+
<ul role="list">
|
|
62
168
|
{#each Object.entries(entry.changes) as [field, change] (field)}
|
|
63
|
-
<li>{t(M['ui.audit.change'], {
|
|
169
|
+
<li>{t(M['ui.audit.change'], {
|
|
170
|
+
field: changedFieldLabel(field, entry),
|
|
171
|
+
before: display(change.before, entry, field, 'before'),
|
|
172
|
+
after: display(change.after, entry, field, 'after'),
|
|
173
|
+
})}</li>
|
|
64
174
|
{/each}
|
|
65
175
|
</ul>
|
|
66
176
|
{/if}
|
|
@@ -70,7 +180,55 @@ function date(value: string): string {
|
|
|
70
180
|
</section>
|
|
71
181
|
|
|
72
182
|
<style>
|
|
73
|
-
.smrt-record-history ol {
|
|
74
|
-
|
|
75
|
-
|
|
183
|
+
.smrt-record-history > ol {
|
|
184
|
+
display: grid;
|
|
185
|
+
margin: 0;
|
|
186
|
+
padding: 0;
|
|
187
|
+
list-style: none;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.smrt-record-history > ol > li {
|
|
191
|
+
min-inline-size: 0;
|
|
192
|
+
padding-block: var(--smrt-spacing-3);
|
|
193
|
+
border-block-end: 1px solid var(--smrt-color-outline-variant);
|
|
194
|
+
overflow-wrap: anywhere;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
.smrt-record-history > ol > li:first-child { padding-block-start: 0; }
|
|
198
|
+
.smrt-record-history > ol > li:last-child {
|
|
199
|
+
padding-block-end: 0;
|
|
200
|
+
border-block-end: 0;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
.smrt-record-history p { margin-block: var(--smrt-spacing-1); }
|
|
204
|
+
.smrt-record-history time {
|
|
205
|
+
display: block;
|
|
206
|
+
color: var(--smrt-color-on-surface-variant);
|
|
207
|
+
font: var(--smrt-typography-label-medium-font);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
.smrt-record-history a {
|
|
211
|
+
color: var(--smrt-color-on-surface);
|
|
212
|
+
text-decoration-color: var(--smrt-color-primary);
|
|
213
|
+
text-decoration-thickness: .08em;
|
|
214
|
+
text-underline-offset: .18em;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
.smrt-record-history a:hover { text-decoration-thickness: .14em; }
|
|
218
|
+
.smrt-record-history a:focus-visible {
|
|
219
|
+
border-radius: var(--smrt-radius-extra-small, .25rem);
|
|
220
|
+
outline: 2px solid var(--smrt-color-primary);
|
|
221
|
+
outline-offset: 2px;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
.smrt-record-history ul {
|
|
225
|
+
display: grid;
|
|
226
|
+
gap: var(--smrt-spacing-1);
|
|
227
|
+
margin-block: var(--smrt-spacing-2) 0;
|
|
228
|
+
padding: var(--smrt-spacing-2) var(--smrt-spacing-3);
|
|
229
|
+
border-inline-start: 2px solid var(--smrt-color-outline);
|
|
230
|
+
border-radius: var(--smrt-radius-small, .375rem);
|
|
231
|
+
background: var(--smrt-color-surface-container-low);
|
|
232
|
+
list-style: none;
|
|
233
|
+
}
|
|
76
234
|
</style>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AuditHistoryEntry } from './types.js';
|
|
1
|
+
import type { AuditEntryLabel, AuditFieldLabel, AuditHistoryEntry, AuditResourceHref, AuditValueFormatter } from './types.js';
|
|
2
2
|
interface Props {
|
|
3
3
|
/** Authorized entries. This component never fetches or authorizes records. */
|
|
4
4
|
entries: AuditHistoryEntry[];
|
|
@@ -12,6 +12,16 @@ interface Props {
|
|
|
12
12
|
error?: string | null;
|
|
13
13
|
/** Overrides the translated accessible label for the history section. */
|
|
14
14
|
label?: string;
|
|
15
|
+
/** Resolves friendly resource text for each authorized entry. */
|
|
16
|
+
resourceLabel?: AuditEntryLabel;
|
|
17
|
+
/** Resolves an already-authorized local or HTTP(S) destination for each entry. */
|
|
18
|
+
resourceHref?: AuditResourceHref;
|
|
19
|
+
/** Resolves friendly action text for each authorized entry. */
|
|
20
|
+
actionLabel?: AuditEntryLabel;
|
|
21
|
+
/** Resolves friendly field text for each authorized entry change. */
|
|
22
|
+
fieldLabel?: AuditFieldLabel;
|
|
23
|
+
/** Formats before/after values as escaped text. */
|
|
24
|
+
formatValue?: AuditValueFormatter;
|
|
15
25
|
}
|
|
16
26
|
declare const RecordHistory: import("svelte").Component<Props, {}, "">;
|
|
17
27
|
type RecordHistory = ReturnType<typeof RecordHistory>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RecordHistory.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/audit/RecordHistory.svelte.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"RecordHistory.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/audit/RecordHistory.svelte.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,mBAAmB,EACpB,MAAM,YAAY,CAAC;AAGpB,UAAU,KAAK;IACb,8EAA8E;IAC9E,OAAO,EAAE,iBAAiB,EAAE,CAAC;IAC7B,wFAAwF;IACxF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gFAAgF;IAChF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gFAAgF;IAChF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,oDAAoD;IACpD,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,yEAAyE;IACzE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iEAAiE;IACjE,aAAa,CAAC,EAAE,eAAe,CAAC;IAChC,kFAAkF;IAClF,YAAY,CAAC,EAAE,iBAAiB,CAAC;IACjC,+DAA+D;IAC/D,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B,qEAAqE;IACrE,UAAU,CAAC,EAAE,eAAe,CAAC;IAC7B,mDAAmD;IACnD,WAAW,CAAC,EAAE,mBAAmB,CAAC;CACnC;AA4JD,QAAA,MAAM,aAAa,2CAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { default as AuditList } from './AuditList.svelte';
|
|
2
2
|
export { default as RecordHistory } from './RecordHistory.svelte';
|
|
3
|
-
export type { AuditHistoryEntry, AuditListFilter } from './types.js';
|
|
3
|
+
export type { AuditEntryLabel, AuditFieldLabel, AuditHistoryEntry, AuditListFilter, AuditResourceHref, AuditValueFormatContext, AuditValueFormatter, } from './types.js';
|
|
4
4
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/audit/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAClE,YAAY,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/audit/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAClE,YAAY,EACV,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,uBAAuB,EACvB,mBAAmB,GACpB,MAAM,YAAY,CAAC"}
|
|
@@ -20,4 +20,22 @@ export interface AuditListFilter {
|
|
|
20
20
|
from: string;
|
|
21
21
|
to: string;
|
|
22
22
|
}
|
|
23
|
+
/** Resolves presentation text for one already-authorized audit entry. */
|
|
24
|
+
export type AuditEntryLabel = (entry: AuditHistoryEntry) => string;
|
|
25
|
+
/**
|
|
26
|
+
* Resolves an already-authorized destination for an audit entry.
|
|
27
|
+
*
|
|
28
|
+
* The component accepts local paths and explicit HTTP(S) URLs only. Consumers
|
|
29
|
+
* must still authorize the referenced resource before exposing its href.
|
|
30
|
+
*/
|
|
31
|
+
export type AuditResourceHref = (entry: AuditHistoryEntry) => string | null | undefined;
|
|
32
|
+
/** Resolves a presentation label for one changed field. */
|
|
33
|
+
export type AuditFieldLabel = (field: string, entry: AuditHistoryEntry) => string;
|
|
34
|
+
export interface AuditValueFormatContext {
|
|
35
|
+
entry: AuditHistoryEntry;
|
|
36
|
+
field: string;
|
|
37
|
+
side: 'before' | 'after';
|
|
38
|
+
}
|
|
39
|
+
/** Formats an audit value as text. Formatter output is never rendered as HTML. */
|
|
40
|
+
export type AuditValueFormatter = (value: unknown, context: AuditValueFormatContext) => string;
|
|
23
41
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/audit/types.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CAC/D;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;CACZ"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/audit/types.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CAC/D;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,yEAAyE;AACzE,MAAM,MAAM,eAAe,GAAG,CAAC,KAAK,EAAE,iBAAiB,KAAK,MAAM,CAAC;AAEnE;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,GAAG,CAC9B,KAAK,EAAE,iBAAiB,KACrB,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;AAE/B,2DAA2D;AAC3D,MAAM,MAAM,eAAe,GAAG,CAC5B,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,iBAAiB,KACrB,MAAM,CAAC;AAEZ,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,iBAAiB,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC;CAC1B;AAED,kFAAkF;AAClF,MAAM,MAAM,mBAAmB,GAAG,CAChC,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,uBAAuB,KAC7B,MAAM,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@happyvertical/smrt-svelte",
|
|
3
|
-
"version": "0.55.
|
|
3
|
+
"version": "0.55.6",
|
|
4
4
|
"smrtJsdoc": "strict",
|
|
5
5
|
"description": "Svelte 5 components for SMRT user management - auth, users, tenants, roles, permissions, groups",
|
|
6
6
|
"type": "module",
|
|
@@ -148,12 +148,12 @@
|
|
|
148
148
|
"access": "public"
|
|
149
149
|
},
|
|
150
150
|
"dependencies": {
|
|
151
|
-
"@happyvertical/logger": "^0.102.
|
|
152
|
-
"@happyvertical/smrt-languages": "0.55.
|
|
153
|
-
"@happyvertical/smrt-mcp-apps": "0.55.
|
|
154
|
-
"@happyvertical/smrt-types": "0.55.
|
|
155
|
-
"@happyvertical/smrt-ui": "0.55.
|
|
156
|
-
"@happyvertical/smrt-web": "0.55.
|
|
151
|
+
"@happyvertical/logger": "^0.102.4",
|
|
152
|
+
"@happyvertical/smrt-languages": "0.55.6",
|
|
153
|
+
"@happyvertical/smrt-mcp-apps": "0.55.6",
|
|
154
|
+
"@happyvertical/smrt-types": "0.55.6",
|
|
155
|
+
"@happyvertical/smrt-ui": "0.55.6",
|
|
156
|
+
"@happyvertical/smrt-web": "0.55.6",
|
|
157
157
|
"@tanstack/db": "^0.6.14",
|
|
158
158
|
"@tanstack/svelte-db": "^0.1.91",
|
|
159
159
|
"esm-env": "^1.2.2"
|
|
@@ -188,14 +188,14 @@
|
|
|
188
188
|
}
|
|
189
189
|
},
|
|
190
190
|
"devDependencies": {
|
|
191
|
-
"@happyvertical/smrt-agents": "0.55.
|
|
192
|
-
"@happyvertical/smrt-chat": "0.55.
|
|
193
|
-
"@happyvertical/smrt-content": "0.55.
|
|
194
|
-
"@happyvertical/smrt-core": "0.55.
|
|
195
|
-
"@happyvertical/smrt-reports": "0.55.
|
|
196
|
-
"@happyvertical/smrt-scanner": "0.55.
|
|
197
|
-
"@happyvertical/smrt-tenancy": "0.55.
|
|
198
|
-
"@happyvertical/smrt-users": "0.55.
|
|
191
|
+
"@happyvertical/smrt-agents": "0.55.6",
|
|
192
|
+
"@happyvertical/smrt-chat": "0.55.6",
|
|
193
|
+
"@happyvertical/smrt-content": "0.55.6",
|
|
194
|
+
"@happyvertical/smrt-core": "0.55.6",
|
|
195
|
+
"@happyvertical/smrt-reports": "0.55.6",
|
|
196
|
+
"@happyvertical/smrt-scanner": "0.55.6",
|
|
197
|
+
"@happyvertical/smrt-tenancy": "0.55.6",
|
|
198
|
+
"@happyvertical/smrt-users": "0.55.6",
|
|
199
199
|
"@sveltejs/package": "^2.5.8",
|
|
200
200
|
"@sveltejs/vite-plugin-svelte": "^7.3.0",
|
|
201
201
|
"@testing-library/jest-dom": "^7.0.1",
|