@svadmin/ui 0.70.0 → 0.73.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 +40 -25
- package/THIRD_PARTY_NOTICES.md +52 -0
- package/dist/actions.js +1 -1
- package/dist/app.css +7804 -5188
- package/dist/app.theme.css +7738 -5173
- 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.svelte.d.ts +33 -19
- package/dist/component-registry.svelte.js +6 -4
- package/dist/components/AdminApp.svelte +55 -53
- package/dist/components/AdminApp.svelte.d.ts +2 -2
- package/dist/components/ApiSettings.svelte +19 -1
- package/dist/components/AuditLogDrawer.svelte +14 -3
- package/dist/components/AutoForm.svelte +162 -50
- package/dist/components/AutoForm.svelte.d.ts +4 -0
- package/dist/components/AutoTable.svelte +599 -259
- package/dist/components/AutoTable.svelte.d.ts +6 -0
- package/dist/components/BoundRecordDetailDrawer.svelte +172 -0
- package/dist/components/BoundRecordDetailDrawer.svelte.d.ts +11 -0
- package/dist/components/Breadcrumbs.svelte +7 -4
- package/dist/components/CancelTaskButton.svelte +9 -5
- package/dist/components/ColumnHeaderFilter.svelte +4 -3
- package/dist/components/ColumnSettings.svelte +1 -0
- package/dist/components/ComboboxField.svelte +118 -36
- package/dist/components/ComboboxField.svelte.d.ts +5 -4
- package/dist/components/CreatePage.svelte +7 -1
- package/dist/components/CreatePage.svelte.d.ts +2 -0
- package/dist/components/DateRangeInput.svelte +75 -0
- package/dist/components/DateRangeInput.svelte.d.ts +25 -0
- package/dist/components/DateTimeInput.svelte +65 -0
- package/dist/components/DateTimeInput.svelte.d.ts +19 -0
- package/dist/components/DetailDrawer.svelte +4 -0
- package/dist/components/DetailDrawer.svelte.d.ts +1 -0
- package/dist/components/DevTools.svelte +8 -21
- package/dist/components/DraggableGrid.svelte +1 -0
- package/dist/components/DraggableHeader.svelte +5 -9
- package/dist/components/DraggableHeader.svelte.d.ts +43 -18
- package/dist/components/DraggableRowTable.svelte +2 -2
- package/dist/components/DynamicFormList.svelte +17 -17
- package/dist/components/DynamicFormList.svelte.d.ts +2 -1
- package/dist/components/EditPage.svelte +7 -1
- package/dist/components/EditPage.svelte.d.ts +2 -0
- package/dist/components/EditableTable.svelte +4 -0
- package/dist/components/ErrorPage.svelte +3 -1
- package/dist/components/FieldDisplay.svelte +14 -0
- package/dist/components/FieldDisplay.svelte.d.ts +7 -0
- package/dist/components/FieldRenderer.svelte +96 -20
- package/dist/components/FileUpload.svelte +250 -0
- package/dist/components/FileUpload.svelte.d.ts +32 -0
- package/dist/components/FilterBuilder.svelte +236 -268
- package/dist/components/FilterBuilder.svelte.d.ts +3 -0
- package/dist/components/FilterDropdown.svelte.d.ts +1 -1
- package/dist/components/Header.svelte +5 -6
- package/dist/components/ImportWizard.svelte +182 -94
- package/dist/components/InfiniteList.svelte +22 -8
- package/dist/components/InfiniteList.svelte.d.ts +5 -3
- package/dist/components/InlineEdit.svelte +114 -44
- package/dist/components/JsonSchemaForm.svelte +256 -95
- package/dist/components/JsonSchemaForm.svelte.d.ts +12 -1
- package/dist/components/Layout.svelte +20 -17
- package/dist/components/LazyTaskQueueDrawer.svelte +26 -0
- package/dist/components/LazyTaskQueueDrawer.svelte.d.ts +8 -0
- package/dist/components/ListPage.svelte +11 -6
- package/dist/components/ListPage.svelte.d.ts +2 -0
- package/dist/components/LoginPage.svelte +1 -1
- package/dist/components/MasterDetailView.svelte +3 -3
- package/dist/components/MediaLibraryModal.svelte +5 -2
- package/dist/components/MentionsInput.svelte +4 -3
- package/dist/components/MoneyInput.svelte +25 -0
- package/dist/components/MoneyInput.svelte.d.ts +20 -0
- package/dist/components/NavigateToResource.svelte +3 -2
- 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 +4 -3
- package/dist/components/ProfilePage.svelte +2 -2
- package/dist/components/QuickEditDrawer.svelte +42 -0
- package/dist/components/QuickEditDrawer.svelte.d.ts +10 -0
- package/dist/components/RecordDetailDrawer.svelte +16 -108
- package/dist/components/RecordDetailDrawer.svelte.d.ts +2 -0
- package/dist/components/RecordRowActions.svelte +41 -0
- package/dist/components/RecordRowActions.svelte.d.ts +14 -0
- package/dist/components/ResourceAccessGuard.svelte +7 -5
- package/dist/components/ResourceOperationsPage.svelte +25 -19
- package/dist/components/ResourceOperationsPage.svelte.d.ts +5 -1
- package/dist/components/RetryTaskButton.svelte +9 -5
- package/dist/components/RowActions.svelte +5 -3
- package/dist/components/SensitiveDataMask.svelte +3 -3
- package/dist/components/SettingsPage.svelte +1 -1
- package/dist/components/ShowInferencer.svelte +4 -2
- package/dist/components/ShowInferencer.svelte.d.ts +2 -0
- package/dist/components/ShowPage.svelte +49 -39
- package/dist/components/ShowPage.svelte.d.ts +2 -0
- package/dist/components/Sidebar.svelte +15 -13
- package/dist/components/SplitPaneLayout.svelte +4 -2
- package/dist/components/SpreadsheetView.svelte +81 -286
- package/dist/components/StepsForm.svelte +166 -49
- package/dist/components/StepsForm.svelte.d.ts +1 -0
- 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/TaskDetails.svelte +20 -7
- package/dist/components/TaskList.svelte +19 -7
- package/dist/components/TaskQueueDrawer.svelte +92 -37
- package/dist/components/Toast.svelte +4 -2
- package/dist/components/TooltipButton.svelte +1 -1
- package/dist/components/TreeSelect.svelte +212 -30
- package/dist/components/TreeSelect.svelte.d.ts +3 -1
- package/dist/components/ValidatedField.svelte +27 -0
- package/dist/components/ValidatedField.svelte.d.ts +35 -0
- package/dist/components/account/ImportMembersPage.svelte +2 -2
- package/dist/components/account/SecurityLogPage.svelte +3 -1
- package/dist/components/account/SettingsEnterprisePage.svelte +7 -5
- package/dist/components/account/TeamMembersPage.svelte +1 -1
- package/dist/components/auto-table-grid.d.ts +26 -0
- package/dist/components/auto-table-grid.js +1 -0
- package/dist/components/buttons/CloneButton.svelte +6 -4
- package/dist/components/buttons/DeleteButton.svelte +95 -29
- package/dist/components/buttons/DeleteButton.svelte.d.ts +2 -0
- package/dist/components/buttons/EditButton.svelte +6 -4
- package/dist/components/buttons/ExportButton.svelte +22 -4
- package/dist/components/buttons/ImportButton.svelte +83 -38
- package/dist/components/buttons/ImportButton.svelte.d.ts +6 -10
- package/dist/components/buttons/RefreshButton.svelte +48 -8
- package/dist/components/buttons/ShowButton.svelte +6 -4
- package/dist/components/content/ApiKeyList.svelte +3 -1
- package/dist/components/content/ContentPageHeader.svelte +12 -9
- package/dist/components/content/ContentPageShell.svelte +8 -9
- package/dist/components/content/FileBrowser.svelte +35 -0
- package/dist/components/content/FileBrowser.svelte.d.ts +14 -0
- package/dist/components/content/FileList.svelte +3 -1
- package/dist/components/content/MemberList.svelte +3 -1
- package/dist/components/content/MetricBlock.svelte +10 -13
- package/dist/components/content/NetworkTable.svelte +6 -4
- package/dist/components/content/NetworkTable.svelte.d.ts +1 -0
- package/dist/components/content/PageToolbar.svelte +6 -10
- package/dist/components/content/SectionHeader.svelte +8 -13
- package/dist/components/content/SecurityEventTable.svelte +3 -1
- 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/StatusTabs.svelte +2 -2
- 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/fieldComponentMap.d.ts +18 -13
- package/dist/components/fieldComponentMap.js +100 -47
- package/dist/components/fields/AvatarField.svelte +1 -1
- package/dist/components/fields/ChoiceField.svelte +16 -0
- package/dist/components/fields/ChoiceField.svelte.d.ts +10 -0
- package/dist/components/fields/CodeField.svelte +11 -12
- package/dist/components/fields/CodeField.svelte.d.ts +1 -1
- package/dist/components/fields/DateField.svelte +4 -3
- package/dist/components/fields/DateRangeField.svelte +2 -4
- package/dist/components/fields/ImageField.svelte +3 -1
- package/dist/components/fields/ImagesField.svelte +23 -0
- package/dist/components/fields/ImagesField.svelte.d.ts +6 -0
- package/dist/components/fields/JsonField.svelte +19 -13
- package/dist/components/fields/PasswordField.svelte +5 -0
- package/dist/components/fields/PasswordField.svelte.d.ts +6 -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/fields/json-value.d.ts +11 -0
- package/dist/components/fields/json-value.js +28 -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/profile/ActivityTimeline.svelte +2 -2
- package/dist/components/record-detail.svelte.d.ts +19 -0
- package/dist/components/record-detail.svelte.js +34 -0
- package/dist/components/saved-list-views.js +29 -29
- 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 +13 -0
- package/dist/components/table-contract.js +42 -0
- package/dist/components/task-utils.js +4 -2
- package/dist/components/ui/alert/alert-variants.d.ts +2 -3
- package/dist/components/ui/alert/alert-variants.js +1 -2
- package/dist/components/ui/alert/alert.svelte +4 -5
- package/dist/components/ui/alert/alert.svelte.d.ts +3 -8
- package/dist/components/ui/alert/index.js +0 -2
- package/dist/components/ui/avatar/avatar-variants.d.ts +2 -3
- package/dist/components/ui/avatar/avatar-variants.js +1 -2
- package/dist/components/ui/avatar/avatar.svelte +5 -6
- package/dist/components/ui/avatar/avatar.svelte.d.ts +3 -8
- package/dist/components/ui/badge/badge-variants.d.ts +2 -3
- package/dist/components/ui/badge/badge-variants.js +3 -2
- package/dist/components/ui/badge/badge.svelte +4 -5
- package/dist/components/ui/badge/badge.svelte.d.ts +3 -8
- package/dist/components/ui/badge/index.js +0 -2
- package/dist/components/ui/button/button-variants.d.ts +2 -3
- package/dist/components/ui/button/button-variants.js +5 -3
- package/dist/components/ui/button/button.svelte +100 -44
- package/dist/components/ui/button/button.svelte.d.ts +8 -12
- package/dist/components/ui/button/index.js +0 -2
- package/dist/components/ui/command/command-dialog.svelte +3 -1
- package/dist/components/ui/command/command-dialog.svelte.d.ts +1 -1
- package/dist/components/ui/command/command-group.svelte +4 -2
- package/dist/components/ui/command/command-item.svelte +4 -2
- package/dist/components/ui/command/command-separator.svelte +3 -1
- package/dist/components/ui/command/index.d.ts +5 -5
- package/dist/components/ui/input/input.svelte +41 -24
- package/dist/components/ui/input/input.svelte.d.ts +5 -4
- package/dist/components/ui/sheet/sheet.svelte +9 -3
- package/dist/components/ui/sheet/sheet.svelte.d.ts +1 -0
- package/dist/components/ui/textarea/textarea.svelte +2 -1
- package/dist/components/ui/tooltip/tooltip.svelte +4 -2
- package/dist/components.css +3079 -0
- package/dist/design-contract.d.ts +13 -0
- package/dist/design-contract.js +11 -0
- package/dist/design-system.d.ts +15 -0
- package/dist/design-system.js +7 -0
- package/dist/index.d.ts +15 -1
- package/dist/index.js +9 -0
- package/dist/inline-value.d.ts +5 -0
- package/dist/inline-value.js +24 -0
- package/dist/numeric-input.d.ts +2 -0
- package/dist/numeric-input.js +9 -0
- package/dist/page-chrome.css +12 -49
- package/dist/recipes.d.ts +4 -0
- package/dist/recipes.js +4 -0
- package/dist/rendering/index.d.ts +87 -0
- package/dist/rendering/index.js +117 -0
- package/dist/styled-system/css/conditions.js +36 -0
- package/dist/styled-system/css/css.d.ts +22 -0
- package/dist/styled-system/css/css.js +45 -0
- package/dist/styled-system/css/cva.d.ts +6 -0
- package/dist/styled-system/css/cva.js +87 -0
- package/dist/styled-system/css/cx.d.ts +5 -0
- package/dist/styled-system/css/cx.js +15 -0
- package/dist/styled-system/css/index.d.ts +5 -0
- package/dist/styled-system/css/index.js +4 -0
- package/dist/styled-system/css/sva.d.ts +4 -0
- package/dist/styled-system/css/sva.js +46 -0
- package/dist/styled-system/helpers.js +316 -0
- package/dist/styled-system/patterns/aspect-ratio.d.ts +20 -0
- package/dist/styled-system/patterns/aspect-ratio.js +38 -0
- package/dist/styled-system/patterns/bleed.d.ts +21 -0
- package/dist/styled-system/patterns/bleed.js +24 -0
- package/dist/styled-system/patterns/box.d.ts +20 -0
- package/dist/styled-system/patterns/box.js +15 -0
- package/dist/styled-system/patterns/center.d.ts +20 -0
- package/dist/styled-system/patterns/center.js +21 -0
- package/dist/styled-system/patterns/circle.d.ts +20 -0
- package/dist/styled-system/patterns/circle.js +25 -0
- package/dist/styled-system/patterns/container.d.ts +20 -0
- package/dist/styled-system/patterns/container.js +21 -0
- package/dist/styled-system/patterns/cq.d.ts +21 -0
- package/dist/styled-system/patterns/cq.js +21 -0
- package/dist/styled-system/patterns/divider.d.ts +22 -0
- package/dist/styled-system/patterns/divider.js +25 -0
- package/dist/styled-system/patterns/flex.d.ts +26 -0
- package/dist/styled-system/patterns/flex.js +26 -0
- package/dist/styled-system/patterns/float.d.ts +23 -0
- package/dist/styled-system/patterns/float.js +52 -0
- package/dist/styled-system/patterns/grid-item.d.ts +25 -0
- package/dist/styled-system/patterns/grid-item.js +25 -0
- package/dist/styled-system/patterns/grid.d.ts +24 -0
- package/dist/styled-system/patterns/grid.js +27 -0
- package/dist/styled-system/patterns/hstack.d.ts +21 -0
- package/dist/styled-system/patterns/hstack.js +24 -0
- package/dist/styled-system/patterns/index.d.ts +21 -0
- package/dist/styled-system/patterns/index.js +20 -0
- package/dist/styled-system/patterns/link-overlay.d.ts +20 -0
- package/dist/styled-system/patterns/link-overlay.js +24 -0
- package/dist/styled-system/patterns/spacer.d.ts +20 -0
- package/dist/styled-system/patterns/spacer.js +25 -0
- package/dist/styled-system/patterns/square.d.ts +20 -0
- package/dist/styled-system/patterns/square.js +24 -0
- package/dist/styled-system/patterns/stack.d.ts +23 -0
- package/dist/styled-system/patterns/stack.js +24 -0
- package/dist/styled-system/patterns/visually-hidden.d.ts +20 -0
- package/dist/styled-system/patterns/visually-hidden.js +18 -0
- package/dist/styled-system/patterns/vstack.d.ts +21 -0
- package/dist/styled-system/patterns/vstack.js +24 -0
- package/dist/styled-system/patterns/wrap.d.ts +24 -0
- package/dist/styled-system/patterns/wrap.js +25 -0
- package/dist/styled-system/recipes/content-header.d.ts +31 -0
- package/dist/styled-system/recipes/content-header.js +65 -0
- package/dist/styled-system/recipes/content-page.d.ts +34 -0
- package/dist/styled-system/recipes/content-page.js +43 -0
- package/dist/styled-system/recipes/create-recipe.js +82 -0
- package/dist/styled-system/recipes/index.d.ts +17 -0
- package/dist/styled-system/recipes/index.js +16 -0
- package/dist/styled-system/recipes/metric-block.d.ts +34 -0
- package/dist/styled-system/recipes/metric-block.js +76 -0
- package/dist/styled-system/recipes/product-list.d.ts +31 -0
- package/dist/styled-system/recipes/product-list.js +73 -0
- package/dist/styled-system/recipes/product-section.d.ts +31 -0
- package/dist/styled-system/recipes/product-section.js +49 -0
- package/dist/styled-system/recipes/product-settings-row.d.ts +34 -0
- package/dist/styled-system/recipes/product-settings-row.js +58 -0
- package/dist/styled-system/recipes/product-settings.d.ts +31 -0
- package/dist/styled-system/recipes/product-settings.js +57 -0
- package/dist/styled-system/recipes/product-status.d.ts +34 -0
- package/dist/styled-system/recipes/product-status.js +45 -0
- package/dist/styled-system/recipes/product-toolbar.d.ts +31 -0
- package/dist/styled-system/recipes/product-toolbar.js +41 -0
- package/dist/styled-system/recipes/product-workspace.d.ts +34 -0
- package/dist/styled-system/recipes/product-workspace.js +58 -0
- package/dist/styled-system/recipes/surface-metric.d.ts +38 -0
- package/dist/styled-system/recipes/surface-metric.js +63 -0
- package/dist/styled-system/recipes/surface-table.d.ts +34 -0
- package/dist/styled-system/recipes/surface-table.js +62 -0
- package/dist/styled-system/recipes/ui-badge.d.ts +31 -0
- package/dist/styled-system/recipes/ui-badge.js +38 -0
- package/dist/styled-system/recipes/ui-button.d.ts +32 -0
- package/dist/styled-system/recipes/ui-button.js +43 -0
- package/dist/styled-system/recipes/ui-input.d.ts +31 -0
- package/dist/styled-system/recipes/ui-input.js +49 -0
- package/dist/styled-system/recipes/ui-textarea.d.ts +31 -0
- package/dist/styled-system/recipes/ui-textarea.js +24 -0
- package/dist/styled-system/styles.css +1257 -0
- package/dist/styled-system/tokens/index.d.ts +9 -0
- package/dist/styled-system/tokens/index.js +268 -0
- package/dist/styled-system/tokens/tokens.d.ts +36 -0
- package/dist/styled-system/types/composition.d.ts +227 -0
- package/dist/styled-system/types/conditions.d.ts +236 -0
- package/dist/styled-system/types/csstype.d.ts +22570 -0
- package/dist/styled-system/types/index.d.ts +6 -0
- package/dist/styled-system/types/parts.d.ts +8 -0
- package/dist/styled-system/types/pattern.d.ts +78 -0
- package/dist/styled-system/types/prop-type.d.ts +223 -0
- package/dist/styled-system/types/recipe.d.ts +181 -0
- package/dist/styled-system/types/selectors.d.ts +59 -0
- package/dist/styled-system/types/static-css.d.ts +56 -0
- package/dist/styled-system/types/style-props.d.ts +8088 -0
- package/dist/styled-system/types/system-types.d.ts +151 -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/styles/recipes.css +1262 -0
- package/dist/types.d.ts +3 -3
- package/dist/utils.d.ts +1 -1
- package/dist/utils.js +1 -1
- package/package.json +38 -14
- package/styles-compatibility.json +12 -0
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import {
|
|
2
|
+
import { captureAdminContext, captureAuthSession, useCan, useImport, useResourceContract } from '@svadmin/core';
|
|
3
|
+
import { untrack } from 'svelte';
|
|
4
|
+
import { definedReactiveOptions } from '@svadmin/core/options';
|
|
3
5
|
import { useTranslation } from '@svadmin/core/i18n';
|
|
4
6
|
import { parseCSV, toCsv } from '@svadmin/core';
|
|
5
7
|
import * as Dialog from './ui/dialog/index.js';
|
|
@@ -23,64 +25,118 @@
|
|
|
23
25
|
}: Props = $props();
|
|
24
26
|
|
|
25
27
|
const i18n = useTranslation();
|
|
26
|
-
const
|
|
27
|
-
const
|
|
28
|
+
const context = captureAdminContext();
|
|
29
|
+
const binding = useResourceContract(() => resourceName);
|
|
30
|
+
const resource = $derived(context.getResource(resourceName));
|
|
31
|
+
const can = useCan(() => ({ resource: resourceName, action: 'import' }));
|
|
32
|
+
const session = $derived(captureAuthSession(context.authProvider));
|
|
33
|
+
const allowed = $derived(can.allowed === true && resource.canCreate !== false && session.available);
|
|
34
|
+
const scope = $derived({
|
|
35
|
+
contract: binding.resource, provider: context.providers?.[binding.dataProviderName],
|
|
36
|
+
tenant: context.tenantCacheKey?.__svadminTenant, meta: binding.meta,
|
|
37
|
+
auth: context.authProvider, router: context.routerProvider, session, allowed,
|
|
38
|
+
});
|
|
28
39
|
const availableFields = $derived(
|
|
29
40
|
resource.fields.filter((f) => f.key !== (resource.primaryKey ?? 'id') && f.showInForm !== false)
|
|
30
41
|
);
|
|
31
42
|
|
|
32
43
|
let currentStep = $state<1 | 2 | 3>(1);
|
|
33
44
|
let fileName = $state('');
|
|
45
|
+
let selectedFile = $state<File | null>(null);
|
|
34
46
|
let rawHeaders = $state<string[]>([]);
|
|
35
|
-
let rawRows = $state<
|
|
47
|
+
let rawRows = $state<unknown[][]>([]);
|
|
36
48
|
let columnMapping = $state<Record<string, string>>({}); // header -> fieldKey or ''
|
|
49
|
+
let fileError = $state<string | null>(null);
|
|
50
|
+
let importError = $state<string | null>(null);
|
|
51
|
+
let parseToken = 0;
|
|
52
|
+
let mounted = true;
|
|
37
53
|
|
|
38
|
-
let
|
|
39
|
-
let processedCount = $state(0);
|
|
54
|
+
let importResult = $state<{ succeeded: number; failed: number } | null>(null);
|
|
40
55
|
let succeededCount = $state(0);
|
|
41
56
|
let failedRecords = $state<Array<{ row: Record<string, unknown>; error: string }>>([]);
|
|
42
57
|
|
|
58
|
+
const importer = useImport(definedReactiveOptions({
|
|
59
|
+
get resource() { return binding.resource; },
|
|
60
|
+
get dataProviderName() { return binding.dataProviderName; },
|
|
61
|
+
get batchSize() { return batchSize; },
|
|
62
|
+
get enabled() { return open && allowed; },
|
|
63
|
+
mapData: mapRow,
|
|
64
|
+
}));
|
|
65
|
+
const isImporting = $derived(importer.isLoading);
|
|
66
|
+
const processedCount = $derived(importer.progress.processedAmount);
|
|
67
|
+
const totalCount = $derived(importer.progress.totalAmount || rawRows.length);
|
|
43
68
|
const progressPercent = $derived(
|
|
44
|
-
|
|
69
|
+
totalCount > 0 ? Math.min(100, Math.round((processedCount / totalCount) * 100)) : 0
|
|
45
70
|
);
|
|
46
71
|
|
|
47
|
-
async function handleFileSelect(
|
|
48
|
-
|
|
49
|
-
const
|
|
50
|
-
const
|
|
72
|
+
async function handleFileSelect(file: File) {
|
|
73
|
+
if (!open || !allowed || isImporting) return;
|
|
74
|
+
const origin = scope;
|
|
75
|
+
const token = ++parseToken;
|
|
76
|
+
fileError = null;
|
|
77
|
+
importError = null;
|
|
78
|
+
selectedFile = null;
|
|
79
|
+
fileName = file.name;
|
|
80
|
+
rawHeaders = [];
|
|
81
|
+
rawRows = [];
|
|
82
|
+
columnMapping = {};
|
|
83
|
+
try {
|
|
84
|
+
const text = await file.text();
|
|
85
|
+
if (!current(origin, token)) return;
|
|
86
|
+
const cleanText = text.charCodeAt(0) === 0xfeff ? text.slice(1) : text;
|
|
51
87
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
rawRows = json.map((item) => keys.map((k) => String(item[k] ?? '')));
|
|
88
|
+
if (file.name.toLowerCase().endsWith('.json')) {
|
|
89
|
+
const json: unknown = JSON.parse(cleanText);
|
|
90
|
+
if (!Array.isArray(json) || json.length === 0 || json.some((item) => (
|
|
91
|
+
typeof item !== 'object' || item === null || Array.isArray(item)
|
|
92
|
+
))) {
|
|
93
|
+
throw new Error('The JSON file must contain a non-empty array of records.');
|
|
59
94
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
if (
|
|
66
|
-
|
|
67
|
-
|
|
95
|
+
const records = json as Record<string, unknown>[];
|
|
96
|
+
const keys = [...new Set(records.flatMap(item => Object.keys(item)))];
|
|
97
|
+
if (keys.length === 0) throw new Error('The import file has no columns.');
|
|
98
|
+
rawHeaders = keys;
|
|
99
|
+
rawRows = records.map((item) => keys.map((key) => item[key]));
|
|
100
|
+
} else if (file.name.toLowerCase().endsWith('.csv')) {
|
|
101
|
+
const rows = parseCSV(cleanText);
|
|
102
|
+
const firstRow = rows[0];
|
|
103
|
+
if (!firstRow || firstRow.length === 0 || firstRow.every((cell) => !cell.trim())) {
|
|
104
|
+
throw new Error('The CSV file has no header row.');
|
|
105
|
+
}
|
|
106
|
+
if (firstRow.some(header => !header.trim()) || new Set(firstRow).size !== firstRow.length) {
|
|
107
|
+
throw new Error('CSV column names must be non-empty and unique.');
|
|
108
|
+
}
|
|
109
|
+
const records = rows.slice(1).filter((r: string[]) =>
|
|
110
|
+
r.some((cell: string) => cell.trim().length > 0));
|
|
111
|
+
if (records.length === 0) throw new Error('The import file has no records.');
|
|
112
|
+
if (records.some((row) => row.length !== firstRow.length)) {
|
|
113
|
+
throw new Error('The CSV file contains rows with inconsistent column counts.');
|
|
114
|
+
}
|
|
115
|
+
rawHeaders = firstRow;
|
|
116
|
+
rawRows = records;
|
|
117
|
+
} else {
|
|
118
|
+
throw new Error('Only CSV and JSON files are supported.');
|
|
68
119
|
}
|
|
69
|
-
}
|
|
70
120
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
(
|
|
77
|
-
f
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
121
|
+
if (!current(origin, token)) return;
|
|
122
|
+
selectedFile = file;
|
|
123
|
+
const initialMapping: Record<string, string> = {};
|
|
124
|
+
for (const h of rawHeaders) {
|
|
125
|
+
const normalized = h.toLowerCase().trim().replace(/[-_]/g, '');
|
|
126
|
+
const match = availableFields.find(
|
|
127
|
+
(f) =>
|
|
128
|
+
f.key.toLowerCase().replace(/[-_]/g, '') === normalized ||
|
|
129
|
+
f.label.toLowerCase().replace(/[-_]/g, '') === normalized
|
|
130
|
+
);
|
|
131
|
+
initialMapping[h] = match ? match.key : '';
|
|
132
|
+
}
|
|
133
|
+
columnMapping = initialMapping;
|
|
134
|
+
currentStep = 2;
|
|
135
|
+
} catch (error) {
|
|
136
|
+
if (!current(origin, token)) return;
|
|
137
|
+
fileError = error instanceof Error ? error.message : 'Unable to read the import file.';
|
|
138
|
+
currentStep = 1;
|
|
81
139
|
}
|
|
82
|
-
columnMapping = initialMapping;
|
|
83
|
-
currentStep = 2;
|
|
84
140
|
}
|
|
85
141
|
|
|
86
142
|
function handleDrop(e: DragEvent) {
|
|
@@ -90,63 +146,67 @@
|
|
|
90
146
|
}
|
|
91
147
|
}
|
|
92
148
|
|
|
149
|
+
function mapRow(row: Record<string, unknown>): Record<string, unknown> {
|
|
150
|
+
const record: Record<string, unknown> = {};
|
|
151
|
+
rawHeaders.forEach((header) => {
|
|
152
|
+
const targetFieldKey = columnMapping[header];
|
|
153
|
+
if (!targetFieldKey) return;
|
|
154
|
+
const fieldDef = availableFields.find((f) => f.key === targetFieldKey);
|
|
155
|
+
let val: unknown = row[header];
|
|
156
|
+
if (typeof val === 'string') {
|
|
157
|
+
if (fieldDef?.type === 'number' || fieldDef?.type === 'currency' || fieldDef?.type === 'percent') {
|
|
158
|
+
const num = val.trim() === '' ? NaN : Number(val);
|
|
159
|
+
val = val.trim() === '' ? undefined : Number.isFinite(num) ? num : val;
|
|
160
|
+
} else if (fieldDef?.type === 'boolean') {
|
|
161
|
+
const normalized = val.trim().toLowerCase();
|
|
162
|
+
if (['true', '1', 'yes', '是'].includes(normalized)) val = true;
|
|
163
|
+
else if (['false', '0', 'no', '否'].includes(normalized)) val = false;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
if (val !== undefined) {
|
|
167
|
+
Object.defineProperty(record, targetFieldKey, { value: val, enumerable: true });
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
return record;
|
|
171
|
+
}
|
|
172
|
+
|
|
93
173
|
async function startImport() {
|
|
174
|
+
if (!selectedFile || rawRows.length === 0 || isImporting || !open || !allowed) return;
|
|
175
|
+
const targets = Object.values(columnMapping).filter(Boolean);
|
|
176
|
+
if (targets.length === 0 || new Set(targets).size !== targets.length) {
|
|
177
|
+
fileError = 'Map at least one column, and use each target field only once.';
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
const origin = scope;
|
|
181
|
+
const token = parseToken;
|
|
182
|
+
const notifySuccess = onSuccess;
|
|
94
183
|
currentStep = 3;
|
|
95
|
-
isImporting = true;
|
|
96
|
-
processedCount = 0;
|
|
97
184
|
succeededCount = 0;
|
|
98
185
|
failedRecords = [];
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
} else if (fieldDef?.type === 'boolean') {
|
|
115
|
-
val = val === 'true' || val === '1' || val === 'yes' || val === '是';
|
|
116
|
-
}
|
|
117
|
-
record[targetFieldKey] = val;
|
|
118
|
-
}
|
|
119
|
-
});
|
|
120
|
-
recordsToImport.push(record);
|
|
186
|
+
importResult = null;
|
|
187
|
+
importError = null;
|
|
188
|
+
try {
|
|
189
|
+
const result = await importer.handleChange({ file: selectedFile });
|
|
190
|
+
if (!current(origin, token)) return;
|
|
191
|
+
succeededCount = result.succeeded.length;
|
|
192
|
+
failedRecords = result.errored.map(item => ({
|
|
193
|
+
row: item.request as Record<string, unknown>,
|
|
194
|
+
error: item.error.message,
|
|
195
|
+
}));
|
|
196
|
+
importResult = { succeeded: succeededCount, failed: failedRecords.length };
|
|
197
|
+
} catch (error) {
|
|
198
|
+
if (!current(origin, token)) return;
|
|
199
|
+
importError = error instanceof Error ? error.message : 'Import failed.';
|
|
200
|
+
importResult = null;
|
|
121
201
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
const batch = recordsToImport.slice(i, i + batchSize);
|
|
126
|
-
if (provider.createMany) {
|
|
127
|
-
try {
|
|
128
|
-
await provider.createMany({ resource: resourceName, variables: batch });
|
|
129
|
-
succeededCount += batch.length;
|
|
130
|
-
} catch (err) {
|
|
131
|
-
batch.forEach((item) => {
|
|
132
|
-
failedRecords.push({ row: item, error: err instanceof Error ? err.message : String(err) });
|
|
133
|
-
});
|
|
134
|
-
}
|
|
135
|
-
} else {
|
|
136
|
-
for (const item of batch) {
|
|
137
|
-
try {
|
|
138
|
-
await provider.create({ resource: resourceName, variables: item });
|
|
139
|
-
succeededCount++;
|
|
140
|
-
} catch (err) {
|
|
141
|
-
failedRecords.push({ row: item, error: err instanceof Error ? err.message : String(err) });
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
processedCount = Math.min(recordsToImport.length, i + batch.length);
|
|
202
|
+
if (importResult) {
|
|
203
|
+
try { notifySuccess?.(importResult); }
|
|
204
|
+
catch { /* 消费方回调失败不能把已完成的写入改判为导入失败。 */ }
|
|
146
205
|
}
|
|
206
|
+
}
|
|
147
207
|
|
|
148
|
-
|
|
149
|
-
|
|
208
|
+
function current(origin: typeof scope, token: number): boolean {
|
|
209
|
+
return mounted && open && allowed && origin === scope && origin.session.isCurrent() && token === parseToken;
|
|
150
210
|
}
|
|
151
211
|
|
|
152
212
|
function downloadErrors() {
|
|
@@ -166,16 +226,27 @@
|
|
|
166
226
|
}
|
|
167
227
|
|
|
168
228
|
function reset() {
|
|
229
|
+
parseToken += 1;
|
|
169
230
|
currentStep = 1;
|
|
170
231
|
fileName = '';
|
|
232
|
+
selectedFile = null;
|
|
171
233
|
rawHeaders = [];
|
|
172
234
|
rawRows = [];
|
|
173
235
|
columnMapping = {};
|
|
174
|
-
processedCount = 0;
|
|
175
236
|
succeededCount = 0;
|
|
176
237
|
failedRecords = [];
|
|
177
|
-
|
|
238
|
+
importResult = null;
|
|
239
|
+
fileError = null;
|
|
240
|
+
importError = null;
|
|
241
|
+
importer.reset();
|
|
178
242
|
}
|
|
243
|
+
|
|
244
|
+
$effect.pre(() => {
|
|
245
|
+
void scope;
|
|
246
|
+
void open;
|
|
247
|
+
untrack(reset);
|
|
248
|
+
});
|
|
249
|
+
$effect(() => () => { mounted = false; parseToken += 1; });
|
|
179
250
|
</script>
|
|
180
251
|
|
|
181
252
|
{#if open}
|
|
@@ -198,6 +269,9 @@
|
|
|
198
269
|
</div>
|
|
199
270
|
|
|
200
271
|
<!-- Step 1: Upload -->
|
|
272
|
+
{#if !allowed}
|
|
273
|
+
<p role="status">{i18n.t('common.operationFailed', { defaultValue: 'Import is unavailable.' })}</p>
|
|
274
|
+
{/if}
|
|
201
275
|
{#if currentStep === 1}
|
|
202
276
|
<div
|
|
203
277
|
class="svadmin-u-65935df577ba svadmin-u-a29b7a649c77 svadmin-u-c9ed8c5f79ae svadmin-u-8b9d5d768973 svadmin-u-a217b4eaa918 svadmin-u-845f53365c8d svadmin-u-ca6bf63030aa svadmin-u-ceb69a6b0e5f svadmin-u-34516836730d svadmin-u-967d113a1451"
|
|
@@ -217,6 +291,7 @@
|
|
|
217
291
|
<input
|
|
218
292
|
type="file"
|
|
219
293
|
accept=".csv,.json"
|
|
294
|
+
disabled={!allowed}
|
|
220
295
|
class="svadmin-u-99d72c7fc3e2"
|
|
221
296
|
onchange={(e) => {
|
|
222
297
|
const target = e.currentTarget;
|
|
@@ -227,12 +302,16 @@
|
|
|
227
302
|
{i18n.t('common.selectFile', { defaultValue: 'Browse File' })}
|
|
228
303
|
</span>
|
|
229
304
|
</label>
|
|
305
|
+
{#if fileError}
|
|
306
|
+
<p role="alert">{fileError}</p>
|
|
307
|
+
{/if}
|
|
230
308
|
</div>
|
|
231
309
|
{/if}
|
|
232
310
|
|
|
233
311
|
<!-- Step 2: Column Mapping -->
|
|
234
312
|
{#if currentStep === 2}
|
|
235
313
|
<div class="svadmin-u-3e7ce58d64fa">
|
|
314
|
+
{#if fileError}<p role="alert">{fileError}</p>{/if}
|
|
236
315
|
<div class="svadmin-u-60fbb7713999 svadmin-u-3960ffc248d9 svadmin-u-8ef2268efbbc svadmin-u-359090c2d529 svadmin-u-bfa603190748 svadmin-u-2859c861d7de svadmin-u-9fe52d5d506c svadmin-u-5f22e64f2282 svadmin-u-ca6bcd4b6f3f svadmin-u-05faf5c801ff">
|
|
237
316
|
<span>{i18n.t('common.detectedRows', { defaultValue: 'Detected' })}: <strong class="svadmin-u-d4108abe6359">{rawRows.length}</strong> {i18n.t('common.records', { defaultValue: 'records' })}</span>
|
|
238
317
|
<Badge variant="secondary" class="svadmin-u-d058ca6de60f svadmin-u-0e65706bcccd">{fileName}</Badge>
|
|
@@ -251,8 +330,13 @@
|
|
|
251
330
|
</div>
|
|
252
331
|
<div class="svadmin-u-74b2435a1d40 svadmin-u-012fbd121f37">
|
|
253
332
|
<select
|
|
333
|
+
aria-label={`Map ${header}`}
|
|
254
334
|
class="svadmin-u-ed8a5df7b2fb svadmin-u-6da6a3c3f741 svadmin-u-421ac2be5045 svadmin-u-ca6bcd4b6f3f svadmin-u-e5795dad4d22 svadmin-u-e6f9e383a762 svadmin-u-d5eab218aa34 svadmin-u-359090c2d529 svadmin-u-f10f771f87e9 svadmin-u-3e94a98e1466 svadmin-u-9c1295a6914a"
|
|
255
|
-
|
|
335
|
+
value={columnMapping[header]}
|
|
336
|
+
onchange={(event) => {
|
|
337
|
+
columnMapping = { ...columnMapping, [header]: event.currentTarget.value };
|
|
338
|
+
fileError = null;
|
|
339
|
+
}}
|
|
256
340
|
>
|
|
257
341
|
<option value="">— {i18n.t('common.ignoreColumn', { defaultValue: 'Ignore' })} —</option>
|
|
258
342
|
{#each availableFields as field (field.key)}
|
|
@@ -271,7 +355,7 @@
|
|
|
271
355
|
<ArrowLeft class="svadmin-u-7fc7f732bf7e svadmin-u-bf600f8e029c svadmin-u-618162408e7a" />
|
|
272
356
|
{i18n.t('common.back', { defaultValue: 'Back' })}
|
|
273
357
|
</Button>
|
|
274
|
-
<Button size="sm" onclick={startImport}>
|
|
358
|
+
<Button size="sm" disabled={!allowed || isImporting} onclick={startImport}>
|
|
275
359
|
{i18n.t('common.startImport', { defaultValue: 'Start Import' })}
|
|
276
360
|
<ArrowRight class="svadmin-u-7fc7f732bf7e svadmin-u-bf600f8e029c svadmin-u-f58b02572ab2" />
|
|
277
361
|
</Button>
|
|
@@ -284,7 +368,7 @@
|
|
|
284
368
|
<div class="svadmin-u-b43b4c086d9a svadmin-u-03b4dd7f172b">
|
|
285
369
|
<div class="svadmin-u-6f7e013d6499">
|
|
286
370
|
<div class="svadmin-u-60fbb7713999 svadmin-u-3960ffc248d9 svadmin-u-8ef2268efbbc svadmin-u-359090c2d529">
|
|
287
|
-
<span class="svadmin-u-bfa603190748">{isImporting ? i18n.t('common.importing', { defaultValue: 'Importing...' }) : i18n.t('common.completed', { defaultValue: 'Completed' })}</span>
|
|
371
|
+
<span class="svadmin-u-bfa603190748">{isImporting ? i18n.t('common.importing', { defaultValue: 'Importing...' }) : importError ? i18n.t('common.operationFailed', { defaultValue: 'Import failed' }) : i18n.t('common.completed', { defaultValue: 'Completed' })}</span>
|
|
288
372
|
<span class="svadmin-u-e83a7042bc91 svadmin-u-d4108abe6359 svadmin-u-3032cae0badb">{progressPercent}%</span>
|
|
289
373
|
</div>
|
|
290
374
|
<Progress value={progressPercent} class="svadmin-u-2f2a842e50fa" />
|
|
@@ -301,6 +385,10 @@
|
|
|
301
385
|
</div>
|
|
302
386
|
</div>
|
|
303
387
|
|
|
388
|
+
{#if importError}
|
|
389
|
+
<p role="alert">{importError}</p>
|
|
390
|
+
{/if}
|
|
391
|
+
|
|
304
392
|
{#if failedRecords.length > 0}
|
|
305
393
|
<div class="svadmin-u-60fbb7713999 svadmin-u-3960ffc248d9 svadmin-u-8ef2268efbbc svadmin-u-eb6e8b881acd svadmin-u-5f22e64f2282 svadmin-u-7a0854fdbc30 svadmin-u-ca6bcd4b6f3f svadmin-u-e09a917c4c3b svadmin-u-359090c2d529">
|
|
306
394
|
<div class="svadmin-u-60fbb7713999 svadmin-u-3960ffc248d9 svadmin-u-77a2a20e90d4 svadmin-u-811148b13d1e">
|
|
@@ -1,23 +1,26 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { definedReactiveOptions } from '@svadmin/core/options';
|
|
3
|
+
|
|
2
4
|
import { fade } from 'svelte/transition';
|
|
3
|
-
import { useInfiniteList } from '@svadmin/core';
|
|
5
|
+
import { useInfiniteList, useResourceContract } from '@svadmin/core';
|
|
4
6
|
import type { BaseRecord, Sort, Filter } from '@svadmin/core';
|
|
5
7
|
import type { Snippet } from 'svelte';
|
|
6
8
|
import { useTranslation } from '@svadmin/core/i18n';
|
|
7
9
|
|
|
8
10
|
import { Skeleton } from './ui/skeleton/index.js';
|
|
9
|
-
import { Loader2 } from '@lucide/svelte';
|
|
11
|
+
import { Loader2, RotateCw } from '@lucide/svelte';
|
|
12
|
+
import { Button } from './ui/button/index.js';
|
|
10
13
|
import { intersect } from '../actions.js';
|
|
11
14
|
|
|
12
15
|
const i18n = useTranslation();
|
|
13
16
|
|
|
14
|
-
interface Props
|
|
17
|
+
interface Props {
|
|
15
18
|
resource: string;
|
|
16
19
|
pageSize?: number;
|
|
17
20
|
sorters?: Sort[];
|
|
18
21
|
filters?: Filter[];
|
|
19
22
|
/** Render each item */
|
|
20
|
-
children: Snippet<[{ item:
|
|
23
|
+
children: Snippet<[{ item: BaseRecord & { id: string | number }; index: number }]>;
|
|
21
24
|
/** Custom empty state */
|
|
22
25
|
empty?: Snippet;
|
|
23
26
|
/** Custom loading skeleton */
|
|
@@ -34,15 +37,18 @@
|
|
|
34
37
|
loadingSkeleton,
|
|
35
38
|
}: Props = $props();
|
|
36
39
|
|
|
37
|
-
const
|
|
38
|
-
|
|
40
|
+
const binding = useResourceContract(() => resource);
|
|
41
|
+
const { query } = useInfiniteList(definedReactiveOptions({
|
|
42
|
+
get resource() { return binding.resource; },
|
|
43
|
+
get dataProviderName() { return binding.dataProviderName; },
|
|
44
|
+
get meta() { return binding.meta; },
|
|
39
45
|
get pagination() { return { pageSize }; },
|
|
40
46
|
get sorters() { return sorters; },
|
|
41
47
|
get filters() { return filters; },
|
|
42
|
-
});
|
|
48
|
+
}));
|
|
43
49
|
|
|
44
50
|
const allItems = $derived(
|
|
45
|
-
|
|
51
|
+
query.data?.pages.flatMap(p => p.data) ?? []
|
|
46
52
|
);
|
|
47
53
|
|
|
48
54
|
const hasNextPage = $derived(query.hasNextPage ?? false);
|
|
@@ -66,6 +72,14 @@
|
|
|
66
72
|
{/each}
|
|
67
73
|
</div>
|
|
68
74
|
{/if}
|
|
75
|
+
{:else if query.isError}
|
|
76
|
+
<div role="alert">
|
|
77
|
+
<p>{i18n.t('common.error')}</p>
|
|
78
|
+
<Button variant="outline" disabled={query.isFetching} onclick={() => query.refetch()}>
|
|
79
|
+
<RotateCw />
|
|
80
|
+
{i18n.t('common.retry')}
|
|
81
|
+
</Button>
|
|
82
|
+
</div>
|
|
69
83
|
{:else if allItems.length === 0}
|
|
70
84
|
{#if empty}
|
|
71
85
|
{@render empty()}
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import type { BaseRecord, Sort, Filter } from '@svadmin/core';
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
|
-
interface Props
|
|
3
|
+
interface Props {
|
|
4
4
|
resource: string;
|
|
5
5
|
pageSize?: number;
|
|
6
6
|
sorters?: Sort[];
|
|
7
7
|
filters?: Filter[];
|
|
8
8
|
/** Render each item */
|
|
9
9
|
children: Snippet<[{
|
|
10
|
-
item:
|
|
10
|
+
item: BaseRecord & {
|
|
11
|
+
id: string | number;
|
|
12
|
+
};
|
|
11
13
|
index: number;
|
|
12
14
|
}]>;
|
|
13
15
|
/** Custom empty state */
|
|
@@ -15,6 +17,6 @@ interface Props<T extends BaseRecord = BaseRecord> {
|
|
|
15
17
|
/** Custom loading skeleton */
|
|
16
18
|
loadingSkeleton?: Snippet;
|
|
17
19
|
}
|
|
18
|
-
declare const InfiniteList: import("svelte").Component<Props
|
|
20
|
+
declare const InfiniteList: import("svelte").Component<Props, {}, "">;
|
|
19
21
|
type InfiniteList = ReturnType<typeof InfiniteList>;
|
|
20
22
|
export default InfiniteList;
|