@happyvertical/smrt-fields 0.40.60 → 0.40.62

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