@svadmin/ui 0.72.0 → 0.74.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +62 -22
- package/THIRD_PARTY_NOTICES.md +52 -0
- package/dist/app.css +8488 -6297
- package/dist/app.theme.css +8514 -6374
- package/dist/class-properties.generated.d.ts +1 -0
- package/dist/class-properties.generated.js +2 -0
- package/dist/classnames.d.ts +8 -0
- package/dist/classnames.js +26 -0
- package/dist/component-registry.d.ts +14977 -0
- package/dist/component-registry.js +216 -0
- package/dist/components/AboutSettings.svelte +7 -1
- package/dist/components/AboutSettings.svelte.d.ts +4 -1
- package/dist/components/ActivityFeed.svelte +9 -3
- package/dist/components/ActivityFeed.svelte.d.ts +3 -0
- package/dist/components/AdminApp.svelte +19 -10
- package/dist/components/AdminApp.svelte.d.ts +6 -0
- package/dist/components/ApiSettings.svelte +41 -5
- package/dist/components/ApprovalCenter.svelte +283 -0
- package/dist/components/ApprovalCenter.svelte.d.ts +10 -0
- package/dist/components/AuditLogViewer.svelte +3 -1
- package/dist/components/AutoForm.svelte +53 -9
- package/dist/components/AutoForm.svelte.d.ts +3 -0
- package/dist/components/AutoTable.svelte +846 -43
- package/dist/components/AutoTable.svelte.d.ts +22 -1
- package/dist/components/BoundRecordDetailDrawer.svelte +17 -2
- package/dist/components/BoundRecordDetailDrawer.svelte.d.ts +4 -0
- package/dist/components/Breadcrumbs.svelte +11 -1
- package/dist/components/CancelTaskButton.svelte +12 -42
- package/dist/components/ColorPicker.svelte +73 -0
- package/dist/components/ColorPicker.svelte.d.ts +15 -0
- package/dist/components/ComboboxField.svelte +143 -34
- package/dist/components/ComboboxField.svelte.d.ts +4 -2
- package/dist/components/CreatePage.svelte +4 -0
- package/dist/components/CreatePage.svelte.d.ts +2 -0
- package/dist/components/DashboardView.svelte +99 -0
- package/dist/components/DashboardView.svelte.d.ts +14 -0
- package/dist/components/DatePicker.svelte +10 -0
- package/dist/components/DatePicker.svelte.d.ts +6 -0
- package/dist/components/DateRangeInput.svelte +155 -0
- package/dist/components/DateRangeInput.svelte.d.ts +35 -0
- package/dist/components/DateRangePicker.svelte +10 -0
- package/dist/components/DateRangePicker.svelte.d.ts +6 -0
- package/dist/components/DateTimeInput.svelte +134 -0
- package/dist/components/DateTimeInput.svelte.d.ts +27 -0
- package/dist/components/DateTimePicker.svelte +10 -0
- package/dist/components/DateTimePicker.svelte.d.ts +6 -0
- package/dist/components/DevTools.svelte +36 -28
- package/dist/components/DevframePanel.svelte +123 -0
- package/dist/components/DevframePanel.svelte.d.ts +3 -0
- package/dist/components/EditPage.svelte +4 -0
- package/dist/components/EditPage.svelte.d.ts +2 -0
- package/dist/components/ErrorSummary.svelte +52 -0
- package/dist/components/ErrorSummary.svelte.d.ts +14 -0
- package/dist/components/FieldRenderer.svelte +172 -99
- package/dist/components/FileUpload.svelte +412 -0
- package/dist/components/FileUpload.svelte.d.ts +43 -0
- package/dist/components/FilterBuilder.svelte +244 -265
- package/dist/components/FilterBuilder.svelte.d.ts +3 -0
- package/dist/components/FilterCollectionInput.svelte +80 -0
- package/dist/components/FilterCollectionInput.svelte.d.ts +10 -0
- package/dist/components/GanttChart.svelte +66 -14
- package/dist/components/GanttChart.svelte.d.ts +6 -0
- package/dist/components/Header.svelte +18 -2
- package/dist/components/ImportWizard.svelte +509 -100
- package/dist/components/ImportWizard.svelte.d.ts +11 -0
- package/dist/components/JsonSchemaForm.svelte +322 -98
- package/dist/components/JsonSchemaForm.svelte.d.ts +18 -1
- package/dist/components/KanbanBoard.svelte +195 -40
- package/dist/components/KanbanBoard.svelte.d.ts +9 -2
- package/dist/components/Layout.svelte +4 -3
- package/dist/components/LazyAutoForm.svelte +28 -0
- package/dist/components/LazyAutoForm.svelte.d.ts +8 -0
- package/dist/components/LazyAutoTable.svelte +28 -0
- package/dist/components/LazyAutoTable.svelte.d.ts +8 -0
- package/dist/components/LazySettingsPage.svelte +28 -0
- package/dist/components/LazySettingsPage.svelte.d.ts +8 -0
- package/dist/components/LazyShowPage.svelte +28 -0
- package/dist/components/LazyShowPage.svelte.d.ts +8 -0
- package/dist/components/LazyTaskQueueDrawer.svelte.d.ts +1 -1
- package/dist/components/ListPage.svelte +9 -1
- package/dist/components/ListPage.svelte.d.ts +5 -0
- package/dist/components/LoginPage.svelte +2 -2
- package/dist/components/MoneyInput.svelte +25 -0
- package/dist/components/MoneyInput.svelte.d.ts +20 -0
- package/dist/components/MultiTabKeepAlive.svelte +11 -6
- package/dist/components/NotificationsSettings.svelte +69 -2
- package/dist/components/NotificationsSettings.svelte.d.ts +25 -1
- package/dist/components/NumberInput.svelte +25 -0
- package/dist/components/NumberInput.svelte.d.ts +19 -0
- package/dist/components/NumericInput.svelte +110 -0
- package/dist/components/NumericInput.svelte.d.ts +23 -0
- package/dist/components/PercentInput.svelte +25 -0
- package/dist/components/PercentInput.svelte.d.ts +20 -0
- package/dist/components/PermissionMatrix.svelte +20 -1
- package/dist/components/PivotExportButton.svelte +157 -0
- package/dist/components/PivotExportButton.svelte.d.ts +16 -0
- package/dist/components/PivotTable.svelte +229 -74
- package/dist/components/PivotTable.svelte.d.ts +19 -2
- package/dist/components/QuickEditDrawer.svelte +4 -1
- package/dist/components/QuickEditDrawer.svelte.d.ts +2 -0
- package/dist/components/RadioGroup.svelte +121 -0
- package/dist/components/RadioGroup.svelte.d.ts +43 -0
- package/dist/components/RangeSlider.svelte +127 -0
- package/dist/components/RangeSlider.svelte.d.ts +22 -0
- package/dist/components/Rate.svelte +121 -0
- package/dist/components/Rate.svelte.d.ts +16 -0
- package/dist/components/RecordDetailDrawer.svelte +6 -2
- package/dist/components/RecordDetailDrawer.svelte.d.ts +4 -0
- package/dist/components/RelationPicker.svelte +341 -0
- package/dist/components/RelationPicker.svelte.d.ts +26 -0
- package/dist/components/ResourceOperationsPage.svelte +25 -19
- package/dist/components/ResourceOperationsPage.svelte.d.ts +5 -1
- package/dist/components/RetryTaskButton.svelte +12 -42
- package/dist/components/SecuritySettings.svelte +29 -5
- package/dist/components/SegmentedControl.svelte +145 -0
- package/dist/components/SegmentedControl.svelte.d.ts +38 -0
- package/dist/components/SettingsPage.svelte +3 -1
- package/dist/components/SettingsPage.svelte.d.ts +1 -0
- package/dist/components/ShowInferencer.svelte +4 -2
- package/dist/components/ShowInferencer.svelte.d.ts +2 -0
- package/dist/components/ShowPage.svelte +25 -6
- package/dist/components/ShowPage.svelte.d.ts +5 -0
- package/dist/components/Sidebar.svelte +5 -5
- package/dist/components/Slider.svelte +100 -0
- package/dist/components/Slider.svelte.d.ts +19 -0
- package/dist/components/SpreadsheetView.svelte +1037 -124
- package/dist/components/SpreadsheetView.svelte.d.ts +19 -0
- package/dist/components/StepsForm.svelte +5 -5
- package/dist/components/SvarAutoTable.svelte +39 -0
- package/dist/components/SvarAutoTable.svelte.d.ts +13 -0
- package/dist/components/SvarDataGrid.svelte +362 -0
- package/dist/components/SvarDataGrid.svelte.d.ts +57 -0
- package/dist/components/SvarGridCell.svelte +10 -0
- package/dist/components/SvarGridCell.svelte.d.ts +7 -0
- package/dist/components/SvarResourceRead.svelte +50 -0
- package/dist/components/SvarResourceRead.svelte.d.ts +23 -0
- package/dist/components/SvarResourceTable.svelte +63 -0
- package/dist/components/SvarResourceTable.svelte.d.ts +42 -0
- package/dist/components/SvarResourceTableView.svelte +364 -0
- package/dist/components/SvarResourceTableView.svelte.d.ts +4 -0
- package/dist/components/TagsInput.svelte +178 -0
- package/dist/components/TagsInput.svelte.d.ts +17 -0
- package/dist/components/TaskQueueDrawer.svelte +72 -16
- package/dist/components/TimePicker.svelte +10 -0
- package/dist/components/TimePicker.svelte.d.ts +6 -0
- package/dist/components/TreeSelect.svelte +440 -46
- package/dist/components/TreeSelect.svelte.d.ts +6 -1
- package/dist/components/TreeTable.svelte +484 -82
- package/dist/components/TreeTable.svelte.d.ts +24 -1
- package/dist/components/TwoFactorAuthPage.svelte +85 -48
- package/dist/components/TwoFactorAuthPage.svelte.d.ts +12 -1
- package/dist/components/VirtualTable.svelte +116 -20
- package/dist/components/VirtualTable.svelte.d.ts +5 -0
- package/dist/components/account/CompanyProfilePage.svelte +74 -38
- package/dist/components/account/GetStartedPage.svelte +2 -1
- package/dist/components/account/ImportMembersPage.svelte +22 -167
- package/dist/components/account/ImportMembersPage.svelte.d.ts +4 -1
- package/dist/components/account/MemberDirectory.svelte +156 -0
- package/dist/components/account/MemberDirectory.svelte.d.ts +19 -0
- package/dist/components/account/MembersStarterPage.svelte +9 -55
- package/dist/components/account/MembersStarterPage.svelte.d.ts +5 -1
- package/dist/components/account/SecurityLogPage.svelte +4 -1
- package/dist/components/account/SettingsPlainPage.svelte +7 -38
- package/dist/components/account/SettingsPlainPage.svelte.d.ts +4 -1
- package/dist/components/account/SettingsSidebarPage.svelte +7 -20
- package/dist/components/account/TeamMembersPage.svelte +4 -20
- package/dist/components/account/TeamMembersPage.svelte.d.ts +5 -1
- package/dist/components/account/UserProfilePage.svelte +3 -25
- package/dist/components/account/UserProfilePage.svelte.d.ts +17 -2
- package/dist/components/auto-table-grid.d.ts +26 -0
- package/dist/components/auto-table-grid.js +1 -0
- package/dist/components/buttons/ExportButton.svelte +56 -12
- package/dist/components/buttons/ExportButton.svelte.d.ts +11 -0
- package/dist/components/content/ContentPageHeader.svelte +12 -9
- package/dist/components/content/ContentPageShell.svelte +6 -9
- package/dist/components/content/FileBrowser.svelte +35 -0
- package/dist/components/content/FileBrowser.svelte.d.ts +14 -0
- package/dist/components/content/MetricBlock.svelte +10 -13
- package/dist/components/content/NetworkTable.svelte +3 -3
- package/dist/components/content/NetworkTable.svelte.d.ts +1 -0
- package/dist/components/content/PageToolbar.svelte +6 -10
- package/dist/components/content/ReferenceNotice.svelte +5 -0
- package/dist/components/content/ReferenceNotice.svelte.d.ts +18 -0
- package/dist/components/content/SectionHeader.svelte +8 -13
- package/dist/components/content/SettingsFieldRow.svelte +9 -23
- package/dist/components/content/SettingsGroup.svelte +11 -27
- package/dist/components/content/StatusBadge.svelte +3 -8
- package/dist/components/content/WorkspaceLayout.svelte +8 -12
- package/dist/components/enterprise/filter-tree.d.ts +48 -0
- package/dist/components/enterprise/filter-tree.js +224 -0
- package/dist/components/enterprise/json-schema-form.d.ts +39 -0
- package/dist/components/enterprise/json-schema-form.js +195 -0
- package/dist/components/enterprise/recursive-schema-form.d.ts +30 -0
- package/dist/components/enterprise/recursive-schema-form.js +196 -0
- package/dist/components/enterprise/spreadsheet-formula.d.ts +12 -0
- package/dist/components/enterprise/spreadsheet-formula.js +245 -0
- package/dist/components/export-reference.d.ts +2 -0
- package/dist/components/export-reference.js +9 -0
- package/dist/components/fieldComponentMap.js +2 -0
- package/dist/components/fields/DateField.svelte +12 -12
- package/dist/components/fields/date-display.d.ts +6 -0
- package/dist/components/fields/date-display.js +24 -0
- package/dist/components/fields/date-field-value.d.ts +2 -0
- package/dist/components/fields/date-field-value.js +13 -0
- package/dist/components/json-schema-form-state.d.ts +37 -0
- package/dist/components/json-schema-form-state.js +168 -0
- package/dist/components/network/TeamCrewTablePage.svelte +6 -1
- package/dist/components/network/UserCardsNFTPage.svelte +2 -0
- package/dist/components/profile/PublicProfilePage.svelte +2 -0
- package/dist/components/record-detail.svelte.d.ts +3 -0
- package/dist/components/record-detail.svelte.js +10 -4
- package/dist/components/saved-list-views.d.ts +74 -1
- package/dist/components/saved-list-views.js +191 -3
- package/dist/components/svar-grid-cells.d.ts +14 -0
- package/dist/components/svar-grid-cells.js +2 -0
- package/dist/components/svar-grid-contract.d.ts +80 -0
- package/dist/components/svar-grid-contract.js +159 -0
- package/dist/components/svar-grid-interactions.d.ts +54 -0
- package/dist/components/svar-grid-interactions.js +174 -0
- package/dist/components/svar-grid-loading.d.ts +40 -0
- package/dist/components/svar-grid-loading.js +180 -0
- package/dist/components/svar-grid-operations.d.ts +37 -0
- package/dist/components/svar-grid-operations.js +186 -0
- package/dist/components/svar-grid-panes.d.ts +34 -0
- package/dist/components/svar-grid-panes.js +66 -0
- package/dist/components/svar-grid-resource-loading.d.ts +18 -0
- package/dist/components/svar-grid-resource-loading.js +68 -0
- package/dist/components/svar-grid-resource-session.svelte.d.ts +29 -0
- package/dist/components/svar-grid-resource-session.svelte.js +61 -0
- package/dist/components/table-contract.d.ts +12 -1
- package/dist/components/task-action.svelte.d.ts +13 -0
- package/dist/components/task-action.svelte.js +73 -0
- package/dist/components/ui/DesignSystemShowcase.svelte +164 -0
- package/dist/components/ui/DesignSystemShowcase.svelte.d.ts +3 -0
- package/dist/components/ui/badge/badge-variants.d.ts +3 -2
- package/dist/components/ui/badge/badge-variants.js +2 -1
- package/dist/components/ui/badge/badge.svelte +3 -0
- package/dist/components/ui/badge/badge.svelte.d.ts +1 -0
- package/dist/components/ui/button/button-variants.d.ts +5 -4
- package/dist/components/ui/button/button-variants.js +7 -2
- package/dist/components/ui/checkbox/checkbox.svelte +5 -1
- package/dist/components/ui/checkbox/checkbox.svelte.d.ts +5 -1
- package/dist/components/ui/input/input.svelte +8 -6
- package/dist/components/ui/input/input.svelte.d.ts +4 -1
- package/dist/components/ui/select/select.svelte +4 -1
- package/dist/components/ui/select/select.svelte.d.ts +2 -1
- package/dist/components/ui/textarea/textarea.svelte +2 -1
- package/dist/components.css +3110 -0
- package/dist/date-input-policy.d.ts +4 -0
- package/dist/date-input-policy.js +35 -0
- package/dist/design-contract.d.ts +13 -0
- package/dist/design-contract.js +11 -0
- package/dist/design-system-components.d.ts +100 -0
- package/dist/design-system-components.js +101 -0
- package/dist/design-system.d.ts +15 -0
- package/dist/design-system.js +7 -0
- package/dist/devtools-bridge.d.ts +80 -0
- package/dist/devtools-bridge.js +92 -0
- package/dist/index.d.ts +50 -1
- package/dist/index.js +32 -2
- package/dist/page-chrome.css +12 -49
- package/dist/recipes.d.ts +960 -0
- package/dist/recipes.js +264 -0
- package/dist/rendering/index.d.ts +87 -0
- package/dist/rendering/index.js +117 -0
- package/dist/styles/aliases.css +49 -0
- package/dist/styles/compatibility.epilogue.css +384 -0
- package/dist/styles/compatibility.prelude.css +5513 -0
- package/dist/styles/conditional-states.css +28 -0
- package/dist/styles/conditional-utilities.css +22 -0
- package/dist/tree-table-model.d.ts +24 -0
- package/dist/tree-table-model.js +111 -0
- package/dist/utils.d.ts +1 -1
- package/dist/utils.js +1 -1
- package/package.json +40 -10
- package/styles-compatibility.json +12 -0
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { ChevronLeft, ChevronRight, Loader2, RefreshCw, Search } from '@lucide/svelte';
|
|
3
|
+
import { onDestroy, untrack } from 'svelte';
|
|
4
|
+
import { captureAdminContext, captureAuthSession, createEnterpriseRequestContext } from '@svadmin/core';
|
|
5
|
+
import {
|
|
6
|
+
ApprovalContractError, decodeApprovalList, decodeApprovalReceipt, decodeApprovalTransition,
|
|
7
|
+
} from '@svadmin/core';
|
|
8
|
+
import type {
|
|
9
|
+
ApprovalProvider, ApprovalRecord, ApprovalTransition, EnterpriseProviderRequestContext,
|
|
10
|
+
} from '@svadmin/core';
|
|
11
|
+
import { useTranslation } from '@svadmin/core/i18n';
|
|
12
|
+
import { Badge } from './ui/badge/index.js';
|
|
13
|
+
import { Button } from './ui/button/index.js';
|
|
14
|
+
import { Input } from './ui/input/index.js';
|
|
15
|
+
|
|
16
|
+
type ApprovalView = 'pending' | 'history';
|
|
17
|
+
interface Props {
|
|
18
|
+
provider: ApprovalProvider;
|
|
19
|
+
requestContext?: EnterpriseProviderRequestContext;
|
|
20
|
+
pageSize?: number;
|
|
21
|
+
title?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
let { provider, requestContext, pageSize = 20, title }: Props = $props();
|
|
25
|
+
const context = captureAdminContext();
|
|
26
|
+
const i18n = useTranslation();
|
|
27
|
+
let view = $state<ApprovalView>('pending');
|
|
28
|
+
let search = $state('');
|
|
29
|
+
let appliedSearch = $state('');
|
|
30
|
+
let page = $state(1);
|
|
31
|
+
let records = $state<ApprovalRecord[]>([]);
|
|
32
|
+
let total = $state(0);
|
|
33
|
+
let selectedId = $state<string>();
|
|
34
|
+
let loading = $state(false);
|
|
35
|
+
let error = $state<'load' | 'invalid' | 'conflict' | 'action'>();
|
|
36
|
+
let actionPending = $state(false);
|
|
37
|
+
let comment = $state('');
|
|
38
|
+
let targetId = $state('');
|
|
39
|
+
let actionDialog = $state<string>();
|
|
40
|
+
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
41
|
+
let mounted = true;
|
|
42
|
+
let epoch = 0;
|
|
43
|
+
let requestScope: EnterpriseProviderRequestContext | undefined;
|
|
44
|
+
let generatedRequestContext: EnterpriseProviderRequestContext | undefined;
|
|
45
|
+
onDestroy(() => { mounted = false; clearTimeout(timer); });
|
|
46
|
+
|
|
47
|
+
const activeRecord = $derived(records.find(record => record.id === selectedId));
|
|
48
|
+
const activeAction = $derived(
|
|
49
|
+
activeRecord?.allowedActions.find(action => action.id === actionDialog),
|
|
50
|
+
);
|
|
51
|
+
const normalizedPageSize = $derived(Number.isSafeInteger(pageSize) && pageSize > 0 && pageSize <= 200 ? pageSize : 20);
|
|
52
|
+
const totalPages = $derived(Math.max(1, Math.ceil(total / normalizedPageSize)));
|
|
53
|
+
|
|
54
|
+
function resolveRequestContext(): EnterpriseProviderRequestContext {
|
|
55
|
+
if (requestContext) return requestContext;
|
|
56
|
+
const tenant = context.tenantCacheKey?.__svadminTenant;
|
|
57
|
+
if (typeof tenant !== 'string' && typeof tenant !== 'number') throw new Error('Missing tenant context');
|
|
58
|
+
if (generatedRequestContext?.tenantId === tenant) return generatedRequestContext;
|
|
59
|
+
generatedRequestContext = createEnterpriseRequestContext({ tenantId: tenant });
|
|
60
|
+
return generatedRequestContext;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async function load(): Promise<void> {
|
|
64
|
+
const currentEpoch = ++epoch;
|
|
65
|
+
loading = true;
|
|
66
|
+
error = undefined;
|
|
67
|
+
try {
|
|
68
|
+
const scope = resolveRequestContext();
|
|
69
|
+
requestScope = scope;
|
|
70
|
+
const result = decodeApprovalList(await provider.list(scope, {
|
|
71
|
+
view, page, pageSize: normalizedPageSize, search: appliedSearch,
|
|
72
|
+
}));
|
|
73
|
+
if (!mounted || currentEpoch !== epoch || requestScope !== scope) return;
|
|
74
|
+
records = result.data;
|
|
75
|
+
total = result.total;
|
|
76
|
+
selectedId = result.data.some(record => record.id === selectedId) ? selectedId : result.data[0]?.id;
|
|
77
|
+
} catch (cause) {
|
|
78
|
+
if (!mounted || currentEpoch !== epoch) return;
|
|
79
|
+
error = cause instanceof ApprovalContractError ? 'invalid' : 'load';
|
|
80
|
+
records = [];
|
|
81
|
+
total = 0;
|
|
82
|
+
selectedId = undefined;
|
|
83
|
+
} finally {
|
|
84
|
+
if (mounted && currentEpoch === epoch) loading = false;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function scheduleSearch(event: Event): void {
|
|
89
|
+
if (!(event.currentTarget instanceof HTMLInputElement)) return;
|
|
90
|
+
search = event.currentTarget.value;
|
|
91
|
+
clearTimeout(timer);
|
|
92
|
+
timer = setTimeout(() => {
|
|
93
|
+
appliedSearch = search.trim().slice(0, 200);
|
|
94
|
+
page = 1;
|
|
95
|
+
}, 250);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function switchView(next: ApprovalView): void {
|
|
99
|
+
if (view === next) return;
|
|
100
|
+
view = next;
|
|
101
|
+
page = 1;
|
|
102
|
+
selectedId = undefined;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function openAction(action: string): void {
|
|
106
|
+
if (!activeRecord?.allowedActions.some(candidate => candidate.id === action)) return;
|
|
107
|
+
actionDialog = action;
|
|
108
|
+
comment = '';
|
|
109
|
+
targetId = '';
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
async function submitAction(): Promise<void> {
|
|
113
|
+
const record = activeRecord;
|
|
114
|
+
const action = activeAction;
|
|
115
|
+
const scope = requestScope;
|
|
116
|
+
if (!record || !action || !scope || !provider.transition || actionPending) return;
|
|
117
|
+
let input: ApprovalTransition;
|
|
118
|
+
try {
|
|
119
|
+
input = decodeApprovalTransition({
|
|
120
|
+
id: record.id,
|
|
121
|
+
expectedVersion: record.version,
|
|
122
|
+
action: action.id,
|
|
123
|
+
comment,
|
|
124
|
+
...(targetId.trim() ? { targetId: targetId.trim() } : {}),
|
|
125
|
+
idempotencyKey: `${record.id}:${record.version}:${action.id}:${crypto.randomUUID()}`,
|
|
126
|
+
}, record);
|
|
127
|
+
} catch {
|
|
128
|
+
error = 'action';
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
actionPending = true;
|
|
132
|
+
const actionEpoch = epoch;
|
|
133
|
+
error = undefined;
|
|
134
|
+
try {
|
|
135
|
+
const receipt = decodeApprovalReceipt(await provider.transition(scope, input), input);
|
|
136
|
+
if (!mounted || actionEpoch !== epoch) return;
|
|
137
|
+
if (!receipt.ok) {
|
|
138
|
+
error = 'conflict';
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
actionDialog = undefined;
|
|
142
|
+
records = records.map(candidate => candidate.id === receipt.record.id ? receipt.record : candidate);
|
|
143
|
+
selectedId = receipt.record.id;
|
|
144
|
+
} catch (cause) {
|
|
145
|
+
if (!mounted || actionEpoch !== epoch) return;
|
|
146
|
+
error = cause instanceof ApprovalContractError ? 'invalid' : 'action';
|
|
147
|
+
} finally {
|
|
148
|
+
if (mounted && actionEpoch === epoch) actionPending = false;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function canSubmit(action: ApprovalRecord['allowedActions'][number]): boolean {
|
|
153
|
+
return (!action.commentRequired || !!comment.trim()) && (!action.targetRequired || !!targetId.trim());
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
$effect(() => {
|
|
157
|
+
void provider;
|
|
158
|
+
void view;
|
|
159
|
+
void page;
|
|
160
|
+
void appliedSearch;
|
|
161
|
+
void requestContext;
|
|
162
|
+
void normalizedPageSize;
|
|
163
|
+
void context.tenantCacheKey?.__svadminTenant;
|
|
164
|
+
void captureAuthSession(context.authProvider).cacheKey;
|
|
165
|
+
untrack(() => {
|
|
166
|
+
records = [];
|
|
167
|
+
selectedId = undefined;
|
|
168
|
+
actionDialog = undefined;
|
|
169
|
+
actionPending = false;
|
|
170
|
+
void load();
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
</script>
|
|
174
|
+
|
|
175
|
+
<section class="svadmin-approval-center" aria-label={title ?? i18n.t('approval.title')}>
|
|
176
|
+
<header class="svadmin-approval-center__header">
|
|
177
|
+
<div>
|
|
178
|
+
<h2>{title ?? i18n.t('approval.title')}</h2>
|
|
179
|
+
</div>
|
|
180
|
+
<Button type="button" variant="outline" size="sm" aria-label={i18n.t('common.refresh')} onclick={() => void load()}>
|
|
181
|
+
<RefreshCw class={loading ? 'svadmin-approval-center__spin' : ''} />
|
|
182
|
+
</Button>
|
|
183
|
+
</header>
|
|
184
|
+
<div class="svadmin-approval-center__toolbar">
|
|
185
|
+
<Button type="button" aria-pressed={view === 'pending'} variant={view === 'pending' ? 'default' : 'outline'} onclick={() => switchView('pending')}>{i18n.t('approval.pending')}</Button>
|
|
186
|
+
<Button type="button" aria-pressed={view === 'history'} variant={view === 'history' ? 'default' : 'outline'} onclick={() => switchView('history')}>{i18n.t('approval.history')}</Button>
|
|
187
|
+
<label class="svadmin-approval-center__search">
|
|
188
|
+
<Search aria-hidden="true" />
|
|
189
|
+
<Input value={search} oninput={scheduleSearch} placeholder={i18n.t('approval.search')} aria-label={i18n.t('approval.search')} />
|
|
190
|
+
</label>
|
|
191
|
+
</div>
|
|
192
|
+
{#if error}
|
|
193
|
+
<div role="alert">{i18n.t(`approval.${error}`)}</div>
|
|
194
|
+
{/if}
|
|
195
|
+
<div class="svadmin-approval-center__body">
|
|
196
|
+
<div class="svadmin-approval-center__list">
|
|
197
|
+
{#if loading}
|
|
198
|
+
<div role="status"><Loader2 class="svadmin-approval-center__spin" /> {i18n.t('common.loading')}</div>
|
|
199
|
+
{:else if records.length === 0}
|
|
200
|
+
<div role="status">{i18n.t('approval.empty')}</div>
|
|
201
|
+
{:else}
|
|
202
|
+
{#each records as record (record.id)}
|
|
203
|
+
<button type="button" aria-pressed={record.id === selectedId} class:selected={record.id === selectedId} onclick={() => selectedId = record.id}>
|
|
204
|
+
<strong>{record.title}</strong>
|
|
205
|
+
<span>{record.applicant} · {record.status}</span>
|
|
206
|
+
</button>
|
|
207
|
+
{/each}
|
|
208
|
+
{/if}
|
|
209
|
+
</div>
|
|
210
|
+
<div class="svadmin-approval-center__detail">
|
|
211
|
+
{#if activeRecord}
|
|
212
|
+
<h3>{activeRecord.title}</h3>
|
|
213
|
+
<Badge variant="outline">{activeRecord.status}</Badge>
|
|
214
|
+
<p>{i18n.t('approval.applicant', { name: activeRecord.applicant })}</p>
|
|
215
|
+
{#if activeRecord.attachments.length}
|
|
216
|
+
<h4>{i18n.t('approval.attachments')}</h4>
|
|
217
|
+
<ul>{#each activeRecord.attachments as attachment (attachment.id)}<li>{attachment.name}</li>{/each}</ul>
|
|
218
|
+
{/if}
|
|
219
|
+
<h4>{i18n.t('approval.history')}</h4>
|
|
220
|
+
<ol>{#each activeRecord.history as event (event.id)}<li>{event.actor} · {event.action} · {event.comment || '—'}</li>{/each}</ol>
|
|
221
|
+
{#if provider.transition && activeRecord.allowedActions.length}
|
|
222
|
+
<div class="svadmin-approval-center__actions">
|
|
223
|
+
{#each activeRecord.allowedActions as action (action.id)}
|
|
224
|
+
<Button type="button" disabled={actionPending} onclick={() => openAction(action.id)}>{action.label}</Button>
|
|
225
|
+
{/each}
|
|
226
|
+
</div>
|
|
227
|
+
{/if}
|
|
228
|
+
{:else}
|
|
229
|
+
<p>{i18n.t('approval.select')}</p>
|
|
230
|
+
{/if}
|
|
231
|
+
</div>
|
|
232
|
+
</div>
|
|
233
|
+
<footer class="svadmin-approval-center__footer">
|
|
234
|
+
<Button type="button" aria-label={i18n.t('common.prev')} title={i18n.t('common.prev')} variant="outline" disabled={page <= 1 || loading} onclick={() => { page -= 1; }}>
|
|
235
|
+
<ChevronLeft />
|
|
236
|
+
</Button>
|
|
237
|
+
<span>{page} / {totalPages}</span>
|
|
238
|
+
<Button type="button" aria-label={i18n.t('common.next')} title={i18n.t('common.next')} variant="outline" disabled={page >= totalPages || loading} onclick={() => { page += 1; }}>
|
|
239
|
+
<ChevronRight />
|
|
240
|
+
</Button>
|
|
241
|
+
</footer>
|
|
242
|
+
</section>
|
|
243
|
+
|
|
244
|
+
{#if actionDialog && activeRecord}
|
|
245
|
+
<div class="svadmin-approval-center__dialog" role="dialog" aria-modal="true" aria-label={activeAction?.label ?? i18n.t('common.confirmAction')}>
|
|
246
|
+
<h3>{activeAction?.label}</h3>
|
|
247
|
+
<label>{i18n.t('approval.comment')}
|
|
248
|
+
<textarea bind:value={comment} required={activeAction?.commentRequired} maxlength={10000}></textarea>
|
|
249
|
+
</label>
|
|
250
|
+
{#if activeAction?.targetRequired}
|
|
251
|
+
<label>{i18n.t('approval.target')}
|
|
252
|
+
<Input bind:value={targetId} required maxlength={200} />
|
|
253
|
+
</label>
|
|
254
|
+
{/if}
|
|
255
|
+
<div>
|
|
256
|
+
<Button type="button" variant="outline" onclick={() => actionDialog = undefined}>{i18n.t('common.cancel')}</Button>
|
|
257
|
+
<Button type="button" disabled={actionPending || !activeAction || !canSubmit(activeAction)} onclick={() => void submitAction()}>
|
|
258
|
+
{actionPending ? i18n.t('common.processing') : i18n.t('common.confirm')}
|
|
259
|
+
</Button>
|
|
260
|
+
</div>
|
|
261
|
+
</div>
|
|
262
|
+
{/if}
|
|
263
|
+
|
|
264
|
+
<style>
|
|
265
|
+
.svadmin-approval-center { display: grid; gap: 1rem; min-width: 0; }
|
|
266
|
+
.svadmin-approval-center__header, .svadmin-approval-center__toolbar, .svadmin-approval-center__footer,
|
|
267
|
+
.svadmin-approval-center__actions { display: flex; align-items: center; gap: 0.5rem; }
|
|
268
|
+
.svadmin-approval-center__header, .svadmin-approval-center__footer { justify-content: space-between; }
|
|
269
|
+
.svadmin-approval-center__toolbar { flex-wrap: wrap; }
|
|
270
|
+
.svadmin-approval-center__search { display: flex; align-items: center; gap: 0.5rem; min-width: min(100%, 20rem); }
|
|
271
|
+
.svadmin-approval-center__body { display: grid; grid-template-columns: minmax(12rem, 0.8fr) minmax(0, 1.6fr); border: 1px solid var(--border); }
|
|
272
|
+
.svadmin-approval-center__list { border-inline-end: 1px solid var(--border); }
|
|
273
|
+
.svadmin-approval-center__list button { display: grid; gap: 0.25rem; width: 100%; padding: 0.75rem; text-align: start; border-block-end: 1px solid var(--border); }
|
|
274
|
+
.svadmin-approval-center__list button.selected { background: var(--muted); }
|
|
275
|
+
.svadmin-approval-center__list span { color: var(--muted-foreground); font-size: 0.875rem; }
|
|
276
|
+
.svadmin-approval-center__detail { display: grid; gap: 0.75rem; padding: 1rem; min-width: 0; }
|
|
277
|
+
.svadmin-approval-center__detail ol, .svadmin-approval-center__detail ul { margin: 0; padding-inline-start: 1.25rem; }
|
|
278
|
+
.svadmin-approval-center__dialog { position: fixed; inset: 20% auto auto 50%; z-index: 20; display: grid; gap: 1rem; width: min(28rem, calc(100vw - 2rem)); transform: translateX(-50%); padding: 1rem; background: var(--card); border: 1px solid var(--border); box-shadow: var(--shadow-lg); }
|
|
279
|
+
.svadmin-approval-center__dialog textarea { min-height: 6rem; width: 100%; }
|
|
280
|
+
:global(.svadmin-approval-center__spin) { animation: svadmin-approval-spin 1s linear infinite; }
|
|
281
|
+
@keyframes svadmin-approval-spin { to { transform: rotate(360deg); } }
|
|
282
|
+
@media (max-width: 640px) { .svadmin-approval-center__body { grid-template-columns: 1fr; } .svadmin-approval-center__list { border-inline-end: 0; border-block-end: 1px solid var(--border); max-height: 15rem; overflow: auto; } }
|
|
283
|
+
</style>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ApprovalProvider, EnterpriseProviderRequestContext } from '@svadmin/core';
|
|
2
|
+
interface Props {
|
|
3
|
+
provider: ApprovalProvider;
|
|
4
|
+
requestContext?: EnterpriseProviderRequestContext;
|
|
5
|
+
pageSize?: number;
|
|
6
|
+
title?: string;
|
|
7
|
+
}
|
|
8
|
+
declare const ApprovalCenter: import("svelte").Component<Props, {}, "">;
|
|
9
|
+
type ApprovalCenter = ReturnType<typeof ApprovalCenter>;
|
|
10
|
+
export default ApprovalCenter;
|
|
@@ -58,7 +58,8 @@
|
|
|
58
58
|
total = result.total;
|
|
59
59
|
} catch (e) {
|
|
60
60
|
if (currentId !== requestId) return;
|
|
61
|
-
|
|
61
|
+
error = e instanceof Error ? e.message : String(e);
|
|
62
|
+
toast.error(error);
|
|
62
63
|
} finally {
|
|
63
64
|
if (currentId === requestId) loading = false;
|
|
64
65
|
}
|
|
@@ -118,6 +119,7 @@
|
|
|
118
119
|
{#if error}
|
|
119
120
|
<div class="svadmin-u-0478c89a150f svadmin-u-ca6bcd4b6f3f svadmin-u-f0c1e65bd6f2 svadmin-u-7a0854fdbc30 svadmin-u-811148b13d1e svadmin-u-5f22e64f2282 svadmin-u-ca6bf63030aa">
|
|
120
121
|
<p>{error}</p>
|
|
122
|
+
<button type="button" onclick={() => void loadLogs(authProvider, page)}>{i18n.t('common.retry')}</button>
|
|
121
123
|
</div>
|
|
122
124
|
{:else}
|
|
123
125
|
<!-- Search Bar -->
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { bindResourceRendering, type ResourceRendering } from '../rendering/index.js';
|
|
2
3
|
import { definedReactiveOptions } from '@svadmin/core/options';
|
|
3
4
|
|
|
4
5
|
import { definedOptions } from '@svadmin/core/options';
|
|
@@ -17,6 +18,7 @@
|
|
|
17
18
|
import * as Alert from './ui/alert/index.js';
|
|
18
19
|
import { Skeleton } from './ui/skeleton/index.js';
|
|
19
20
|
import ConfirmDialog from './ConfirmDialog.svelte';
|
|
21
|
+
import ErrorSummary from './ErrorSummary.svelte';
|
|
20
22
|
import { cn } from '../utils.js';
|
|
21
23
|
import type { Snippet } from 'svelte';
|
|
22
24
|
|
|
@@ -24,6 +26,7 @@
|
|
|
24
26
|
|
|
25
27
|
interface Props {
|
|
26
28
|
resourceName: string;
|
|
29
|
+
rendering?: ResourceRendering | undefined;
|
|
27
30
|
id?: string | number;
|
|
28
31
|
mode?: 'create' | 'edit' | 'clone' | 'show';
|
|
29
32
|
density?: 'compact' | 'comfortable';
|
|
@@ -36,10 +39,12 @@
|
|
|
36
39
|
redirect?: 'list' | false;
|
|
37
40
|
onCancel?: () => void;
|
|
38
41
|
onNavigationGuardReady?: (guard: (fn: () => void) => void) => void;
|
|
42
|
+
showErrorSummary?: boolean;
|
|
39
43
|
}
|
|
40
44
|
|
|
41
45
|
let {
|
|
42
46
|
resourceName,
|
|
47
|
+
rendering,
|
|
43
48
|
id,
|
|
44
49
|
mode = 'create',
|
|
45
50
|
density = 'comfortable',
|
|
@@ -52,12 +57,15 @@
|
|
|
52
57
|
redirect = 'list',
|
|
53
58
|
onCancel,
|
|
54
59
|
onNavigationGuardReady,
|
|
60
|
+
showErrorSummary = true,
|
|
55
61
|
}: Props = $props();
|
|
56
62
|
const navigation = useNavigation();
|
|
57
63
|
const context = captureAdminContext();
|
|
58
64
|
const binding = useResourceContract(() => resourceName);
|
|
65
|
+
const activeRendering = $derived(bindResourceRendering(rendering, binding.resource));
|
|
59
66
|
const isReadonly = $derived(mode === 'show');
|
|
60
67
|
const isCompact = $derived(density === 'compact');
|
|
68
|
+
const instanceId = $props.id();
|
|
61
69
|
|
|
62
70
|
// ─── Resource metadata ────────────────────────────────────────────
|
|
63
71
|
const resource = $derived(context.getResource(resourceName));
|
|
@@ -128,6 +136,7 @@
|
|
|
128
136
|
case 'boolean': return false;
|
|
129
137
|
case 'tags': case 'images': case 'multiselect': return [];
|
|
130
138
|
case 'select': return field.options?.[0]?.value ?? '';
|
|
139
|
+
case 'relation': return field.multiple ? [] : null;
|
|
131
140
|
case 'json': return {};
|
|
132
141
|
default: return '';
|
|
133
142
|
}
|
|
@@ -143,7 +152,7 @@
|
|
|
143
152
|
|
|
144
153
|
// ─── useForm: single source of truth for values, errors, tainted ──
|
|
145
154
|
const form = useForm(definedReactiveOptions({
|
|
146
|
-
get resource() { return binding.resource; },
|
|
155
|
+
get resource() { void activeRendering; return binding.resource; },
|
|
147
156
|
get action() { return mode; },
|
|
148
157
|
get id() { return id; },
|
|
149
158
|
get defaultValues() { return defaults; },
|
|
@@ -157,6 +166,19 @@
|
|
|
157
166
|
return callback ? () => callback() : undefined;
|
|
158
167
|
},
|
|
159
168
|
}));
|
|
169
|
+
const errorEntries = $derived(formFields.flatMap(field => {
|
|
170
|
+
const message = form.errors[field.key];
|
|
171
|
+
return typeof message === 'string' && message.length > 0
|
|
172
|
+
? [{ fieldKey: field.key, label: field.label || field.key, message }] : [];
|
|
173
|
+
}));
|
|
174
|
+
|
|
175
|
+
const renderedDraft = $derived.by(() => {
|
|
176
|
+
try {
|
|
177
|
+
return { ok: true, values: form.ready && activeRendering ? activeRendering.draft(mode, form.values) : form.values };
|
|
178
|
+
} catch {
|
|
179
|
+
return { ok: false, values: {} };
|
|
180
|
+
}
|
|
181
|
+
});
|
|
160
182
|
|
|
161
183
|
// ─── Submission error (non-field, e.g. network error) ─────────────
|
|
162
184
|
let submitError = $state<string | null>(null);
|
|
@@ -180,7 +202,7 @@
|
|
|
180
202
|
$effect(() => () => { mounted = false; submission = undefined; });
|
|
181
203
|
|
|
182
204
|
function fieldErrorId(fieldKey: string): string {
|
|
183
|
-
return `${resourceName}-${fieldKey}-error`;
|
|
205
|
+
return `${instanceId}-${resourceName}-${fieldKey}-error`;
|
|
184
206
|
}
|
|
185
207
|
|
|
186
208
|
function focusFirstInvalidField(): void {
|
|
@@ -188,6 +210,15 @@
|
|
|
188
210
|
firstInvalid?.focus();
|
|
189
211
|
}
|
|
190
212
|
|
|
213
|
+
function focusField(fieldKey: string): void {
|
|
214
|
+
const field = formElement?.querySelector<HTMLElement>(
|
|
215
|
+
`[data-svadmin-field-key="${CSS.escape(fieldKey)}"]`,
|
|
216
|
+
);
|
|
217
|
+
field?.querySelector<HTMLElement>(
|
|
218
|
+
'input:not([type="hidden"]):not([disabled]), textarea:not([disabled]), select:not([disabled]), button:not([disabled]), [tabindex]:not([tabindex="-1"]):not([disabled])',
|
|
219
|
+
)?.focus();
|
|
220
|
+
}
|
|
221
|
+
|
|
191
222
|
const handleSubmit = $derived.by(() => {
|
|
192
223
|
const current = scope;
|
|
193
224
|
return async () => {
|
|
@@ -228,6 +259,8 @@
|
|
|
228
259
|
const pageTitle = $derived(
|
|
229
260
|
mode === 'create'
|
|
230
261
|
? `${i18n.t('common.create')}${resource.label}`
|
|
262
|
+
: mode === 'clone'
|
|
263
|
+
? `${i18n.t('common.clone')} ${resource.label}`
|
|
231
264
|
: mode === 'show'
|
|
232
265
|
? `${i18n.t('common.detail')}${resource.label}`
|
|
233
266
|
: `${i18n.t('common.edit')}${resource.label}`
|
|
@@ -282,7 +315,7 @@
|
|
|
282
315
|
});
|
|
283
316
|
</script>
|
|
284
317
|
|
|
285
|
-
<div class={isCompact ? 'svadmin-u-3e7ce58d64fa' : 'svadmin-u-b3542e058833'}>
|
|
318
|
+
<div class={isCompact ? 'svadmin-u-3e7ce58d64fa' : 'svadmin-u-b3542e058833'} data-svadmin-rendering-resource={activeRendering?.resource.name} data-svadmin-rendering-kind={activeRendering ? 'form' : undefined}>
|
|
286
319
|
{#if showHeader}
|
|
287
320
|
<div class="svadmin-u-60fbb7713999 svadmin-u-3960ffc248d9 svadmin-u-0c3bc98565dd">
|
|
288
321
|
<TooltipButton
|
|
@@ -319,6 +352,8 @@
|
|
|
319
352
|
<Button type="button" variant="outline" onclick={retry}>
|
|
320
353
|
{i18n.t('common.retry')}
|
|
321
354
|
</Button>
|
|
355
|
+
{:else if !renderedDraft.ok}
|
|
356
|
+
<p role="alert">{i18n.t('common.operationFailed')}</p>
|
|
322
357
|
{:else if form.ready}
|
|
323
358
|
<form bind:this={formElement} onsubmit={submitEvent} class="svadmin-u-cf3893e36c22 svadmin-u-b3542e058833" novalidate>
|
|
324
359
|
{#if submitError}
|
|
@@ -330,6 +365,15 @@
|
|
|
330
365
|
</div>
|
|
331
366
|
{/if}
|
|
332
367
|
|
|
368
|
+
{#if showErrorSummary && errorEntries.length > 0}
|
|
369
|
+
<ErrorSummary
|
|
370
|
+
errors={errorEntries}
|
|
371
|
+
title={i18n.t('common.formErrors')}
|
|
372
|
+
id={`${instanceId}-error-summary`}
|
|
373
|
+
onfocusfield={focusField}
|
|
374
|
+
/>
|
|
375
|
+
{/if}
|
|
376
|
+
|
|
333
377
|
{#if hasGroups}
|
|
334
378
|
{#each groups as group, _i (_i)}
|
|
335
379
|
<Card.Root class="svadmin-u-6ee2d41e2d2d svadmin-u-438b2237b8d6">
|
|
@@ -341,13 +385,13 @@
|
|
|
341
385
|
<Card.Content class={isCompact ? 'svadmin-u-f0faeb26d656 svadmin-u-9fcd8a13827e svadmin-u-9335c39f6eff' : 'svadmin-u-f0faeb26d656 svadmin-u-7a9aabfcd059 svadmin-u-9fcd8a13827e svadmin-u-050494726fba svadmin-u-9335c39f6eff'}>
|
|
342
386
|
<div class={gridClass}>
|
|
343
387
|
{#each group.fields as field (field.key)}
|
|
344
|
-
<div class={cn(columns > 1 && isFullWidthField(field) && 'svadmin-u-2c955d1b45df', !!form.errors[field.key] && 'svadmin-u-ee1a5af3aa10')}>
|
|
388
|
+
<div data-svadmin-field-key={field.key} class={cn(columns > 1 && isFullWidthField(field) && 'svadmin-u-2c955d1b45df', !!form.errors[field.key] && 'svadmin-u-ee1a5af3aa10')}>
|
|
345
389
|
{#if fieldRenderer}
|
|
346
|
-
{@render fieldRenderer({ field, value:
|
|
390
|
+
{@render fieldRenderer({ field, value: renderedDraft.values[field.key], onchange: fieldChange(field.key) })}
|
|
347
391
|
{:else}
|
|
348
392
|
<FieldRenderer
|
|
349
393
|
{field}
|
|
350
|
-
value={
|
|
394
|
+
value={renderedDraft.values[field.key]}
|
|
351
395
|
onchange={fieldChange(field.key)}
|
|
352
396
|
{density}
|
|
353
397
|
invalid={!!form.errors[field.key]}
|
|
@@ -369,13 +413,13 @@
|
|
|
369
413
|
<Card.Content class={isCompact ? 'svadmin-u-8e63407b5ceb' : 'svadmin-u-f0faeb26d656 svadmin-u-52be28846b5f svadmin-u-9fcd8a13827e svadmin-u-7a9aabfcd059 svadmin-u-0a58453f3755 svadmin-u-050494726fba'}>
|
|
370
414
|
<div class={gridClass} data-svadmin-form-grid data-columns={columns} data-density={density}>
|
|
371
415
|
{#each formFields as field (field.key)}
|
|
372
|
-
<div class={cn(columns > 1 && isFullWidthField(field) && 'svadmin-u-2c955d1b45df', !!form.errors[field.key] && 'svadmin-u-ee1a5af3aa10')}>
|
|
416
|
+
<div data-svadmin-field-key={field.key} class={cn(columns > 1 && isFullWidthField(field) && 'svadmin-u-2c955d1b45df', !!form.errors[field.key] && 'svadmin-u-ee1a5af3aa10')}>
|
|
373
417
|
{#if fieldRenderer}
|
|
374
|
-
{@render fieldRenderer({ field, value:
|
|
418
|
+
{@render fieldRenderer({ field, value: renderedDraft.values[field.key], onchange: fieldChange(field.key) })}
|
|
375
419
|
{:else}
|
|
376
420
|
<FieldRenderer
|
|
377
421
|
{field}
|
|
378
|
-
value={
|
|
422
|
+
value={renderedDraft.values[field.key]}
|
|
379
423
|
onchange={fieldChange(field.key)}
|
|
380
424
|
{density}
|
|
381
425
|
invalid={!!form.errors[field.key]}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import { type ResourceRendering } from '../rendering/index.js';
|
|
1
2
|
import type { FieldDefinition } from '@svadmin/core';
|
|
2
3
|
import type { Snippet } from 'svelte';
|
|
3
4
|
interface Props {
|
|
4
5
|
resourceName: string;
|
|
6
|
+
rendering?: ResourceRendering | undefined;
|
|
5
7
|
id?: string | number;
|
|
6
8
|
mode?: 'create' | 'edit' | 'clone' | 'show';
|
|
7
9
|
density?: 'compact' | 'comfortable';
|
|
@@ -21,6 +23,7 @@ interface Props {
|
|
|
21
23
|
redirect?: 'list' | false;
|
|
22
24
|
onCancel?: () => void;
|
|
23
25
|
onNavigationGuardReady?: (guard: (fn: () => void) => void) => void;
|
|
26
|
+
showErrorSummary?: boolean;
|
|
24
27
|
}
|
|
25
28
|
declare const AutoForm: import("svelte").Component<Props, {}, "">;
|
|
26
29
|
type AutoForm = ReturnType<typeof AutoForm>;
|