@riducms/admin 0.2.3 → 0.4.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/THIRD_PARTY_NOTICES.md +60 -37
- package/package.json +29 -15
- package/src/app/admin-core-view-route.svelte +38 -53
- package/src/app/admin-extension-route.svelte +19 -0
- package/src/app/admin-layout.scss +175 -0
- package/src/app/admin-layout.svelte +144 -410
- package/src/app/admin-navigation-progress.svelte +11 -77
- package/src/app/admin-page-title.svelte +17 -85
- package/src/app/admin-page-title.ts +136 -0
- package/src/app/admin-route-error.svelte +24 -0
- package/src/app/admin-router-provider.svelte +34 -0
- package/src/app/admin-router-root.svelte +41 -0
- package/src/app/admin-routes.svelte +56 -19
- package/src/app/loading-boundary.svelte +3 -1
- package/src/app-meta.ts +13 -0
- package/src/app.css +138 -496
- package/src/app.svelte +60 -26
- package/src/components/brand/ridu-logo.svelte +19 -5
- package/src/components/data/list-table.scss +63 -0
- package/src/components/icons/LICENSE.md +24 -0
- package/src/components/icons/chevron.svelte +8 -0
- package/src/components/icons/plus.svelte +12 -0
- package/src/components/icons/search.svelte +12 -0
- package/src/components/icons/x.svelte +8 -0
- package/src/components/json-tree/json-tree-node.svelte +61 -67
- package/src/components/json-tree/json-viewer.scss +153 -0
- package/src/components/json-tree/json-viewer.svelte +57 -96
- package/src/components/ui/banner/banner.scss +28 -0
- package/src/components/ui/banner/banner.svelte +9 -8
- package/src/components/ui/banner/index.ts +1 -5
- package/src/components/ui/code-editor/code-editor.scss +20 -0
- package/src/components/ui/code-editor/code-editor.svelte +71 -0
- package/src/components/ui/code-editor/code-editor.ts +151 -0
- package/src/components/ui/code-editor/code-languages.ts +29 -0
- package/src/components/ui/collapsible-panel/collapsible-panel.scss +38 -0
- package/src/components/ui/collapsible-panel/collapsible-panel.svelte +13 -0
- package/src/components/ui/collapsible-panel/index.ts +1 -0
- package/src/components/ui/combobox/combobox.scss +163 -0
- package/src/components/ui/combobox/index.ts +22 -0
- package/src/components/ui/date-value-control/date-value-calendar.svelte +128 -16
- package/src/components/ui/date-value-control/date-value-control-loader.scss +26 -0
- package/src/components/ui/date-value-control/date-value-control-loader.svelte +35 -13
- package/src/components/ui/date-value-control/date-value-control.scss +223 -0
- package/src/components/ui/date-value-control/date-value-control.svelte +62 -44
- package/src/components/ui/drawer/drawer-depth.ts +8 -0
- package/src/components/ui/dropdown-menu/dropdown-menu-content.svelte +2 -5
- package/src/components/ui/dropdown-menu/dropdown-menu-item.svelte +2 -5
- package/src/components/ui/dropdown-menu/dropdown-menu-separator.svelte +2 -2
- package/src/components/ui/dropdown-menu/dropdown-menu.scss +62 -0
- package/src/components/ui/kbd/kbd.scss +17 -0
- package/src/components/ui/kbd/kbd.svelte +3 -10
- package/src/components/ui/navigation-drawer/navigation-drawer.scss +40 -0
- package/src/components/ui/navigation-drawer/navigation-drawer.svelte +38 -0
- package/src/components/ui/popover/popover-content.svelte +3 -5
- package/src/components/ui/popover/popover.scss +18 -0
- package/src/components/ui/radio-group/index.ts +0 -1
- package/src/components/ui/radio-group/radio-card-item.svelte +7 -12
- package/src/components/ui/radio-group/radio-group.svelte +2 -2
- package/src/components/ui/radio-group/radio.scss +45 -0
- package/src/components/ui/select/select-content.svelte +5 -6
- package/src/components/ui/select/select-item.svelte +8 -8
- package/src/components/ui/select/select-scroll-down-button.svelte +3 -5
- package/src/components/ui/select/select-scroll-up-button.svelte +3 -5
- package/src/components/ui/select/select-trigger.svelte +6 -7
- package/src/components/ui/select/select.scss +126 -0
- package/src/components/ui/sheet/sheet-content.svelte +6 -34
- package/src/components/ui/sheet/sheet-description.svelte +2 -2
- package/src/components/ui/sheet/sheet-overlay.svelte +2 -21
- package/src/components/ui/sheet/sheet-title.svelte +2 -2
- package/src/components/ui/sheet/sheet.scss +221 -0
- package/src/components/ui/skeleton/skeleton.scss +20 -0
- package/src/components/ui/skeleton/skeleton.svelte +4 -16
- package/src/components/ui/sonner/sonner.scss +121 -0
- package/src/components/ui/sonner/sonner.svelte +11 -10
- package/src/components/ui/status-indicator/status-indicator.scss +48 -0
- package/src/components/ui/status-indicator/status-indicator.svelte +14 -14
- package/src/components/ui/tabs/tabs-content.svelte +2 -2
- package/src/components/ui/tabs/tabs-list.svelte +7 -7
- package/src/components/ui/tabs/tabs-trigger.svelte +2 -8
- package/src/components/ui/tabs/tabs.scss +86 -0
- package/src/components/ui/tabs/tabs.svelte +2 -2
- package/src/components/ui/timezone-picker/timezone-picker.svelte +152 -0
- package/src/core/api/admin-client.ts +2 -2
- package/src/core/bootstrap/admin-bootstrap.ts +396 -0
- package/src/core/bootstrap/admin-prepared-state.ts +213 -0
- package/src/core/bootstrap/admin-route-modules.ts +66 -0
- package/src/core/clipboard/copy-feedback.svelte.ts +43 -0
- package/src/core/forms/embedded-fields.ts +4 -8
- package/src/core/forms/field-editor-authoring.ts +8 -0
- package/src/core/forms/field-issue-focus.ts +4 -4
- package/src/core/forms/field-occurrence.ts +4 -7
- package/src/core/forms/form-controller.svelte.ts +14 -21
- package/src/core/forms/form-draft-recovery.ts +17 -4
- package/src/core/forms/form-issue-correlation.ts +13 -13
- package/src/core/forms/form-path.ts +17 -0
- package/src/core/forms/form-schema.ts +12 -43
- package/src/core/forms/form-validation.ts +7 -46
- package/src/core/forms/plugin-field-authoring.ts +6 -2
- package/src/core/forms/plugin-field-write.ts +2 -6
- package/src/core/i18n/admin-i18n.svelte.ts +18 -0
- package/src/core/i18n/format-admin-date-time.ts +19 -0
- package/src/core/i18n/humanize-identifier.ts +5 -0
- package/src/core/i18n/time-zone-label.ts +20 -0
- package/src/core/loaders/admin-view-host.svelte +72 -0
- package/src/core/loaders/admin-view-loader.svelte.ts +90 -0
- package/src/core/notifications/validation-toast.svelte +2 -2
- package/src/core/plugins/field-registry.ts +7 -8
- package/src/core/routing/admin-paths.ts +53 -2
- package/src/core/routing/admin-scroll.svelte.ts +74 -0
- package/src/core/routing/admin-view-selection.ts +78 -0
- package/src/core/runtime/admin-runtime.svelte.ts +131 -135
- package/src/core/schema/field-default.ts +33 -0
- package/src/core/schema/field-localization.ts +15 -0
- package/src/core/schema/read-document-path.ts +11 -0
- package/src/features/account/account-menu.scss +37 -0
- package/src/features/account/account-menu.svelte +115 -0
- package/src/features/{auth → account}/account-navigation.svelte +16 -19
- package/src/features/{auth → account}/account-route.svelte +206 -49
- package/src/features/account/account-security-controller.svelte.ts +159 -0
- package/src/features/{auth → account}/account-security-route.svelte +140 -42
- package/src/features/api-reference/api-reference-code.svelte +114 -0
- package/src/features/api-reference/api-reference-content.svelte +258 -0
- package/src/features/api-reference/api-reference-drawer.scss +74 -0
- package/src/features/api-reference/api-reference-examples.ts +381 -0
- package/src/features/api-reference/api-reference-schema.ts +332 -0
- package/src/features/api-reference/api-reference.scss +190 -0
- package/src/features/api-reference/api-reference.svelte +74 -0
- package/src/features/auth/auth-brand.svelte +5 -3
- package/src/features/auth/auth-field.svelte +92 -0
- package/src/features/auth/auth-frame.svelte +5 -8
- package/src/features/auth/auth.scss +122 -0
- package/src/features/auth/create-first-user-controller.svelte.ts +30 -60
- package/src/features/auth/create-first-user-route.svelte +83 -122
- package/src/features/auth/forgot-password-route.svelte +32 -24
- package/src/features/auth/login-route.svelte +69 -117
- package/src/features/auth/logout-button.scss +34 -0
- package/src/features/auth/logout-button.svelte +52 -0
- package/src/features/auth/request-verification-route.svelte +28 -23
- package/src/features/auth/reset-password-route.svelte +111 -41
- package/src/features/auth/verify-email-route.svelte +52 -15
- package/src/features/bulk-edit/bulk-edit-fields.ts +23 -0
- package/src/features/bulk-edit/bulk-edit.scss +152 -0
- package/src/features/bulk-edit/field-picker.svelte +176 -0
- package/src/features/collections/bulk/bulk-actions.svelte +148 -0
- package/src/features/collections/bulk/bulk-confirmation.svelte +153 -0
- package/src/features/collections/bulk/bulk-editor-loader.svelte +95 -0
- package/src/features/collections/bulk/bulk-editor.svelte +186 -0
- package/src/features/collections/collection-list-cell-values.ts +144 -0
- package/src/features/collections/collection-list-controller.svelte.ts +268 -379
- package/src/features/collections/collection-list-preferences-controller.svelte.ts +54 -40
- package/src/features/collections/collection-list-query.ts +223 -0
- package/src/features/collections/collection-list-results.svelte +205 -329
- package/src/features/collections/collection-list-route.svelte +143 -884
- package/src/features/collections/collection-list.scss +261 -0
- package/src/features/collections/collection-list.svelte.ts +362 -0
- package/src/features/collections/controls/column-picker.svelte +110 -0
- package/src/features/collections/controls/column-pill.svelte +62 -0
- package/src/features/collections/controls/filter-builder.svelte +193 -0
- package/src/features/collections/controls/filter-row.svelte +142 -0
- package/src/features/collections/controls/list-controls.scss +196 -0
- package/src/features/collections/controls/list-options.svelte +203 -0
- package/src/features/collections/controls/list-pagination.scss +78 -0
- package/src/features/collections/controls/list-pagination.svelte +115 -0
- package/src/features/collections/controls/list-toolbar.svelte +132 -0
- package/src/features/collections/controls/sort-heading.scss +52 -0
- package/src/features/collections/controls/sort-heading.svelte +78 -0
- package/src/features/collections/list-columns.ts +43 -0
- package/src/features/collections/list-workspace.ts +155 -54
- package/src/features/dashboard/dashboard-route.svelte +82 -86
- package/src/features/dashboard/dashboard.scss +131 -0
- package/src/features/development/development-tools.svelte +20 -36
- package/src/features/documents/document-action-bar.svelte +438 -0
- package/src/features/documents/document-api-view-loader.svelte +17 -6
- package/src/features/documents/document-api-view.scss +120 -0
- package/src/features/documents/document-api-view.svelte +169 -454
- package/src/features/documents/document-controller.svelte.ts +531 -617
- package/src/features/documents/document-credentials.scss +37 -0
- package/src/features/documents/document-credentials.svelte +72 -0
- package/src/features/documents/{document-route-dirty.ts → document-credentials.ts} +25 -0
- package/src/features/documents/document-field-sections.scss +39 -0
- package/src/features/documents/document-field-sections.svelte +4 -13
- package/src/features/documents/document-loading.scss +24 -0
- package/src/features/documents/document-lock-controller.svelte.ts +187 -0
- package/src/features/documents/document-operation-dialogs.svelte +110 -0
- package/src/features/documents/document-route-loader.svelte +17 -5
- package/src/features/documents/document-route.svelte +305 -811
- package/src/features/documents/document-schedule.scss +127 -0
- package/src/features/documents/document-schedule.svelte +323 -0
- package/src/features/documents/document-title.ts +25 -0
- package/src/features/documents/document.scss +274 -0
- package/src/features/documents/live-preview-panel.scss +117 -0
- package/src/features/documents/live-preview-panel.svelte +167 -168
- package/src/features/documents/live-preview.ts +2 -10
- package/src/features/documents/upload-document-preview-loader.svelte +26 -23
- package/src/features/localization/content-locale-switcher.scss +43 -0
- package/src/features/localization/content-locale-switcher.svelte +24 -17
- package/src/features/navigation/admin-breadcrumbs.scss +56 -0
- package/src/features/navigation/admin-breadcrumbs.svelte +102 -37
- package/src/features/navigation/admin-command-menu.svelte +38 -15
- package/src/features/navigation/admin-navigation.scss +133 -0
- package/src/features/navigation/admin-navigation.svelte +169 -0
- package/src/features/navigation/breadcrumb-context.svelte.ts +15 -0
- package/src/features/navigation/navigation-preference.svelte.ts +70 -0
- package/src/features/reference-browser/reference-browser-editor.svelte +180 -0
- package/src/features/reference-browser/reference-browser-list.scss +113 -0
- package/src/features/reference-browser/reference-browser-list.svelte +370 -0
- package/src/features/reference-browser/reference-browser-loader.svelte +26 -8
- package/src/features/reference-browser/reference-browser-workflow.svelte.ts +336 -239
- package/src/features/reference-browser/reference-browser.scss +217 -0
- package/src/features/reference-browser/reference-browser.svelte +154 -797
- package/src/features/reference-browser/reference-collection-picker.svelte +116 -0
- package/src/features/reference-browser/reference-list-query.ts +35 -0
- package/src/features/uploads/bulk-upload-controller.svelte.ts +604 -0
- package/src/features/uploads/bulk-upload-edit-all.svelte +92 -0
- package/src/features/uploads/bulk-upload-editor.svelte +191 -0
- package/src/features/uploads/bulk-upload-file-picker.svelte +70 -0
- package/src/features/uploads/bulk-upload-remote.svelte +100 -0
- package/src/features/uploads/bulk-upload-route-loader.svelte +54 -0
- package/src/features/uploads/bulk-upload-route.svelte +172 -592
- package/src/features/uploads/bulk-upload-sidebar.svelte +125 -0
- package/src/features/uploads/bulk-upload.scss +526 -0
- package/src/features/uploads/bulk-upload.ts +105 -14
- package/src/features/uploads/crop-surface.ts +150 -0
- package/src/features/uploads/image-editor.svelte +231 -0
- package/src/features/uploads/rendition-preview.svelte +64 -0
- package/src/features/uploads/upload-control.svelte +340 -0
- package/src/features/uploads/upload-document-contracts.ts +30 -0
- package/src/features/uploads/upload-draft.svelte.ts +294 -0
- package/src/features/uploads/upload-metadata-fields.scss +32 -0
- package/src/features/uploads/upload-metadata-fields.svelte +8 -7
- package/src/features/uploads/upload-thumbnail.svelte +47 -0
- package/src/features/uploads/upload.scss +361 -0
- package/src/features/versions/version-comparison.svelte +361 -0
- package/src/features/versions/version-diff-fields.svelte +136 -0
- package/src/features/versions/version-diff.ts +296 -41
- package/src/features/versions/version-history-controller.svelte.ts +311 -0
- package/src/features/versions/version-history-route-loader.svelte +32 -0
- package/src/features/versions/version-history-route.svelte +157 -522
- package/src/features/versions/version-history.scss +444 -0
- package/src/features/versions/version-history.ts +45 -0
- package/src/features/versions/version-table.svelte +91 -0
- package/src/fields/embedded-schema-draft-editor.scss +48 -0
- package/src/fields/embedded-schema-draft-editor.svelte +24 -16
- package/src/fields/field-collapsible.svelte +14 -8
- package/src/fields/field-layout.scss +171 -0
- package/src/fields/field-layout.svelte +3 -5
- package/src/fields/field-renderer.svelte +17 -29
- package/src/fields/field-shell.svelte +1 -1
- package/src/fields/field-tab-layout.svelte +25 -19
- package/src/fields/join/join-field-controller.svelte.ts +513 -0
- package/src/fields/join/join-field-values.ts +111 -0
- package/src/fields/join/join-field.scss +189 -0
- package/src/fields/join/join-field.svelte +164 -332
- package/src/fields/live-validation-feedback.svelte +4 -3
- package/src/fields/local-field-editor.svelte +2 -2
- package/src/fields/nested/block-name-input.svelte +11 -12
- package/src/fields/nested/block-picker.scss +128 -0
- package/src/fields/nested/block-picker.svelte +81 -0
- package/src/fields/nested/block-placeholder.svg +2 -0
- package/src/fields/nested/nested-field.scss +331 -0
- package/src/fields/nested/nested-field.svelte +265 -245
- package/src/fields/nested/sortable-row.svelte +9 -7
- package/src/fields/plugin-field.svelte +4 -6
- package/src/fields/point/point-field.svelte +51 -38
- package/src/fields/primitive-list/primitive-list-field.svelte +63 -19
- package/src/fields/primitive-list/primitive-list.scss +109 -0
- package/src/fields/radio/radio-field.svelte +2 -1
- package/src/fields/relationship/relationship-field-controller.svelte.ts +81 -41
- package/src/fields/relationship/relationship-field.svelte +144 -175
- package/src/fields/relationship/relationship-lookup-controller.svelte.ts +58 -30
- package/src/fields/relationship/relationship-query.ts +2 -10
- package/src/fields/relationship/relationship-quick-picker-controller.svelte.ts +36 -62
- package/src/fields/relationship/relationship-quick-picker.svelte +178 -227
- package/src/fields/relationship/relationship-selection.svelte +120 -0
- package/src/fields/relationship/relationship-value.ts +46 -7
- package/src/fields/relationship/relationship.scss +182 -0
- package/src/fields/scalar/code-field.svelte +101 -0
- package/src/fields/scalar/date-control-value.ts +13 -0
- package/src/fields/scalar/scalar-field.svelte +25 -67
- package/src/fields/select/select-field.svelte +148 -94
- package/src/fields/text/slug-field.scss +28 -0
- package/src/fields/text/slug-field.svelte +19 -15
- package/src/fields/text/text-field.svelte +1 -2
- package/src/fields/ui/ui-field.svelte +7 -4
- package/src/fields/virtual/virtual-field.svelte +2 -5
- package/src/index.ts +1 -2
- package/src/routing.ts +2 -0
- package/src/app/deferred-redirect.svelte +0 -23
- package/src/components/code-block/code-block.svelte +0 -107
- package/src/components/ui/bulk-action-bar/bulk-action-bar.svelte +0 -50
- package/src/components/ui/bulk-action-bar/index.ts +0 -1
- package/src/components/ui/button/index.ts +0 -8
- package/src/components/ui/calendar/calendar-caption.svelte +0 -72
- package/src/components/ui/calendar/calendar-cell.svelte +0 -20
- package/src/components/ui/calendar/calendar-day.svelte +0 -27
- package/src/components/ui/calendar/calendar-grid-row.svelte +0 -13
- package/src/components/ui/calendar/calendar-grid.svelte +0 -17
- package/src/components/ui/calendar/calendar-head-cell.svelte +0 -20
- package/src/components/ui/calendar/calendar-header.svelte +0 -20
- package/src/components/ui/calendar/calendar-heading.svelte +0 -17
- package/src/components/ui/calendar/calendar-month-select.svelte +0 -45
- package/src/components/ui/calendar/calendar-month.svelte +0 -16
- package/src/components/ui/calendar/calendar-months.svelte +0 -20
- package/src/components/ui/calendar/calendar-nav.svelte +0 -20
- package/src/components/ui/calendar/calendar-next-button.svelte +0 -30
- package/src/components/ui/calendar/calendar-prev-button.svelte +0 -30
- package/src/components/ui/calendar/calendar-year-select.svelte +0 -44
- package/src/components/ui/calendar/calendar.svelte +0 -118
- package/src/components/ui/calendar/index.ts +0 -1
- package/src/components/ui/checkbox/checkbox.svelte +0 -35
- package/src/components/ui/checkbox/index.ts +0 -1
- package/src/components/ui/dialog/dialog-close.svelte +0 -11
- package/src/components/ui/dialog/dialog-content.svelte +0 -52
- package/src/components/ui/dialog/dialog-description.svelte +0 -20
- package/src/components/ui/dialog/dialog-footer.svelte +0 -20
- package/src/components/ui/dialog/dialog-header.svelte +0 -20
- package/src/components/ui/dialog/dialog-overlay.svelte +0 -20
- package/src/components/ui/dialog/dialog-title.svelte +0 -17
- package/src/components/ui/dialog/dialog-trigger.svelte +0 -11
- package/src/components/ui/dialog/dialog.svelte +0 -7
- package/src/components/ui/dialog/index.ts +0 -8
- package/src/components/ui/empty-state/empty-state.svelte +0 -34
- package/src/components/ui/empty-state/index.ts +0 -1
- package/src/components/ui/input/index.ts +0 -1
- package/src/components/ui/pagination/index.ts +0 -1
- package/src/components/ui/pagination/pagination.svelte +0 -88
- package/src/components/ui/radio-group/radio-group-item.svelte +0 -17
- package/src/components/ui/slider/index.ts +0 -3
- package/src/components/ui/slider/slider-content.svelte +0 -59
- package/src/components/ui/slider/slider.svelte +0 -35
- package/src/components/ui/table/index.ts +0 -6
- package/src/components/ui/table/table-body.svelte +0 -20
- package/src/components/ui/table/table-cell.svelte +0 -23
- package/src/components/ui/table/table-head.svelte +0 -23
- package/src/components/ui/table/table-header.svelte +0 -20
- package/src/components/ui/table/table-row.svelte +0 -23
- package/src/components/ui/table/table.svelte +0 -22
- package/src/components/ui/textarea/index.ts +0 -1
- package/src/components/ui/tooltip/index.ts +0 -4
- package/src/components/ui/tooltip/tooltip-content.svelte +0 -50
- package/src/components/ui/tooltip/tooltip-provider.svelte +0 -7
- package/src/components/ui/tooltip/tooltip-trigger.svelte +0 -7
- package/src/components/ui/tooltip/tooltip.svelte +0 -7
- package/src/features/auth/account-menu.svelte +0 -159
- package/src/features/auth/account-security-controller.svelte.ts +0 -119
- package/src/features/collections/collection-list-bulk-actions.svelte +0 -143
- package/src/features/collections/collection-list-bulk-editor.svelte +0 -157
- package/src/features/collections/collection-list-filter-popover.svelte +0 -238
- package/src/features/collections/collection-list-workspace-toolbar.svelte +0 -409
- package/src/features/collections/collection-table-skeleton.svelte +0 -44
- package/src/features/documents/document-heading.ts +0 -20
- package/src/features/documents/upload-document-preview.svelte +0 -525
|
@@ -1,24 +1,19 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { useNavigation } from "@hvniel/svelte-router";
|
|
3
|
+
import { tick, untrack } from "svelte";
|
|
4
4
|
|
|
5
5
|
import { getAdminRuntime } from "@admin/core/runtime/admin-runtime.svelte";
|
|
6
6
|
|
|
7
7
|
const revealDelayMilliseconds = 160;
|
|
8
8
|
const minimumVisibleMilliseconds = 180;
|
|
9
9
|
const completionMilliseconds = 150;
|
|
10
|
-
const fallbackIntentMilliseconds = 140;
|
|
11
10
|
const runtime = getAdminRuntime();
|
|
12
|
-
const
|
|
13
|
-
const routeKey = $derived(
|
|
14
|
-
`${routeLocation.pathname}${routeLocation.search}${routeLocation.hash}`
|
|
15
|
-
);
|
|
11
|
+
const navigation = useNavigation();
|
|
16
12
|
|
|
17
13
|
type ProgressPhase = "idle" | "pending" | "running" | "finishing";
|
|
18
14
|
|
|
19
15
|
let phase = $state<ProgressPhase>("idle");
|
|
20
16
|
let progress = $state(0);
|
|
21
|
-
let observedRouteKey = "";
|
|
22
17
|
let startedAt = 0;
|
|
23
18
|
let generation = 0;
|
|
24
19
|
let revealTimer: number | undefined;
|
|
@@ -26,7 +21,6 @@
|
|
|
26
21
|
let finishTimer: number | undefined;
|
|
27
22
|
let hideTimer: number | undefined;
|
|
28
23
|
let resetTimer: number | undefined;
|
|
29
|
-
let intentTimer: number | undefined;
|
|
30
24
|
|
|
31
25
|
function clearTimer(timer: number | undefined) {
|
|
32
26
|
if (timer !== undefined) window.clearTimeout(timer);
|
|
@@ -52,16 +46,12 @@
|
|
|
52
46
|
|
|
53
47
|
function start() {
|
|
54
48
|
clearCompletionTimers();
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
if (phase === "pending") return;
|
|
59
|
-
if (phase === "running") {
|
|
60
|
-
generation += 1;
|
|
49
|
+
generation += 1;
|
|
50
|
+
// Progress phase is an output of this navigation synchronization, not one of its inputs.
|
|
51
|
+
if (untrack(() => phase) === "running") {
|
|
61
52
|
return;
|
|
62
53
|
}
|
|
63
54
|
|
|
64
|
-
generation += 1;
|
|
65
55
|
const activeGeneration = generation;
|
|
66
56
|
phase = "pending";
|
|
67
57
|
progress = 0;
|
|
@@ -77,6 +67,8 @@
|
|
|
77
67
|
}
|
|
78
68
|
|
|
79
69
|
function afterDestinationPaint() {
|
|
70
|
+
// The destination DOM flushes at tick; two frames keep the progress bar visible until that
|
|
71
|
+
// DOM has reached a browser paint rather than finishing over the retained outgoing page.
|
|
80
72
|
return new Promise<void>((resolve) => {
|
|
81
73
|
requestAnimationFrame(() => requestAnimationFrame(() => resolve()));
|
|
82
74
|
});
|
|
@@ -112,74 +104,16 @@
|
|
|
112
104
|
}, remaining);
|
|
113
105
|
}
|
|
114
106
|
|
|
115
|
-
function startIntent() {
|
|
116
|
-
const routeBeforeIntent = routeKey;
|
|
117
|
-
start();
|
|
118
|
-
intentTimer = window.setTimeout(() => {
|
|
119
|
-
intentTimer = undefined;
|
|
120
|
-
if (routeKey === routeBeforeIntent) void finish();
|
|
121
|
-
}, fallbackIntentMilliseconds);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
function handleLinkIntent(event: MouseEvent) {
|
|
125
|
-
if (
|
|
126
|
-
event.defaultPrevented ||
|
|
127
|
-
event.button !== 0 ||
|
|
128
|
-
event.metaKey ||
|
|
129
|
-
event.ctrlKey ||
|
|
130
|
-
event.shiftKey ||
|
|
131
|
-
event.altKey ||
|
|
132
|
-
!(event.target instanceof Element)
|
|
133
|
-
) {
|
|
134
|
-
return;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
const anchor = event.target.closest<HTMLAnchorElement>("a[href]");
|
|
138
|
-
if (
|
|
139
|
-
anchor === null ||
|
|
140
|
-
anchor.hasAttribute("download") ||
|
|
141
|
-
(anchor.target !== "" && anchor.target !== "_self")
|
|
142
|
-
) {
|
|
143
|
-
return;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
const destination = new URL(anchor.href, window.location.href);
|
|
147
|
-
if (
|
|
148
|
-
destination.origin !== window.location.origin ||
|
|
149
|
-
`${destination.pathname}${destination.search}${destination.hash}` ===
|
|
150
|
-
`${window.location.pathname}${window.location.search}${window.location.hash}`
|
|
151
|
-
) {
|
|
152
|
-
return;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
startIntent();
|
|
156
|
-
}
|
|
157
|
-
|
|
158
107
|
$effect(() => {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
observedRouteKey = nextRouteKey;
|
|
162
|
-
return;
|
|
163
|
-
}
|
|
164
|
-
if (nextRouteKey === observedRouteKey) return;
|
|
165
|
-
|
|
166
|
-
observedRouteKey = nextRouteKey;
|
|
167
|
-
start();
|
|
168
|
-
void finish();
|
|
108
|
+
if (navigation.current.state === "idle") void finish();
|
|
109
|
+
else start();
|
|
169
110
|
});
|
|
170
111
|
|
|
171
|
-
|
|
172
|
-
const handleHistoryIntent = () => startIntent();
|
|
173
|
-
document.addEventListener("click", handleLinkIntent, true);
|
|
174
|
-
window.addEventListener("popstate", handleHistoryIntent);
|
|
175
|
-
|
|
112
|
+
$effect(() => {
|
|
176
113
|
return () => {
|
|
177
114
|
generation += 1;
|
|
178
|
-
document.removeEventListener("click", handleLinkIntent, true);
|
|
179
|
-
window.removeEventListener("popstate", handleHistoryIntent);
|
|
180
115
|
clearTimer(revealTimer);
|
|
181
116
|
clearTimer(trickleTimer);
|
|
182
|
-
clearTimer(intentTimer);
|
|
183
117
|
clearCompletionTimers();
|
|
184
118
|
};
|
|
185
119
|
});
|
|
@@ -1,94 +1,26 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { useLocation } from "@hvniel/svelte-router";
|
|
3
3
|
|
|
4
|
-
import { ADMIN_NAME } from "@admin/app-meta";
|
|
4
|
+
import { ADMIN_NAME, adminApplicationName } from "@admin/app-meta";
|
|
5
|
+
import { resolveAdminPageLabel } from "@admin/app/admin-page-title";
|
|
5
6
|
import { getAdminRuntime } from "@admin/core/runtime/admin-runtime.svelte";
|
|
6
7
|
|
|
7
8
|
const runtime = getAdminRuntime();
|
|
8
|
-
const location =
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
segments[1] === "security"
|
|
24
|
-
? runtime.i18n.t("account:accountSecurity")
|
|
25
|
-
: runtime.i18n.t("account:account")
|
|
26
|
-
);
|
|
27
|
-
}
|
|
28
|
-
if (segments[0] === "collections" && segments[1] !== undefined) {
|
|
29
|
-
const collection = runtime.manifest?.collections.find(
|
|
30
|
-
(candidate) => candidate.slug === segments[1]
|
|
31
|
-
);
|
|
32
|
-
const singular =
|
|
33
|
-
collection === undefined
|
|
34
|
-
? humanize(segments[1])
|
|
35
|
-
: runtime.i18n.text(collection.labels.singular, collection.labels.singularTranslations);
|
|
36
|
-
const plural =
|
|
37
|
-
collection === undefined
|
|
38
|
-
? singular
|
|
39
|
-
: runtime.i18n.text(collection.labels.plural, collection.labels.pluralTranslations);
|
|
40
|
-
if (segments[2] === undefined) return titled(plural);
|
|
41
|
-
if (segments[2] === "create") {
|
|
42
|
-
return titled(
|
|
43
|
-
segments[3] === "api"
|
|
44
|
-
? runtime.i18n.t("documents:apiFor", { label: singular })
|
|
45
|
-
: runtime.i18n.t("collections:createNew", { label: singular })
|
|
46
|
-
);
|
|
47
|
-
}
|
|
48
|
-
if (segments[2] === "trash")
|
|
49
|
-
return titled(
|
|
50
|
-
runtime.i18n.t("collections:trashFor", {
|
|
51
|
-
label: plural,
|
|
52
|
-
})
|
|
53
|
-
);
|
|
54
|
-
if (segments[3] === "api")
|
|
55
|
-
return titled(runtime.i18n.t("documents:apiFor", { label: singular }));
|
|
56
|
-
if (segments[3] === "versions")
|
|
57
|
-
return titled(runtime.i18n.t("documents:versionsFor", { label: singular }));
|
|
58
|
-
return titled(runtime.i18n.t("documents:editing", { label: singular }));
|
|
59
|
-
}
|
|
60
|
-
if (segments[0] === "globals" && segments[1] !== undefined) {
|
|
61
|
-
const global = runtime.manifest?.globals?.find((candidate) => candidate.slug === segments[1]);
|
|
62
|
-
const label =
|
|
63
|
-
global === undefined
|
|
64
|
-
? humanize(segments[1])
|
|
65
|
-
: runtime.i18n.text(global.labels.singular, global.labels.singularTranslations);
|
|
66
|
-
if (segments[2] === "api") return titled(runtime.i18n.t("documents:apiFor", { label }));
|
|
67
|
-
if (segments[2] === "versions")
|
|
68
|
-
return titled(runtime.i18n.t("documents:versionsFor", { label }));
|
|
69
|
-
return titled(label);
|
|
70
|
-
}
|
|
71
|
-
const pluginPath = segments.join("/");
|
|
72
|
-
const pluginRoute = runtime.pluginRoutes.find((route) => route.path === pluginPath);
|
|
73
|
-
if (pluginRoute?.navigation?.labelKey !== undefined)
|
|
74
|
-
return titled(runtime.i18n.t(pluginRoute.navigation.labelKey));
|
|
75
|
-
if (pluginRoute?.navigation?.label !== undefined) return titled(pluginRoute.navigation.label);
|
|
76
|
-
return titled(humanize(segments.at(-1) ?? runtime.i18n.t("navigation:page")));
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function titled(value: string) {
|
|
80
|
-
const application = runtime.manifest?.application;
|
|
81
|
-
const name =
|
|
82
|
-
application === undefined
|
|
83
|
-
? ADMIN_NAME
|
|
84
|
-
: runtime.i18n.text(application.name, application.nameTranslations);
|
|
85
|
-
return `${value} - ${name}`;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
function humanize(value: string) {
|
|
89
|
-
const decoded = decodeURIComponent(value).replaceAll("-", " ");
|
|
90
|
-
return decoded.charAt(0).toLocaleUpperCase(runtime.i18n.language) + decoded.slice(1);
|
|
91
|
-
}
|
|
9
|
+
const location = useLocation();
|
|
10
|
+
const extensions = runtime.config.extensions;
|
|
11
|
+
const pageLabel = $derived(
|
|
12
|
+
resolveAdminPageLabel({
|
|
13
|
+
pathname: location.current.pathname,
|
|
14
|
+
manifest: runtime.manifest,
|
|
15
|
+
routes: extensions.routes,
|
|
16
|
+
documentViews: extensions.documentViews,
|
|
17
|
+
i18n: runtime.i18n,
|
|
18
|
+
})
|
|
19
|
+
);
|
|
20
|
+
const applicationName = $derived(
|
|
21
|
+
adminApplicationName(runtime.manifest, runtime.i18n, ADMIN_NAME)
|
|
22
|
+
);
|
|
23
|
+
const pageTitle = $derived(`${pageLabel} - ${applicationName}`);
|
|
92
24
|
</script>
|
|
93
25
|
|
|
94
26
|
<svelte:head><title>{pageTitle}</title></svelte:head>
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import type { AdminDocumentView, AdminRoute } from "@riducms/plugin";
|
|
2
|
+
import type { SchemaManifest } from "@riducms/protocol";
|
|
3
|
+
import type { AdminI18n, ExtensionTranslationKey } from "@riducms/translations";
|
|
4
|
+
|
|
5
|
+
import { adminPathSegments, humanizeAdminPathSegment } from "@admin/core/routing/admin-paths";
|
|
6
|
+
|
|
7
|
+
type PageTitleI18n = Pick<AdminI18n, "language" | "t" | "text">;
|
|
8
|
+
|
|
9
|
+
interface AdminPageLabelOptions {
|
|
10
|
+
pathname: string;
|
|
11
|
+
manifest: SchemaManifest | undefined;
|
|
12
|
+
routes: readonly AdminRoute[];
|
|
13
|
+
documentViews: readonly AdminDocumentView[];
|
|
14
|
+
i18n: PageTitleI18n;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function resolveAdminPageLabel(options: AdminPageLabelOptions): string {
|
|
18
|
+
const segments = adminPathSegments(options.pathname);
|
|
19
|
+
const [root, resource, action, view] = segments;
|
|
20
|
+
|
|
21
|
+
switch (root) {
|
|
22
|
+
case undefined:
|
|
23
|
+
return options.i18n.t("dashboard:heading");
|
|
24
|
+
case "create-first-user":
|
|
25
|
+
return options.i18n.t("auth:createFirstUser");
|
|
26
|
+
case "login":
|
|
27
|
+
return options.i18n.t("auth:login");
|
|
28
|
+
case "forgot-password":
|
|
29
|
+
return options.i18n.t("auth:forgotPassword");
|
|
30
|
+
case "reset-password":
|
|
31
|
+
return options.i18n.t("auth:resetPassword");
|
|
32
|
+
case "request-verification":
|
|
33
|
+
return options.i18n.t("auth:requestVerification");
|
|
34
|
+
case "verify-email":
|
|
35
|
+
return options.i18n.t("auth:verifyEmail");
|
|
36
|
+
case "account":
|
|
37
|
+
return options.i18n.t(
|
|
38
|
+
resource === "security" ? "account:accountSecurity" : "account:account"
|
|
39
|
+
);
|
|
40
|
+
case "collections":
|
|
41
|
+
return resolveCollectionLabel(options, resource, action, view);
|
|
42
|
+
case "globals":
|
|
43
|
+
return resolveGlobalLabel(options, resource, action);
|
|
44
|
+
default:
|
|
45
|
+
return resolvePluginOrFallbackLabel(options, segments);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function resolveCollectionLabel(
|
|
50
|
+
options: AdminPageLabelOptions,
|
|
51
|
+
resource: string | undefined,
|
|
52
|
+
action: string | undefined,
|
|
53
|
+
view: string | undefined
|
|
54
|
+
) {
|
|
55
|
+
if (resource === undefined) return humanize("collections", options.i18n);
|
|
56
|
+
|
|
57
|
+
const collection = options.manifest?.collections.find((candidate) => candidate.slug === resource);
|
|
58
|
+
const singular =
|
|
59
|
+
collection === undefined
|
|
60
|
+
? humanize(resource, options.i18n)
|
|
61
|
+
: options.i18n.text(collection.labels.singular, collection.labels.singularTranslations);
|
|
62
|
+
const plural =
|
|
63
|
+
collection === undefined
|
|
64
|
+
? singular
|
|
65
|
+
: options.i18n.text(collection.labels.plural, collection.labels.pluralTranslations);
|
|
66
|
+
|
|
67
|
+
if (action === undefined) return plural;
|
|
68
|
+
if (action === "create") {
|
|
69
|
+
return view === "api"
|
|
70
|
+
? options.i18n.t("documents:apiFor", { label: singular })
|
|
71
|
+
: options.i18n.t("collections:createNew", { label: singular });
|
|
72
|
+
}
|
|
73
|
+
if (action === "trash") return options.i18n.t("collections:trashFor", { label: plural });
|
|
74
|
+
if (action === "upload") return options.i18n.t("uploads:bulkUpload");
|
|
75
|
+
if (view === "api") return options.i18n.t("documents:apiFor", { label: singular });
|
|
76
|
+
if (view === "versions") return options.i18n.t("documents:versionsFor", { label: singular });
|
|
77
|
+
|
|
78
|
+
return (
|
|
79
|
+
resolveDocumentViewLabel(options, resource, view) ??
|
|
80
|
+
options.i18n.t("documents:editing", { label: singular })
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function resolveGlobalLabel(
|
|
85
|
+
options: AdminPageLabelOptions,
|
|
86
|
+
resource: string | undefined,
|
|
87
|
+
view: string | undefined
|
|
88
|
+
) {
|
|
89
|
+
if (resource === undefined) return humanize("globals", options.i18n);
|
|
90
|
+
|
|
91
|
+
const global = options.manifest?.globals?.find((candidate) => candidate.slug === resource);
|
|
92
|
+
const label =
|
|
93
|
+
global === undefined
|
|
94
|
+
? humanize(resource, options.i18n)
|
|
95
|
+
: options.i18n.text(global.labels.singular, global.labels.singularTranslations);
|
|
96
|
+
|
|
97
|
+
if (view === "api") return options.i18n.t("documents:apiFor", { label });
|
|
98
|
+
if (view === "versions") return options.i18n.t("documents:versionsFor", { label });
|
|
99
|
+
return resolveDocumentViewLabel(options, resource, view) ?? label;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function resolveDocumentViewLabel(
|
|
103
|
+
options: AdminPageLabelOptions,
|
|
104
|
+
resource: string,
|
|
105
|
+
view: string | undefined
|
|
106
|
+
) {
|
|
107
|
+
if (view === undefined) return undefined;
|
|
108
|
+
return resolveExtensionLabel(
|
|
109
|
+
options.documentViews.find(
|
|
110
|
+
(candidate) =>
|
|
111
|
+
candidate.key === view &&
|
|
112
|
+
(candidate.collection === undefined || candidate.collection === resource)
|
|
113
|
+
),
|
|
114
|
+
options.i18n
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function resolvePluginOrFallbackLabel(options: AdminPageLabelOptions, segments: string[]) {
|
|
119
|
+
const route = options.routes.find((candidate) => candidate.path === segments.join("/"));
|
|
120
|
+
return (
|
|
121
|
+
resolveExtensionLabel(route?.navigation, options.i18n) ??
|
|
122
|
+
humanize(segments.at(-1) ?? options.i18n.t("navigation:page"), options.i18n)
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function resolveExtensionLabel(
|
|
127
|
+
extension: { label: string; labelKey?: ExtensionTranslationKey } | undefined,
|
|
128
|
+
i18n: PageTitleI18n
|
|
129
|
+
) {
|
|
130
|
+
if (extension?.labelKey !== undefined) return i18n.t(extension.labelKey);
|
|
131
|
+
return extension?.label;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function humanize(value: string, i18n: PageTitleI18n) {
|
|
135
|
+
return humanizeAdminPathSegment(value, i18n.language);
|
|
136
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Link, useRouteError } from "@hvniel/svelte-router";
|
|
3
|
+
import { getAdminI18n } from "@riducms/plugin";
|
|
4
|
+
import { Button, buttonVariants } from "@riducms/ui";
|
|
5
|
+
|
|
6
|
+
const i18n = getAdminI18n();
|
|
7
|
+
const error = useRouteError();
|
|
8
|
+
|
|
9
|
+
$effect(() => {
|
|
10
|
+
console.error("Ridu admin route failed", error.current);
|
|
11
|
+
});
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<main class="grid min-h-screen place-items-center p-6">
|
|
15
|
+
<section class="grid max-w-lg justify-items-start gap-5" role="alert">
|
|
16
|
+
<h1 class="text-2xl font-semibold">{i18n.t("errors:unknown")}</h1>
|
|
17
|
+
<div class="flex flex-wrap gap-3">
|
|
18
|
+
<Button onclick={() => window.location.reload()}>{i18n.t("general:reloadPage")}</Button>
|
|
19
|
+
<Link to="/" replace class={buttonVariants({ variant: "outline" })}>
|
|
20
|
+
{i18n.t("errors:returnDashboard")}
|
|
21
|
+
</Link>
|
|
22
|
+
</div>
|
|
23
|
+
</section>
|
|
24
|
+
</main>
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { createBrowserRouter, RouterProvider } from "@hvniel/svelte-router";
|
|
3
|
+
|
|
4
|
+
import AdminRouteError from "@admin/app/admin-route-error.svelte";
|
|
5
|
+
import AdminRouterRoot from "@admin/app/admin-router-root.svelte";
|
|
6
|
+
import type { AdminBootstrapCoordinator } from "@admin/core/bootstrap/admin-bootstrap";
|
|
7
|
+
|
|
8
|
+
let {
|
|
9
|
+
coordinator,
|
|
10
|
+
adminBasePath,
|
|
11
|
+
}: { coordinator: AdminBootstrapCoordinator; adminBasePath: string } = $props();
|
|
12
|
+
// One router owns the coordinator and base path selected when this provider mounts.
|
|
13
|
+
// svelte-ignore state_referenced_locally
|
|
14
|
+
const router = createBrowserRouter(
|
|
15
|
+
[
|
|
16
|
+
{
|
|
17
|
+
id: "admin-root",
|
|
18
|
+
path: "*",
|
|
19
|
+
Component: AdminRouterRoot,
|
|
20
|
+
ErrorBoundary: AdminRouteError,
|
|
21
|
+
loader: coordinator.loader,
|
|
22
|
+
shouldRevalidate: coordinator.shouldRevalidate,
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
{
|
|
26
|
+
basename: adminBasePath,
|
|
27
|
+
hydrationData: { loaderData: { "admin-root": coordinator.initialState ?? null } },
|
|
28
|
+
}
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
$effect(() => () => router.dispose());
|
|
32
|
+
</script>
|
|
33
|
+
|
|
34
|
+
<RouterProvider {router} />
|
|
@@ -1,7 +1,48 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { useLoaderData, useLocation } from "@hvniel/svelte-router";
|
|
3
|
+
import type { AdminPreparedRouteStateV1 } from "@riducms/protocol";
|
|
4
|
+
import { tick } from "svelte";
|
|
5
|
+
|
|
6
|
+
import { createAdminScroll } from "@admin/core/routing/admin-scroll.svelte";
|
|
7
|
+
import { getAdminBootstrapCoordinator } from "@admin/core/bootstrap/admin-bootstrap";
|
|
8
|
+
import { normalizedURLIdentity } from "@admin/core/bootstrap/admin-prepared-state";
|
|
2
9
|
import AdminNavigationProgress from "@admin/app/admin-navigation-progress.svelte";
|
|
3
10
|
import AdminPageTitle from "@admin/app/admin-page-title.svelte";
|
|
4
11
|
import AdminRoutes from "@admin/app/admin-routes.svelte";
|
|
12
|
+
|
|
13
|
+
const coordinator = getAdminBootstrapCoordinator();
|
|
14
|
+
const location = useLocation();
|
|
15
|
+
const loaderData = useLoaderData<AdminPreparedRouteStateV1 | null>();
|
|
16
|
+
createAdminScroll();
|
|
17
|
+
let committedStateKey = "";
|
|
18
|
+
let markedIdentity = "";
|
|
19
|
+
|
|
20
|
+
$effect.pre(() => {
|
|
21
|
+
const routedIdentity = normalizedURLIdentity(location.current);
|
|
22
|
+
const state = loaderData.current;
|
|
23
|
+
const stateKey = `${routedIdentity}:${state?.fingerprint ?? "none"}:${state?.outcome ?? "none"}`;
|
|
24
|
+
if (stateKey === committedStateKey) return;
|
|
25
|
+
|
|
26
|
+
committedStateKey = stateKey;
|
|
27
|
+
if (state == null) return;
|
|
28
|
+
|
|
29
|
+
const stateIdentity = `${state.pathname}${state.search}`;
|
|
30
|
+
const url = new URL(stateIdentity, window.location.origin);
|
|
31
|
+
const preparedRoute = coordinator.commit(state, url);
|
|
32
|
+
if (preparedRoute !== true) return;
|
|
33
|
+
|
|
34
|
+
// Descendant controllers adopt the staged seed during this update. Discard it only after
|
|
35
|
+
// their pre-effects and the resulting DOM have committed.
|
|
36
|
+
tick().then(() => {
|
|
37
|
+
if (!coordinator.isRouteStaged(state)) return;
|
|
38
|
+
coordinator.discardRouteData(state);
|
|
39
|
+
|
|
40
|
+
if (stateIdentity !== markedIdentity) {
|
|
41
|
+
markedIdentity = stateIdentity;
|
|
42
|
+
performance.mark("ridu:admin-route-ready");
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
});
|
|
5
46
|
</script>
|
|
6
47
|
|
|
7
48
|
<AdminNavigationProgress />
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { Route, Routes, useLocation } from "@hvniel/svelte-router";
|
|
2
|
+
import { Navigate, Route, Routes, useLocation } from "@hvniel/svelte-router";
|
|
3
3
|
|
|
4
4
|
import {
|
|
5
5
|
adminCreateFirstUserPath,
|
|
@@ -9,40 +9,42 @@
|
|
|
9
9
|
} from "@admin/core/routing/admin-paths";
|
|
10
10
|
import { getAdminRuntime } from "@admin/core/runtime/admin-runtime.svelte";
|
|
11
11
|
import CollectionListRoute from "@admin/features/collections/collection-list-route.svelte";
|
|
12
|
-
import BulkUploadRoute from "@admin/features/uploads/bulk-upload-route.svelte";
|
|
12
|
+
import BulkUploadRoute from "@admin/features/uploads/bulk-upload-route-loader.svelte";
|
|
13
13
|
import LoginRoute from "@admin/features/auth/login-route.svelte";
|
|
14
14
|
import CreateFirstUserRoute from "@admin/features/auth/create-first-user-route.svelte";
|
|
15
15
|
import ForgotPasswordRoute from "@admin/features/auth/forgot-password-route.svelte";
|
|
16
16
|
import ResetPasswordRoute from "@admin/features/auth/reset-password-route.svelte";
|
|
17
17
|
import RequestVerificationRoute from "@admin/features/auth/request-verification-route.svelte";
|
|
18
18
|
import VerifyEmailRoute from "@admin/features/auth/verify-email-route.svelte";
|
|
19
|
-
import AccountSecurityRoute from "@admin/features/
|
|
20
|
-
import AccountRoute from "@admin/features/
|
|
19
|
+
import AccountSecurityRoute from "@admin/features/account/account-security-route.svelte";
|
|
20
|
+
import AccountRoute from "@admin/features/account/account-route.svelte";
|
|
21
21
|
import DashboardRoute from "@admin/features/dashboard/dashboard-route.svelte";
|
|
22
22
|
import DocumentRoute from "@admin/features/documents/document-route-loader.svelte";
|
|
23
|
-
import VersionHistoryRoute from "@admin/features/versions/version-history-route.svelte";
|
|
23
|
+
import VersionHistoryRoute from "@admin/features/versions/version-history-route-loader.svelte";
|
|
24
24
|
|
|
25
25
|
import AdminLayout from "@admin/app/admin-layout.svelte";
|
|
26
26
|
import AdminCoreViewRoute from "@admin/app/admin-core-view-route.svelte";
|
|
27
|
-
import
|
|
27
|
+
import AdminExtensionRoute from "@admin/app/admin-extension-route.svelte";
|
|
28
28
|
import NotFoundRoute from "@admin/app/not-found-route.svelte";
|
|
29
29
|
|
|
30
30
|
const runtime = getAdminRuntime();
|
|
31
|
-
const location =
|
|
32
|
-
const requestedPath = $derived(
|
|
33
|
-
|
|
31
|
+
const location = useLocation();
|
|
32
|
+
const requestedPath = $derived(
|
|
33
|
+
`${location.current.pathname}${location.current.search}${location.current.hash}`
|
|
34
|
+
);
|
|
35
|
+
const postLoginPath = $derived(adminRedirectFromSearch(location.current.search));
|
|
34
36
|
</script>
|
|
35
37
|
|
|
36
38
|
{#if runtime.authenticated}
|
|
37
39
|
<Routes>
|
|
38
40
|
<Route path="login">
|
|
39
41
|
{#snippet element()}
|
|
40
|
-
<
|
|
42
|
+
<Navigate to={postLoginPath} replace />
|
|
41
43
|
{/snippet}
|
|
42
44
|
</Route>
|
|
43
45
|
<Route path="create-first-user">
|
|
44
46
|
{#snippet element()}
|
|
45
|
-
<
|
|
47
|
+
<Navigate to={adminRoutePatterns.home} replace />
|
|
46
48
|
{/snippet}
|
|
47
49
|
</Route>
|
|
48
50
|
<Route Component={AdminLayout}>
|
|
@@ -56,7 +58,12 @@
|
|
|
56
58
|
</Route>
|
|
57
59
|
<Route path="collections/:collection/trash" Component={CollectionListRoute} />
|
|
58
60
|
<Route path="collections/:collection/upload" Component={BulkUploadRoute} />
|
|
59
|
-
<Route path="collections/:collection/create
|
|
61
|
+
<Route path="collections/:collection/create">
|
|
62
|
+
{#snippet element()}
|
|
63
|
+
<AdminCoreViewRoute surface="collectionCreate" DefaultView={DocumentRoute} />
|
|
64
|
+
{/snippet}
|
|
65
|
+
</Route>
|
|
66
|
+
<Route path="collections/:collection/create/api">
|
|
60
67
|
{#snippet element()}
|
|
61
68
|
<AdminCoreViewRoute surface="collectionCreate" DefaultView={DocumentRoute} />
|
|
62
69
|
{/snippet}
|
|
@@ -65,19 +72,49 @@
|
|
|
65
72
|
path="collections/:collection/:document/versions/:revision?"
|
|
66
73
|
Component={VersionHistoryRoute}
|
|
67
74
|
/>
|
|
68
|
-
<Route path="collections/:collection/:document
|
|
75
|
+
<Route path="collections/:collection/:document">
|
|
76
|
+
{#snippet element()}
|
|
77
|
+
<AdminCoreViewRoute surface="collectionEdit" DefaultView={DocumentRoute} />
|
|
78
|
+
{/snippet}
|
|
79
|
+
</Route>
|
|
80
|
+
<Route path="collections/:collection/:document/api">
|
|
69
81
|
{#snippet element()}
|
|
70
82
|
<AdminCoreViewRoute surface="collectionEdit" DefaultView={DocumentRoute} />
|
|
71
83
|
{/snippet}
|
|
72
84
|
</Route>
|
|
85
|
+
{#each runtime.config.extensions.documentViews as view (`${view.collection ?? "*"}:${view.key}`)}
|
|
86
|
+
<Route
|
|
87
|
+
path={view.collection === undefined
|
|
88
|
+
? `collections/:collection/:document/${view.key}`
|
|
89
|
+
: `collections/${view.collection}/:document/${view.key}`}
|
|
90
|
+
Component={DocumentRoute}
|
|
91
|
+
/>
|
|
92
|
+
{/each}
|
|
73
93
|
<Route path="globals/:global/versions/:revision?" Component={VersionHistoryRoute} />
|
|
74
|
-
<Route path="globals/:global
|
|
94
|
+
<Route path="globals/:global">
|
|
75
95
|
{#snippet element()}
|
|
76
96
|
<AdminCoreViewRoute surface="global" DefaultView={DocumentRoute} />
|
|
77
97
|
{/snippet}
|
|
78
98
|
</Route>
|
|
79
|
-
|
|
80
|
-
|
|
99
|
+
<Route path="globals/:global/api">
|
|
100
|
+
{#snippet element()}
|
|
101
|
+
<AdminCoreViewRoute surface="global" DefaultView={DocumentRoute} />
|
|
102
|
+
{/snippet}
|
|
103
|
+
</Route>
|
|
104
|
+
{#each runtime.config.extensions.documentViews as view (`${view.collection ?? "*"}:${view.key}`)}
|
|
105
|
+
<Route
|
|
106
|
+
path={view.collection === undefined
|
|
107
|
+
? `globals/:global/${view.key}`
|
|
108
|
+
: `globals/${view.collection}/${view.key}`}
|
|
109
|
+
Component={DocumentRoute}
|
|
110
|
+
/>
|
|
111
|
+
{/each}
|
|
112
|
+
{#each runtime.config.extensions.routes as pluginRoute (pluginRoute.path)}
|
|
113
|
+
<Route path={pluginRoute.path}>
|
|
114
|
+
{#snippet element()}
|
|
115
|
+
<AdminExtensionRoute route={pluginRoute} />
|
|
116
|
+
{/snippet}
|
|
117
|
+
</Route>
|
|
81
118
|
{/each}
|
|
82
119
|
<Route path="*">
|
|
83
120
|
{#snippet element()}
|
|
@@ -91,7 +128,7 @@
|
|
|
91
128
|
<Route path="create-first-user" Component={CreateFirstUserRoute} />
|
|
92
129
|
<Route path="*">
|
|
93
130
|
{#snippet element()}
|
|
94
|
-
<
|
|
131
|
+
<Navigate to={adminCreateFirstUserPath()} replace />
|
|
95
132
|
{/snippet}
|
|
96
133
|
</Route>
|
|
97
134
|
</Routes>
|
|
@@ -99,7 +136,7 @@
|
|
|
99
136
|
<Routes>
|
|
100
137
|
<Route path="create-first-user">
|
|
101
138
|
{#snippet element()}
|
|
102
|
-
<
|
|
139
|
+
<Navigate to={adminRoutePatterns.login} replace />
|
|
103
140
|
{/snippet}
|
|
104
141
|
</Route>
|
|
105
142
|
<Route path="login" Component={LoginRoute} />
|
|
@@ -109,7 +146,7 @@
|
|
|
109
146
|
<Route path="verify-email" Component={VerifyEmailRoute} />
|
|
110
147
|
<Route path="*">
|
|
111
148
|
{#snippet element()}
|
|
112
|
-
<
|
|
149
|
+
<Navigate to={adminLoginPath(requestedPath)} replace />
|
|
113
150
|
{/snippet}
|
|
114
151
|
</Route>
|
|
115
152
|
</Routes>
|
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
|
|
4
4
|
import RiduLogo from "@admin/components/brand/ridu-logo.svelte";
|
|
5
5
|
import { Banner } from "@admin/components/ui/banner";
|
|
6
|
-
import { Button } from "@
|
|
6
|
+
import { Button } from "@riducms/ui";
|
|
7
7
|
import { getAdminRuntime } from "@admin/core/runtime/admin-runtime.svelte";
|
|
8
8
|
|
|
9
9
|
let { children }: { children: Snippet } = $props();
|
|
10
|
+
|
|
10
11
|
const runtime = getAdminRuntime();
|
|
11
12
|
const development = import.meta.hot !== undefined;
|
|
12
13
|
</script>
|
|
@@ -14,6 +15,7 @@
|
|
|
14
15
|
{#if runtime.loading}
|
|
15
16
|
<main
|
|
16
17
|
class="ridu-surface-grid grid min-h-screen place-items-center"
|
|
18
|
+
data-ridu-loading-surface="runtime"
|
|
17
19
|
aria-label={runtime.i18n.t("general:loadingSchema")}
|
|
18
20
|
>
|
|
19
21
|
<div class="grid justify-items-center gap-4 text-[13px] text-foreground-muted">
|