@happyvertical/smrt-fields 0.40.59 → 0.40.61
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/AGENTS.md +58 -12
- package/README.md +90 -2
- package/dist/__smrt-register__.d.ts +2 -0
- package/dist/__smrt-register__.d.ts.map +1 -0
- package/dist/cache.d.ts +18 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/collections/FieldPolicyCollection.d.ts +95 -0
- package/dist/collections/FieldPolicyCollection.d.ts.map +1 -0
- package/dist/field-definitions.d.ts +77 -0
- package/dist/field-definitions.d.ts.map +1 -0
- package/dist/field-policy-resolver.d.ts +46 -0
- package/dist/field-policy-resolver.d.ts.map +1 -0
- package/dist/index.d.ts +9 -532
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +752 -55
- package/dist/index.js.map +1 -1
- package/dist/manifest.json +45 -3
- package/dist/models/FieldPolicy.d.ts +163 -0
- package/dist/models/FieldPolicy.d.ts.map +1 -0
- package/dist/permissions.d.ts +9 -0
- package/dist/permissions.d.ts.map +1 -0
- package/dist/playground.d.ts +2 -0
- package/dist/playground.d.ts.map +1 -0
- package/dist/playground.js +39 -0
- package/dist/playground.js.map +1 -0
- package/dist/settings-catalog.d.ts +73 -0
- package/dist/settings-catalog.d.ts.map +1 -0
- package/dist/smrt-knowledge.json +50 -7
- package/dist/svelte/__tests__/FieldPolicyControlPanel.test.js +223 -0
- package/dist/svelte/__tests__/FieldPolicyGear.test.js +503 -0
- package/dist/svelte/__tests__/FormHelp.test.js +138 -0
- package/dist/svelte/__tests__/ModeUX.test.js +109 -0
- package/dist/svelte/__tests__/ObjectForm.test.js +556 -0
- package/dist/svelte/__tests__/ObjectFormGeneratedApi.integration.test.js +436 -0
- package/dist/svelte/__tests__/PolicyField.test.js +373 -0
- package/dist/svelte/__tests__/fixtures/AdvancedFieldsFixture.svelte +30 -0
- package/dist/svelte/__tests__/fixtures/AdvancedFieldsFixture.svelte.d.ts +9 -0
- package/dist/svelte/__tests__/fixtures/AdvancedFieldsFixture.svelte.d.ts.map +1 -0
- package/dist/svelte/__tests__/fixtures/DomPrefillFixture.svelte +33 -0
- package/dist/svelte/__tests__/fixtures/DomPrefillFixture.svelte.d.ts +10 -0
- package/dist/svelte/__tests__/fixtures/DomPrefillFixture.svelte.d.ts.map +1 -0
- package/dist/svelte/__tests__/fixtures/FormHelpFixture.svelte +19 -0
- package/dist/svelte/__tests__/fixtures/FormHelpFixture.svelte.d.ts +10 -0
- package/dist/svelte/__tests__/fixtures/FormHelpFixture.svelte.d.ts.map +1 -0
- package/dist/svelte/__tests__/fixtures/GeneratedApiGearFixture.svelte +18 -0
- package/dist/svelte/__tests__/fixtures/GeneratedApiGearFixture.svelte.d.ts +11 -0
- package/dist/svelte/__tests__/fixtures/GeneratedApiGearFixture.svelte.d.ts.map +1 -0
- package/dist/svelte/__tests__/fixtures/GracefulDegradeFixture.svelte +11 -0
- package/dist/svelte/__tests__/fixtures/GracefulDegradeFixture.svelte.d.ts +19 -0
- package/dist/svelte/__tests__/fixtures/GracefulDegradeFixture.svelte.d.ts.map +1 -0
- package/dist/svelte/__tests__/fixtures/ModeSwitchFixture.svelte +18 -0
- package/dist/svelte/__tests__/fixtures/ModeSwitchFixture.svelte.d.ts +8 -0
- package/dist/svelte/__tests__/fixtures/ModeSwitchFixture.svelte.d.ts.map +1 -0
- package/dist/svelte/__tests__/fixtures/NoIdFixture.svelte +24 -0
- package/dist/svelte/__tests__/fixtures/NoIdFixture.svelte.d.ts +13 -0
- package/dist/svelte/__tests__/fixtures/NoIdFixture.svelte.d.ts.map +1 -0
- package/dist/svelte/__tests__/fixtures/ObjectFormActionsFixture.svelte +20 -0
- package/dist/svelte/__tests__/fixtures/ObjectFormActionsFixture.svelte.d.ts +11 -0
- package/dist/svelte/__tests__/fixtures/ObjectFormActionsFixture.svelte.d.ts.map +1 -0
- package/dist/svelte/__tests__/fixtures/ObjectFormFixture.svelte +17 -0
- package/dist/svelte/__tests__/fixtures/ObjectFormFixture.svelte.d.ts +10 -0
- package/dist/svelte/__tests__/fixtures/ObjectFormFixture.svelte.d.ts.map +1 -0
- package/dist/svelte/__tests__/fixtures/ObjectFormRegistryFixture.svelte +25 -0
- package/dist/svelte/__tests__/fixtures/ObjectFormRegistryFixture.svelte.d.ts +10 -0
- package/dist/svelte/__tests__/fixtures/ObjectFormRegistryFixture.svelte.d.ts.map +1 -0
- package/dist/svelte/__tests__/fixtures/ObjectFormSnippetFixture.svelte +34 -0
- package/dist/svelte/__tests__/fixtures/ObjectFormSnippetFixture.svelte.d.ts +10 -0
- package/dist/svelte/__tests__/fixtures/ObjectFormSnippetFixture.svelte.d.ts.map +1 -0
- package/dist/svelte/__tests__/fixtures/ObjectFormSourceFixture.svelte +29 -0
- package/dist/svelte/__tests__/fixtures/ObjectFormSourceFixture.svelte.d.ts +11 -0
- package/dist/svelte/__tests__/fixtures/ObjectFormSourceFixture.svelte.d.ts.map +1 -0
- package/dist/svelte/__tests__/fixtures/ObjectFormSourceSnippetFixture.svelte +33 -0
- package/dist/svelte/__tests__/fixtures/ObjectFormSourceSnippetFixture.svelte.d.ts +9 -0
- package/dist/svelte/__tests__/fixtures/ObjectFormSourceSnippetFixture.svelte.d.ts.map +1 -0
- package/dist/svelte/__tests__/fixtures/PolicyDataTableFixture.svelte +40 -0
- package/dist/svelte/__tests__/fixtures/PolicyDataTableFixture.svelte.d.ts +8 -0
- package/dist/svelte/__tests__/fixtures/PolicyDataTableFixture.svelte.d.ts.map +1 -0
- package/dist/svelte/__tests__/fixtures/PrefillFixture.svelte +26 -0
- package/dist/svelte/__tests__/fixtures/PrefillFixture.svelte.d.ts +13 -0
- package/dist/svelte/__tests__/fixtures/PrefillFixture.svelte.d.ts.map +1 -0
- package/dist/svelte/__tests__/fixtures/ProviderFieldFixture.svelte +39 -0
- package/dist/svelte/__tests__/fixtures/ProviderFieldFixture.svelte.d.ts +17 -0
- package/dist/svelte/__tests__/fixtures/ProviderFieldFixture.svelte.d.ts.map +1 -0
- package/dist/svelte/__tests__/fixtures/RegistryInput.svelte +15 -0
- package/dist/svelte/__tests__/fixtures/RegistryInput.svelte.d.ts +5 -0
- package/dist/svelte/__tests__/fixtures/RegistryInput.svelte.d.ts.map +1 -0
- package/dist/svelte/__tests__/fixtures/RevealPrefillFixture.svelte +29 -0
- package/dist/svelte/__tests__/fixtures/RevealPrefillFixture.svelte.d.ts +14 -0
- package/dist/svelte/__tests__/fixtures/RevealPrefillFixture.svelte.d.ts.map +1 -0
- package/dist/svelte/__tests__/fixtures/SettingsCatalogStub.svelte +24 -0
- package/dist/svelte/__tests__/fixtures/SettingsCatalogStub.svelte.d.ts +14 -0
- package/dist/svelte/__tests__/fixtures/SettingsCatalogStub.svelte.d.ts.map +1 -0
- package/dist/svelte/__tests__/fixtures/SnippetFixture.svelte +28 -0
- package/dist/svelte/__tests__/fixtures/SnippetFixture.svelte.d.ts +13 -0
- package/dist/svelte/__tests__/fixtures/SnippetFixture.svelte.d.ts.map +1 -0
- package/dist/svelte/__tests__/fixtures/ToggleModeButton.svelte +14 -0
- package/dist/svelte/__tests__/fixtures/ToggleModeButton.svelte.d.ts +19 -0
- package/dist/svelte/__tests__/fixtures/ToggleModeButton.svelte.d.ts.map +1 -0
- package/dist/svelte/__tests__/fixtures/TooltipFixture.svelte +25 -0
- package/dist/svelte/__tests__/fixtures/TooltipFixture.svelte.d.ts +14 -0
- package/dist/svelte/__tests__/fixtures/TooltipFixture.svelte.d.ts.map +1 -0
- package/dist/svelte/__tests__/settings-catalog.test.js +161 -0
- package/dist/svelte/components/AdvancedFields.svelte +49 -0
- package/dist/svelte/components/AdvancedFields.svelte.d.ts +17 -0
- package/dist/svelte/components/AdvancedFields.svelte.d.ts.map +1 -0
- package/dist/svelte/components/FieldInput.svelte +159 -0
- package/dist/svelte/components/FieldInput.svelte.d.ts +5 -0
- package/dist/svelte/components/FieldInput.svelte.d.ts.map +1 -0
- package/dist/svelte/components/FieldPolicyControlPanel.svelte +261 -0
- package/dist/svelte/components/FieldPolicyControlPanel.svelte.d.ts +26 -0
- package/dist/svelte/components/FieldPolicyControlPanel.svelte.d.ts.map +1 -0
- package/dist/svelte/components/FieldPolicyEditor.svelte +417 -0
- package/dist/svelte/components/FieldPolicyEditor.svelte.d.ts +18 -0
- package/dist/svelte/components/FieldPolicyEditor.svelte.d.ts.map +1 -0
- package/dist/svelte/components/FieldPolicyGearButton.svelte +17 -0
- package/dist/svelte/components/FieldPolicyGearButton.svelte.d.ts +8 -0
- package/dist/svelte/components/FieldPolicyGearButton.svelte.d.ts.map +1 -0
- package/dist/svelte/components/FieldPolicyGearProvider.svelte +135 -0
- package/dist/svelte/components/FieldPolicyGearProvider.svelte.d.ts +17 -0
- package/dist/svelte/components/FieldPolicyGearProvider.svelte.d.ts.map +1 -0
- package/dist/svelte/components/FieldPolicyProvider.svelte +89 -0
- package/dist/svelte/components/FieldPolicyProvider.svelte.d.ts +35 -0
- package/dist/svelte/components/FieldPolicyProvider.svelte.d.ts.map +1 -0
- package/dist/svelte/components/FormHelp.svelte +157 -0
- package/dist/svelte/components/FormHelp.svelte.d.ts +15 -0
- package/dist/svelte/components/FormHelp.svelte.d.ts.map +1 -0
- package/dist/svelte/components/ModeSwitch.svelte +47 -0
- package/dist/svelte/components/ModeSwitch.svelte.d.ts +10 -0
- package/dist/svelte/components/ModeSwitch.svelte.d.ts.map +1 -0
- package/dist/svelte/components/ObjectForm.svelte +351 -0
- package/dist/svelte/components/ObjectForm.svelte.d.ts +40 -0
- package/dist/svelte/components/ObjectForm.svelte.d.ts.map +1 -0
- package/dist/svelte/components/ObjectFormSourceProvider.svelte +18 -0
- package/dist/svelte/components/ObjectFormSourceProvider.svelte.d.ts +11 -0
- package/dist/svelte/components/ObjectFormSourceProvider.svelte.d.ts.map +1 -0
- package/dist/svelte/components/PolicyField.svelte +338 -0
- package/dist/svelte/components/PolicyField.svelte.d.ts +80 -0
- package/dist/svelte/components/PolicyField.svelte.d.ts.map +1 -0
- package/dist/svelte/context.svelte.d.ts +54 -0
- package/dist/svelte/context.svelte.d.ts.map +1 -0
- package/dist/svelte/context.svelte.js +55 -0
- package/dist/svelte/data-table.d.ts +17 -0
- package/dist/svelte/data-table.d.ts.map +1 -0
- package/dist/svelte/data-table.js +19 -0
- package/dist/svelte/field-policy-editor.d.ts +81 -0
- package/dist/svelte/field-policy-editor.d.ts.map +1 -0
- package/dist/svelte/field-policy-editor.js +120 -0
- package/dist/svelte/gear-context.svelte.d.ts +14 -0
- package/dist/svelte/gear-context.svelte.d.ts.map +1 -0
- package/dist/svelte/gear-context.svelte.js +15 -0
- package/dist/svelte/index.d.ts +58 -0
- package/dist/svelte/index.d.ts.map +1 -0
- package/dist/svelte/index.js +38 -0
- package/dist/svelte/input-registry.d.ts +21 -0
- package/dist/svelte/input-registry.d.ts.map +1 -0
- package/dist/svelte/input-registry.js +26 -0
- package/dist/svelte/object-form-source-context.svelte.d.ts +4 -0
- package/dist/svelte/object-form-source-context.svelte.d.ts.map +1 -0
- package/dist/svelte/object-form-source-context.svelte.js +8 -0
- package/dist/svelte/object-form-source.svelte.d.ts +18 -0
- package/dist/svelte/object-form-source.svelte.d.ts.map +1 -0
- package/dist/svelte/object-form-source.svelte.js +99 -0
- package/dist/svelte/object-form.d.ts +6 -0
- package/dist/svelte/object-form.d.ts.map +1 -0
- package/dist/svelte/object-form.js +38 -0
- package/dist/svelte/playground/FieldPolicyFormPreview.svelte +212 -0
- package/dist/svelte/playground/FieldPolicyFormPreview.svelte.d.ts +4 -0
- package/dist/svelte/playground/FieldPolicyFormPreview.svelte.d.ts.map +1 -0
- package/dist/svelte/playground/ObjectFormPreview.svelte +129 -0
- package/dist/svelte/playground/ObjectFormPreview.svelte.d.ts +4 -0
- package/dist/svelte/playground/ObjectFormPreview.svelte.d.ts.map +1 -0
- package/dist/svelte/playground.d.ts +20 -0
- package/dist/svelte/playground.d.ts.map +1 -0
- package/dist/svelte/playground.js +38 -0
- package/dist/svelte/settings-catalog.d.ts +54 -0
- package/dist/svelte/settings-catalog.d.ts.map +1 -0
- package/dist/svelte/settings-catalog.js +116 -0
- package/dist/svelte/types.d.ts +101 -0
- package/dist/svelte/types.d.ts.map +1 -0
- package/dist/svelte/types.js +4 -0
- package/dist/types.d.ts +276 -203
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js.map +1 -1
- package/package.json +33 -8
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* Main-content tenant-admin destination for field defaults. The host supplies
|
|
4
|
+
* the SettingsCatalog shell and generated-client adapter, keeping this package
|
|
5
|
+
* independent of both smrt-svelte and smrt-web.
|
|
6
|
+
*/
|
|
7
|
+
import { Button } from '@happyvertical/smrt-ui/ui';
|
|
8
|
+
import type { Component, Snippet } from 'svelte';
|
|
9
|
+
import type {
|
|
10
|
+
FieldPolicyDetailItem,
|
|
11
|
+
FieldPolicySettingsCatalogData,
|
|
12
|
+
FieldPolicySettingsCatalogPage,
|
|
13
|
+
} from '../../settings-catalog.js';
|
|
14
|
+
import type {
|
|
15
|
+
FieldPolicyAuditSnapshot,
|
|
16
|
+
FieldPolicyEditorState,
|
|
17
|
+
} from '../../types.js';
|
|
18
|
+
import {
|
|
19
|
+
editorStateErrorMessage,
|
|
20
|
+
isFieldPolicyEditorState,
|
|
21
|
+
} from '../field-policy-editor.js';
|
|
22
|
+
import {
|
|
23
|
+
auditObjectRefs,
|
|
24
|
+
decorateCatalogPage,
|
|
25
|
+
type FieldPolicyControlPanelAdapter,
|
|
26
|
+
type FieldPolicyLayerCell,
|
|
27
|
+
fieldPolicyCatalogPreservedParams,
|
|
28
|
+
fieldPolicyRollup,
|
|
29
|
+
orgRowIdsForObject,
|
|
30
|
+
prunableDriftRows,
|
|
31
|
+
} from '../settings-catalog.js';
|
|
32
|
+
import FieldPolicyEditor from './FieldPolicyEditor.svelte';
|
|
33
|
+
|
|
34
|
+
export interface FieldPolicyCatalogComponentProps {
|
|
35
|
+
page: FieldPolicySettingsCatalogPage;
|
|
36
|
+
baseUrl: string;
|
|
37
|
+
detail: Snippet<[{ item: FieldPolicyDetailItem }]>;
|
|
38
|
+
preservedParams?: Record<string, string>;
|
|
39
|
+
searchPlaceholder?: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface FieldPolicyControlPanelProps {
|
|
43
|
+
data: FieldPolicySettingsCatalogData;
|
|
44
|
+
adapter: FieldPolicyControlPanelAdapter;
|
|
45
|
+
catalog: Component<FieldPolicyCatalogComponentProps>;
|
|
46
|
+
baseUrl: string;
|
|
47
|
+
permissions?: readonly string[];
|
|
48
|
+
heading?: string;
|
|
49
|
+
onchanged?: () => void;
|
|
50
|
+
confirmAction?: (message: string) => boolean | Promise<boolean>;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
let {
|
|
54
|
+
data,
|
|
55
|
+
adapter,
|
|
56
|
+
catalog,
|
|
57
|
+
baseUrl,
|
|
58
|
+
permissions,
|
|
59
|
+
heading = 'Field settings',
|
|
60
|
+
onchanged,
|
|
61
|
+
confirmAction,
|
|
62
|
+
}: FieldPolicyControlPanelProps = $props();
|
|
63
|
+
|
|
64
|
+
// Before client effects run (including SSR), render the server snapshot.
|
|
65
|
+
// Later mutations replace `audit`; prop changes continue to resync it below.
|
|
66
|
+
let audit = $state<FieldPolicyAuditSnapshot | null>(null);
|
|
67
|
+
let editorState = $state<FieldPolicyEditorState | null>(null);
|
|
68
|
+
let editorOpen = $state(false);
|
|
69
|
+
let loadingEditor = $state(false);
|
|
70
|
+
let busy = $state(false);
|
|
71
|
+
let error = $state<string | null>(null);
|
|
72
|
+
let generation = 0;
|
|
73
|
+
|
|
74
|
+
const Catalog = $derived(catalog);
|
|
75
|
+
const visibleAudit = $derived(audit ?? data.audit);
|
|
76
|
+
const canManage = $derived(
|
|
77
|
+
visibleAudit.caller.canManageOrg &&
|
|
78
|
+
(permissions === undefined || permissions.includes('fields.policy.manage')),
|
|
79
|
+
);
|
|
80
|
+
const selected = $derived(data.page.selected);
|
|
81
|
+
const decoratedPage = $derived(decorateCatalogPage(data.page, visibleAudit));
|
|
82
|
+
const preservedParams = $derived(fieldPolicyCatalogPreservedParams(data));
|
|
83
|
+
|
|
84
|
+
$effect(() => {
|
|
85
|
+
data;
|
|
86
|
+
audit = data.audit;
|
|
87
|
+
editorState = null;
|
|
88
|
+
editorOpen = false;
|
|
89
|
+
error = null;
|
|
90
|
+
void loadEditor();
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
async function loadEditor(): Promise<void> {
|
|
94
|
+
if (!selected || !canManage) return;
|
|
95
|
+
const token = ++generation;
|
|
96
|
+
loadingEditor = true;
|
|
97
|
+
try {
|
|
98
|
+
const result = await adapter.load({ objectRef: selected.objectRef });
|
|
99
|
+
if (token !== generation) return;
|
|
100
|
+
if (isFieldPolicyEditorState(result, selected.objectRef)) {
|
|
101
|
+
editorState = result;
|
|
102
|
+
} else {
|
|
103
|
+
error = editorStateErrorMessage(result);
|
|
104
|
+
}
|
|
105
|
+
} catch (cause) {
|
|
106
|
+
if (token === generation)
|
|
107
|
+
error =
|
|
108
|
+
cause instanceof Error
|
|
109
|
+
? cause.message
|
|
110
|
+
: 'Unable to load field settings.';
|
|
111
|
+
} finally {
|
|
112
|
+
if (token === generation) loadingEditor = false;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
async function refreshAudit(): Promise<boolean> {
|
|
117
|
+
const refs = auditObjectRefs(data.page);
|
|
118
|
+
try {
|
|
119
|
+
audit = await adapter.loadAudit({ ...refs, includeDrift: true });
|
|
120
|
+
return true;
|
|
121
|
+
} catch (cause) {
|
|
122
|
+
error =
|
|
123
|
+
cause instanceof Error
|
|
124
|
+
? cause.message
|
|
125
|
+
: 'Unable to refresh field settings.';
|
|
126
|
+
return false;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
async function confirm(message: string): Promise<boolean> {
|
|
131
|
+
if (confirmAction) return await confirmAction(message);
|
|
132
|
+
return typeof window !== 'undefined' && window.confirm(message);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
async function resetOrganization(): Promise<void> {
|
|
136
|
+
if (!selected || busy) return;
|
|
137
|
+
const ids = orgRowIdsForObject(visibleAudit, selected.objectRef);
|
|
138
|
+
if (!ids.length) return;
|
|
139
|
+
if (
|
|
140
|
+
!(await confirm(
|
|
141
|
+
'Reset every organization override for this object? This cannot be undone.',
|
|
142
|
+
))
|
|
143
|
+
)
|
|
144
|
+
return;
|
|
145
|
+
busy = true;
|
|
146
|
+
error = null;
|
|
147
|
+
let changed = false;
|
|
148
|
+
try {
|
|
149
|
+
for (const id of ids) {
|
|
150
|
+
await adapter.delete({ id });
|
|
151
|
+
changed = true;
|
|
152
|
+
}
|
|
153
|
+
} catch (cause) {
|
|
154
|
+
error =
|
|
155
|
+
cause instanceof Error
|
|
156
|
+
? cause.message
|
|
157
|
+
: 'Unable to reset organization overrides.';
|
|
158
|
+
} finally {
|
|
159
|
+
const refreshed = await refreshAudit();
|
|
160
|
+
await loadEditor();
|
|
161
|
+
if (changed && refreshed) onchanged?.();
|
|
162
|
+
busy = false;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
async function prune(id: string): Promise<void> {
|
|
167
|
+
if (busy) return;
|
|
168
|
+
if (!(await confirm('Prune this stale policy row? This cannot be undone.')))
|
|
169
|
+
return;
|
|
170
|
+
busy = true;
|
|
171
|
+
error = null;
|
|
172
|
+
try {
|
|
173
|
+
await adapter.delete({ id });
|
|
174
|
+
if (await refreshAudit()) onchanged?.();
|
|
175
|
+
} catch (cause) {
|
|
176
|
+
error =
|
|
177
|
+
cause instanceof Error ? cause.message : 'Unable to prune stale policy.';
|
|
178
|
+
} finally {
|
|
179
|
+
busy = false;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
async function editorMutated(): Promise<void> {
|
|
184
|
+
if (await refreshAudit()) {
|
|
185
|
+
await loadEditor();
|
|
186
|
+
onchanged?.();
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function valueText(cell: FieldPolicyLayerCell): string {
|
|
191
|
+
if (!cell.hasDefault) return 'No default';
|
|
192
|
+
try {
|
|
193
|
+
return JSON.stringify(cell.defaultValue) ?? 'undefined';
|
|
194
|
+
} catch {
|
|
195
|
+
return String(cell.defaultValue);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
</script>
|
|
199
|
+
|
|
200
|
+
{#if canManage}
|
|
201
|
+
<section class="field-policy-control-panel" aria-label={heading}>
|
|
202
|
+
<header>
|
|
203
|
+
<h1>{heading}</h1>
|
|
204
|
+
<p>Manage inherited defaults, visibility, help, labels, order, and locks for every registered field.</p>
|
|
205
|
+
</header>
|
|
206
|
+
{#if error}<p class="field-policy-control-panel__error" role="alert">{error}</p>{/if}
|
|
207
|
+
<Catalog page={decoratedPage} {baseUrl} {preservedParams} searchPlaceholder="Search fields">
|
|
208
|
+
{#snippet detail({ item }: { item: FieldPolicyDetailItem })}
|
|
209
|
+
{@const rollup = fieldPolicyRollup(visibleAudit, item.objectRef, item.fieldName)}
|
|
210
|
+
<article class="field-policy-control-panel__detail">
|
|
211
|
+
<h2>{rollup.resolved?.label ?? item.label}</h2>
|
|
212
|
+
<p>{rollup.resolved?.help ?? item.description ?? 'No help text.'}</p>
|
|
213
|
+
<dl class="field-policy-control-panel__layers">
|
|
214
|
+
<div><dt>Code {rollup.code.contributed ? 'override' : 'inherited'}</dt><dd><code>{valueText(rollup.code)}</code> · {rollup.code.visibility}{rollup.code.locked ? ' · locked' : ''}</dd></div>
|
|
215
|
+
<div><dt>App {rollup.app.contributed ? 'override' : 'inherited'}</dt><dd><code>{valueText(rollup.app)}</code> · {rollup.app.visibility}{rollup.app.locked ? ' · locked' : ''}</dd></div>
|
|
216
|
+
<div><dt>Organization {rollup.org.contributed ? 'override' : 'inherited'}</dt><dd><code>{valueText(rollup.org)}</code> · {rollup.org.visibility}{rollup.org.locked ? ' · locked' : ''}</dd></div>
|
|
217
|
+
<div><dt>Users</dt><dd>{rollup.userCount} personal override{rollup.userCount === 1 ? '' : 's'}</dd></div>
|
|
218
|
+
</dl>
|
|
219
|
+
{#if rollup.orgRow}<p>Organization row last changed {rollup.orgRow.updatedAt ?? 'unknown'}{rollup.orgRow.updatedBy ? ` by ${rollup.orgRow.updatedBy}` : ''}.</p>{/if}
|
|
220
|
+
{#if rollup.appRow}<p>App row is read-only{rollup.appRow.updatedBy ? ` (last changed by ${rollup.appRow.updatedBy})` : ''}.</p>{/if}
|
|
221
|
+
<div class="field-policy-control-panel__actions">
|
|
222
|
+
<Button type="button" disabled={busy || loadingEditor || !editorState} onclick={() => editorOpen = true}>Edit settings</Button>
|
|
223
|
+
<Button type="button" variant="ghost" disabled={busy || orgRowIdsForObject(visibleAudit, item.objectRef).length === 0} onclick={resetOrganization}>Reset all organization overrides for this object</Button>
|
|
224
|
+
</div>
|
|
225
|
+
</article>
|
|
226
|
+
{/snippet}
|
|
227
|
+
</Catalog>
|
|
228
|
+
{#if editorOpen && editorState && selected}
|
|
229
|
+
<FieldPolicyEditor
|
|
230
|
+
state={editorState}
|
|
231
|
+
{adapter}
|
|
232
|
+
fields={selected.fields}
|
|
233
|
+
onclose={() => editorOpen = false}
|
|
234
|
+
onmutated={editorMutated}
|
|
235
|
+
/>
|
|
236
|
+
{/if}
|
|
237
|
+
{#if prunableDriftRows(visibleAudit).length}
|
|
238
|
+
<section class="field-policy-control-panel__drift" aria-label="Manifest drift">
|
|
239
|
+
<h2>Manifest drift</h2>
|
|
240
|
+
<p>These policy rows no longer match a registered field and are ignored by the resolver.</p>
|
|
241
|
+
<ul>
|
|
242
|
+
{#each prunableDriftRows(visibleAudit) as row (row.id)}
|
|
243
|
+
<li><code>{row.objectRef}.{row.fieldName}</code> — {row.reason} <Button type="button" variant="ghost" disabled={busy} onclick={() => prune(row.id)}>Prune</Button></li>
|
|
244
|
+
{/each}
|
|
245
|
+
</ul>
|
|
246
|
+
</section>
|
|
247
|
+
{/if}
|
|
248
|
+
</section>
|
|
249
|
+
{/if}
|
|
250
|
+
|
|
251
|
+
<style>
|
|
252
|
+
.field-policy-control-panel { display: grid; gap: var(--smrt-spacing-4); }
|
|
253
|
+
.field-policy-control-panel header p, .field-policy-control-panel__detail > p { color: var(--smrt-color-on-surface-variant); }
|
|
254
|
+
.field-policy-control-panel__error { color: var(--smrt-color-error, #b42318); }
|
|
255
|
+
.field-policy-control-panel__layers { display: grid; gap: var(--smrt-spacing-2); }
|
|
256
|
+
.field-policy-control-panel__layers div { display: grid; grid-template-columns: 10rem minmax(0, 1fr); gap: var(--smrt-spacing-2); }
|
|
257
|
+
.field-policy-control-panel__layers dt { font-weight: 600; }
|
|
258
|
+
.field-policy-control-panel__layers dd { margin: 0; }
|
|
259
|
+
.field-policy-control-panel__actions { display: flex; flex-wrap: wrap; gap: var(--smrt-spacing-2); }
|
|
260
|
+
.field-policy-control-panel__drift ul { display: grid; gap: var(--smrt-spacing-2); padding-inline-start: var(--smrt-spacing-5); }
|
|
261
|
+
</style>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Component, Snippet } from 'svelte';
|
|
2
|
+
import type { FieldPolicyDetailItem, FieldPolicySettingsCatalogData, FieldPolicySettingsCatalogPage } from '../../settings-catalog.js';
|
|
3
|
+
import { type FieldPolicyControlPanelAdapter } from '../settings-catalog.js';
|
|
4
|
+
export interface FieldPolicyCatalogComponentProps {
|
|
5
|
+
page: FieldPolicySettingsCatalogPage;
|
|
6
|
+
baseUrl: string;
|
|
7
|
+
detail: Snippet<[{
|
|
8
|
+
item: FieldPolicyDetailItem;
|
|
9
|
+
}]>;
|
|
10
|
+
preservedParams?: Record<string, string>;
|
|
11
|
+
searchPlaceholder?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface FieldPolicyControlPanelProps {
|
|
14
|
+
data: FieldPolicySettingsCatalogData;
|
|
15
|
+
adapter: FieldPolicyControlPanelAdapter;
|
|
16
|
+
catalog: Component<FieldPolicyCatalogComponentProps>;
|
|
17
|
+
baseUrl: string;
|
|
18
|
+
permissions?: readonly string[];
|
|
19
|
+
heading?: string;
|
|
20
|
+
onchanged?: () => void;
|
|
21
|
+
confirmAction?: (message: string) => boolean | Promise<boolean>;
|
|
22
|
+
}
|
|
23
|
+
declare const FieldPolicyControlPanel: Component<FieldPolicyControlPanelProps, {}, "">;
|
|
24
|
+
type FieldPolicyControlPanel = ReturnType<typeof FieldPolicyControlPanel>;
|
|
25
|
+
export default FieldPolicyControlPanel;
|
|
26
|
+
//# sourceMappingURL=FieldPolicyControlPanel.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FieldPolicyControlPanel.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/FieldPolicyControlPanel.svelte.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACjD,OAAO,KAAK,EACV,qBAAqB,EACrB,8BAA8B,EAC9B,8BAA8B,EAC/B,MAAM,2BAA2B,CAAC;AASnC,OAAO,EAGL,KAAK,8BAA8B,EAMpC,MAAM,wBAAwB,CAAC;AAIhC,MAAM,WAAW,gCAAgC;IAC/C,IAAI,EAAE,8BAA8B,CAAC;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC,CAAC;QAAE,IAAI,EAAE,qBAAqB,CAAA;KAAE,CAAC,CAAC,CAAC;IACnD,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,4BAA4B;IAC3C,IAAI,EAAE,8BAA8B,CAAC;IACrC,OAAO,EAAE,8BAA8B,CAAC;IACxC,OAAO,EAAE,SAAS,CAAC,gCAAgC,CAAC,CAAC;IACrD,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACjE;AAiND,QAAA,MAAM,uBAAuB,iDAAwC,CAAC;AACtE,KAAK,uBAAuB,GAAG,UAAU,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAC1E,eAAe,uBAAuB,CAAC"}
|