@quazardous/qdadm 1.19.3
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/LICENSE +21 -0
- package/README.md +111 -0
- package/package.json +101 -0
- package/src/assets/logo.svg +6 -0
- package/src/auth/SessionAuthAdapter.ts +459 -0
- package/src/auth/index.ts +15 -0
- package/src/chain/ActiveStack.ts +154 -0
- package/src/chain/StackHydrator.ts +292 -0
- package/src/chain/index.ts +25 -0
- package/src/chain/useActiveStack.ts +120 -0
- package/src/chain/useStackHydrator.ts +155 -0
- package/src/components/BoolCell.vue +34 -0
- package/src/components/InfoBanner.vue +73 -0
- package/src/components/QdadmRoot.vue +52 -0
- package/src/components/SeverityTag.vue +86 -0
- package/src/components/dialogs/BulkStatusDialog.vue +60 -0
- package/src/components/dialogs/MultiStepDialog.vue +331 -0
- package/src/components/dialogs/SimpleDialog.vue +122 -0
- package/src/components/dialogs/UnsavedChangesDialog.vue +80 -0
- package/src/components/display/BannerZone.vue +65 -0
- package/src/components/display/CardsGrid.vue +72 -0
- package/src/components/display/CopyableId.vue +84 -0
- package/src/components/display/EmptyState.vue +62 -0
- package/src/components/display/IntensityBar.vue +190 -0
- package/src/components/display/RichCardsGrid.vue +101 -0
- package/src/components/edit/FormActions.vue +78 -0
- package/src/components/edit/FormField.vue +82 -0
- package/src/components/edit/FormInput.vue +158 -0
- package/src/components/edit/FormPage.vue +260 -0
- package/src/components/edit/FormTab.vue +217 -0
- package/src/components/edit/FormTabs.vue +120 -0
- package/src/components/edit/LookupField.vue +406 -0
- package/src/components/edit/LookupPickerDialog.vue +230 -0
- package/src/components/editors/JsonEditorFoldable.vue +470 -0
- package/src/components/editors/JsonStructuredField.vue +264 -0
- package/src/components/editors/JsonViewer.vue +51 -0
- package/src/components/editors/KeyValueEditor.vue +314 -0
- package/src/components/editors/LanguageEditor.vue +259 -0
- package/src/components/editors/PermissionEditor.vue +558 -0
- package/src/components/editors/ScopeEditor.vue +372 -0
- package/src/components/editors/VanillaJsonEditor.vue +183 -0
- package/src/components/index.ts +83 -0
- package/src/components/item/FieldGroups.vue +392 -0
- package/src/components/layout/AppLayout.vue +1032 -0
- package/src/components/layout/BaseLayout.vue +190 -0
- package/src/components/layout/Breadcrumb.vue +55 -0
- package/src/components/layout/DashboardLayout.vue +104 -0
- package/src/components/layout/FormLayout.vue +256 -0
- package/src/components/layout/ListLayout.vue +278 -0
- package/src/components/layout/PageHeader.vue +156 -0
- package/src/components/layout/PageLayout.vue +126 -0
- package/src/components/layout/PageNav.vue +192 -0
- package/src/components/layout/SidebarBox.vue +87 -0
- package/src/components/layout/Zone.vue +182 -0
- package/src/components/layout/defaults/DefaultBreadcrumb.vue +149 -0
- package/src/components/layout/defaults/DefaultFooter.vue +89 -0
- package/src/components/layout/defaults/DefaultFormActions.vue +67 -0
- package/src/components/layout/defaults/DefaultHeader.vue +78 -0
- package/src/components/layout/defaults/DefaultMenu.vue +188 -0
- package/src/components/layout/defaults/DefaultPagination.vue +75 -0
- package/src/components/layout/defaults/DefaultTable.vue +137 -0
- package/src/components/layout/defaults/DefaultUserInfo.vue +111 -0
- package/src/components/layout/defaults/index.ts +16 -0
- package/src/components/lists/ActionButtons.vue +49 -0
- package/src/components/lists/ActionColumn.vue +40 -0
- package/src/components/lists/FilterBar.vue +54 -0
- package/src/components/lists/ListPage.vue +467 -0
- package/src/components/pages/LoginPage.vue +334 -0
- package/src/components/pages/NotFoundPage.vue +98 -0
- package/src/components/show/ShowDisplay.vue +343 -0
- package/src/components/show/ShowField.vue +67 -0
- package/src/components/show/ShowPage.vue +431 -0
- package/src/composables/index.ts +155 -0
- package/src/composables/useApp.ts +67 -0
- package/src/composables/useAuth.ts +98 -0
- package/src/composables/useBareForm.ts +319 -0
- package/src/composables/useBreadcrumb.ts +252 -0
- package/src/composables/useChildPage.ts +113 -0
- package/src/composables/useCurrentEntity.ts +60 -0
- package/src/composables/useDeferred.ts +94 -0
- package/src/composables/useDirtyState.ts +138 -0
- package/src/composables/useEntityItemFormPage.ts +942 -0
- package/src/composables/useEntityItemFormPage.types.ts +451 -0
- package/src/composables/useEntityItemPage.ts +438 -0
- package/src/composables/useEntityItemShowPage.ts +722 -0
- package/src/composables/useFieldManager.ts +692 -0
- package/src/composables/useForm.ts +544 -0
- package/src/composables/useGuardStore.ts +53 -0
- package/src/composables/useHooks.ts +56 -0
- package/src/composables/useInfoBanner.ts +217 -0
- package/src/composables/useJsonSyntax.ts +122 -0
- package/src/composables/useLayoutResolver.ts +329 -0
- package/src/composables/useListPage.ts +1535 -0
- package/src/composables/useListPage.types.ts +437 -0
- package/src/composables/useListPage.utils.ts +101 -0
- package/src/composables/useNavContext.ts +439 -0
- package/src/composables/useNavigation.ts +216 -0
- package/src/composables/useOptionsLookup.ts +323 -0
- package/src/composables/usePageTitle.ts +84 -0
- package/src/composables/useSSEBridge.ts +142 -0
- package/src/composables/useSemanticBreadcrumb.ts +222 -0
- package/src/composables/useSidebarState.ts +24 -0
- package/src/composables/useSignals.ts +52 -0
- package/src/composables/useUnsavedChangesGuard.ts +155 -0
- package/src/composables/useUserImpersonator.ts +317 -0
- package/src/composables/useZoneRegistry.ts +252 -0
- package/src/core/bundles.ts +558 -0
- package/src/core/decorator.ts +420 -0
- package/src/core/extension.ts +470 -0
- package/src/core/index.ts +59 -0
- package/src/deferred/DeferredRegistry.ts +353 -0
- package/src/deferred/index.ts +15 -0
- package/src/editors/index.ts +12 -0
- package/src/entity/EntityManager.cache.ts +530 -0
- package/src/entity/EntityManager.crud.ts +615 -0
- package/src/entity/EntityManager.interface.ts +78 -0
- package/src/entity/EntityManager.query.ts +221 -0
- package/src/entity/EntityManager.relations.ts +151 -0
- package/src/entity/EntityManager.ts +944 -0
- package/src/entity/EntityManager.types.ts +288 -0
- package/src/entity/auth/CompositeAuthAdapter.ts +194 -0
- package/src/entity/auth/EntityAuthAdapter.ts +119 -0
- package/src/entity/auth/PermissiveAdapter.ts +43 -0
- package/src/entity/auth/RoleHierarchy.ts +128 -0
- package/src/entity/auth/SecurityChecker.ts +202 -0
- package/src/entity/auth/factory.ts +203 -0
- package/src/entity/auth/index.ts +47 -0
- package/src/entity/factory.test.js +189 -0
- package/src/entity/factory.ts +146 -0
- package/src/entity/index.ts +49 -0
- package/src/entity/storage/ApiStorage.ts +228 -0
- package/src/entity/storage/IStorage.ts +100 -0
- package/src/entity/storage/LocalStorage.ts +200 -0
- package/src/entity/storage/MemoryStorage.ts +184 -0
- package/src/entity/storage/MockApiStorage.ts +318 -0
- package/src/entity/storage/SdkStorage.ts +377 -0
- package/src/entity/storage/factory.test.js +159 -0
- package/src/entity/storage/factory.ts +209 -0
- package/src/entity/storage/index.ts +75 -0
- package/src/gen/FieldMapper.ts +122 -0
- package/src/gen/StorageProfileFactory.ts +93 -0
- package/src/gen/connectors/BaseConnector.ts +150 -0
- package/src/gen/connectors/ManualConnector.test.js +499 -0
- package/src/gen/connectors/ManualConnector.ts +414 -0
- package/src/gen/connectors/OpenAPIConnector.test.js +836 -0
- package/src/gen/connectors/OpenAPIConnector.ts +693 -0
- package/src/gen/connectors/__fixtures__/sample-openapi.json +311 -0
- package/src/gen/connectors/index.ts +27 -0
- package/src/gen/createManagers.ts +245 -0
- package/src/gen/decorators.ts +134 -0
- package/src/gen/generateManagers.test.js +540 -0
- package/src/gen/generateManagers.ts +398 -0
- package/src/gen/index.ts +66 -0
- package/src/gen/schema.ts +248 -0
- package/src/gen/vite-plugin.ts +114 -0
- package/src/generated/managers/testManager.js +45 -0
- package/src/generated/managers/testManager.ts +46 -0
- package/src/hooks/HookRegistry.ts +16 -0
- package/src/hooks/index.ts +15 -0
- package/src/i18n/I18n.ts +344 -0
- package/src/i18n/IncrementalDomainProvider.ts +153 -0
- package/src/i18n/InlineTranslationProvider.ts +4 -0
- package/src/i18n/LazyTranslationProvider.ts +102 -0
- package/src/i18n/MessagesRegistry.ts +4 -0
- package/src/i18n/Resolver.ts +4 -0
- package/src/i18n/__tests__/I18n.test.ts +169 -0
- package/src/i18n/__tests__/IncrementalDomainProvider.test.ts +146 -0
- package/src/i18n/__tests__/LazyTranslationProvider.test.ts +100 -0
- package/src/i18n/__tests__/Resolver.test.ts +271 -0
- package/src/i18n/defaults/DefaultCoreProvider.ts +28 -0
- package/src/i18n/defaults/core.en.yml +55 -0
- package/src/i18n/defaults/core.fr.yml +55 -0
- package/src/i18n/index.ts +55 -0
- package/src/i18n/loaders/raw-modules.d.ts +15 -0
- package/src/i18n/loaders/yaml.ts +35 -0
- package/src/i18n/strategies.ts +4 -0
- package/src/i18n/types.ts +34 -0
- package/src/i18n/useI18n.ts +34 -0
- package/src/index.ts +453 -0
- package/src/kernel/EventRouter.ts +23 -0
- package/src/kernel/Kernel.api.ts +79 -0
- package/src/kernel/Kernel.auth.ts +120 -0
- package/src/kernel/Kernel.i18n.ts +29 -0
- package/src/kernel/Kernel.modules.ts +170 -0
- package/src/kernel/Kernel.registries.ts +237 -0
- package/src/kernel/Kernel.routing.ts +334 -0
- package/src/kernel/Kernel.ts +460 -0
- package/src/kernel/Kernel.types.ts +263 -0
- package/src/kernel/Kernel.vue.ts +304 -0
- package/src/kernel/KernelContext.entities.ts +80 -0
- package/src/kernel/KernelContext.events.ts +57 -0
- package/src/kernel/KernelContext.i18n.ts +37 -0
- package/src/kernel/KernelContext.permissions.ts +38 -0
- package/src/kernel/KernelContext.routing.ts +280 -0
- package/src/kernel/KernelContext.ts +252 -0
- package/src/kernel/KernelContext.types.ts +173 -0
- package/src/kernel/KernelContext.zones.ts +54 -0
- package/src/kernel/Module.ts +169 -0
- package/src/kernel/ModuleLoader.ts +645 -0
- package/src/kernel/SSEBridge.ts +11 -0
- package/src/kernel/SignalBus.ts +48 -0
- package/src/kernel/index.ts +56 -0
- package/src/module/index.ts +33 -0
- package/src/module/moduleRegistry.ts +492 -0
- package/src/modules/debug/AuthCollector.ts +501 -0
- package/src/modules/debug/Collector.ts +20 -0
- package/src/modules/debug/DebugBridge.ts +14 -0
- package/src/modules/debug/DebugModule.ts +220 -0
- package/src/modules/debug/EntitiesCollector.ts +839 -0
- package/src/modules/debug/ErrorCollector.ts +4 -0
- package/src/modules/debug/I18nCollector.ts +9 -0
- package/src/modules/debug/LocalStorageAdapter.ts +7 -0
- package/src/modules/debug/RouterCollector.ts +449 -0
- package/src/modules/debug/SignalCollector.ts +4 -0
- package/src/modules/debug/ToastCollector.ts +4 -0
- package/src/modules/debug/ZonesCollector.ts +447 -0
- package/src/modules/debug/components/DebugBar.vue +31 -0
- package/src/modules/debug/components/adminPanelsConfig.ts +42 -0
- package/src/modules/debug/components/index.ts +9 -0
- package/src/modules/debug/components/panels/AuthPanel.vue +267 -0
- package/src/modules/debug/components/panels/EntitiesPanel.vue +572 -0
- package/src/modules/debug/components/panels/I18nPanel.vue +738 -0
- package/src/modules/debug/components/panels/RouterPanel.vue +440 -0
- package/src/modules/debug/components/panels/ZonesPanel.vue +133 -0
- package/src/modules/debug/components/panels/index.ts +16 -0
- package/src/modules/debug/index.ts +58 -0
- package/src/modules/debug/styles.scss +2671 -0
- package/src/notifications/NotificationBadge.vue +35 -0
- package/src/notifications/NotificationListener.vue +71 -0
- package/src/notifications/NotificationModule.ts +76 -0
- package/src/notifications/NotificationPanel.vue +478 -0
- package/src/notifications/NotificationStore.ts +288 -0
- package/src/notifications/index.ts +42 -0
- package/src/notifications/styles.scss +32 -0
- package/src/orchestrator/Orchestrator.ts +427 -0
- package/src/orchestrator/index.ts +8 -0
- package/src/orchestrator/useOrchestrator.ts +80 -0
- package/src/plugin.ts +251 -0
- package/src/query/FilterQuery.ts +306 -0
- package/src/query/QueryExecutor.ts +341 -0
- package/src/query/index.ts +16 -0
- package/src/security/EntityRolesProvider.ts +385 -0
- package/src/security/PermissionMatcher.ts +152 -0
- package/src/security/PermissionRegistry.ts +273 -0
- package/src/security/PersistableRolesProvider.ts +584 -0
- package/src/security/RolesManager.ts +136 -0
- package/src/security/RolesProvider.ts +167 -0
- package/src/security/RolesProviderStorage.ts +211 -0
- package/src/security/SecurityModule.ts +94 -0
- package/src/security/StaticRolesProvider.ts +117 -0
- package/src/security/UsersManager.ts +163 -0
- package/src/security/index.ts +77 -0
- package/src/security/pages/RoleForm.vue +276 -0
- package/src/security/pages/RoleList.vue +123 -0
- package/src/styles/_alerts.scss +95 -0
- package/src/styles/_buttons.scss +391 -0
- package/src/styles/_cards.scss +241 -0
- package/src/styles/_code.scss +78 -0
- package/src/styles/_dialogs.scss +55 -0
- package/src/styles/_filter-bar.scss +70 -0
- package/src/styles/_forms.scss +434 -0
- package/src/styles/_helpers.scss +153 -0
- package/src/styles/_lists.scss +225 -0
- package/src/styles/_main.scss +356 -0
- package/src/styles/_markdown.scss +88 -0
- package/src/styles/_responsive.scss +255 -0
- package/src/styles/_show-pages.scss +186 -0
- package/src/styles/_sidebar.scss +380 -0
- package/src/styles/_states.scss +115 -0
- package/src/styles/_stats.scss +47 -0
- package/src/styles/_variables.scss +224 -0
- package/src/styles/index.scss +38 -0
- package/src/styles/theme/_components.scss +331 -0
- package/src/styles/theme/_index.scss +10 -0
- package/src/styles/theme/_tokens.scss +147 -0
- package/src/styles/theme/_utilities.scss +175 -0
- package/src/toast/ToastBridgeModule.ts +68 -0
- package/src/toast/ToastListener.vue +55 -0
- package/src/toast/index.ts +26 -0
- package/src/toast/useSignalToast.ts +154 -0
- package/src/types/index.ts +285 -0
- package/src/types/pluralize.d.ts +19 -0
- package/src/types/quarkernel.d.ts +50 -0
- package/src/utils/formatters.ts +174 -0
- package/src/utils/index.ts +35 -0
- package/src/utils/transformers.ts +131 -0
- package/src/vite/qdadmDebugPlugin.ts +401 -0
- package/src/vite-env.d.ts +50 -0
- package/src/zones/ZoneRegistry.ts +934 -0
- package/src/zones/index.ts +29 -0
- package/src/zones/zones.ts +191 -0
|
@@ -0,0 +1,451 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useEntityItemFormPage - Type definitions
|
|
3
|
+
*
|
|
4
|
+
* Extracted from useEntityItemFormPage.ts for maintainability.
|
|
5
|
+
*/
|
|
6
|
+
import type { Ref, ComputedRef } from 'vue'
|
|
7
|
+
import type { RouteLocationNormalizedLoaded, Router } from 'vue-router'
|
|
8
|
+
import type { GuardDialogState } from './useUnsavedChangesGuard'
|
|
9
|
+
import type { BreadcrumbDisplayItem } from './useBreadcrumb'
|
|
10
|
+
import type { ParentConfig, EntityManager } from './useEntityItemPage'
|
|
11
|
+
import type { FieldGroup, GroupDefinition, GroupOptions, MoveFieldPosition } from './useFieldManager'
|
|
12
|
+
import type { StackHydratorReturn } from '../chain/useStackHydrator'
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Orchestrator interface
|
|
16
|
+
*/
|
|
17
|
+
export interface Orchestrator {
|
|
18
|
+
get: (entityName: string) => EntityManager
|
|
19
|
+
toast?: {
|
|
20
|
+
success: (summary: string, detail?: string, emitter?: unknown) => void
|
|
21
|
+
error: (summary: string, detail?: string, emitter?: unknown) => void
|
|
22
|
+
warn: (summary: string, detail?: string, emitter?: unknown) => void
|
|
23
|
+
info: (summary: string, detail?: string, emitter?: unknown) => void
|
|
24
|
+
[key: string]: ((summary: string, detail?: string, emitter?: unknown) => void) | undefined
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Field definition from EntityManager schema
|
|
30
|
+
*/
|
|
31
|
+
export interface FieldDefinition {
|
|
32
|
+
name: string
|
|
33
|
+
type?: string
|
|
34
|
+
schemaType?: string
|
|
35
|
+
label?: string
|
|
36
|
+
required?: boolean
|
|
37
|
+
default?: unknown
|
|
38
|
+
options?: unknown[]
|
|
39
|
+
optionLabel?: string
|
|
40
|
+
optionValue?: string
|
|
41
|
+
placeholder?: string
|
|
42
|
+
disabled?: boolean
|
|
43
|
+
readonly?: boolean
|
|
44
|
+
editable?: boolean
|
|
45
|
+
reference?: string
|
|
46
|
+
validate?: (value: unknown, formData: unknown) => boolean | string | null | undefined
|
|
47
|
+
[key: string]: unknown
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Resolved field configuration for form rendering
|
|
52
|
+
*/
|
|
53
|
+
export interface ResolvedFieldConfig extends FieldDefinition {
|
|
54
|
+
name: string
|
|
55
|
+
type: string
|
|
56
|
+
schemaType: string
|
|
57
|
+
label: string
|
|
58
|
+
group?: string
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Toast helper interface
|
|
63
|
+
*/
|
|
64
|
+
export interface ToastHelper {
|
|
65
|
+
add: (options: {
|
|
66
|
+
severity: 'success' | 'error' | 'warn' | 'info'
|
|
67
|
+
summary: string
|
|
68
|
+
detail?: string
|
|
69
|
+
emitter?: unknown
|
|
70
|
+
life?: number
|
|
71
|
+
}) => void
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Action configuration
|
|
76
|
+
*/
|
|
77
|
+
export interface ActionConfig {
|
|
78
|
+
name: string
|
|
79
|
+
label: string
|
|
80
|
+
icon?: string
|
|
81
|
+
severity?: string
|
|
82
|
+
onClick: () => void | Promise<void>
|
|
83
|
+
visible?: (ctx: { isEdit: boolean; dirty: boolean }) => boolean
|
|
84
|
+
disabled?: (ctx: { dirty: boolean; saving: boolean }) => boolean
|
|
85
|
+
loading?: () => boolean
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Resolved action for rendering
|
|
90
|
+
*/
|
|
91
|
+
export interface ResolvedAction extends ActionConfig {
|
|
92
|
+
isLoading: boolean
|
|
93
|
+
isDisabled: boolean
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Error summary item
|
|
98
|
+
*/
|
|
99
|
+
export interface ErrorSummaryItem {
|
|
100
|
+
field: string
|
|
101
|
+
label: string
|
|
102
|
+
message: string
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Page title parts for PageHeader
|
|
107
|
+
*/
|
|
108
|
+
export interface PageTitleParts {
|
|
109
|
+
action: string
|
|
110
|
+
entityName: string | undefined
|
|
111
|
+
entityLabel: string | undefined
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Form props for FormPage component
|
|
116
|
+
*/
|
|
117
|
+
export interface FormPageProps {
|
|
118
|
+
isEdit: boolean
|
|
119
|
+
mode: 'create' | 'edit'
|
|
120
|
+
loading: boolean
|
|
121
|
+
saving: boolean
|
|
122
|
+
dirty: boolean
|
|
123
|
+
title: string
|
|
124
|
+
titleParts: PageTitleParts
|
|
125
|
+
fields: ResolvedFieldConfig[]
|
|
126
|
+
groups: FieldGroup<ResolvedFieldConfig>[]
|
|
127
|
+
actions: ResolvedAction[]
|
|
128
|
+
canSave: boolean
|
|
129
|
+
canDelete: boolean
|
|
130
|
+
errors: Record<string, string>
|
|
131
|
+
hasErrors: boolean
|
|
132
|
+
errorSummary: ErrorSummaryItem[] | null
|
|
133
|
+
submitted: boolean
|
|
134
|
+
guardDialog: GuardDialogState | null
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Form events for FormPage component
|
|
139
|
+
*/
|
|
140
|
+
export interface FormPageEvents {
|
|
141
|
+
save: () => Promise<unknown>
|
|
142
|
+
saveAndClose: () => Promise<unknown>
|
|
143
|
+
cancel: () => void
|
|
144
|
+
delete: () => void
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Axios-like error interface
|
|
149
|
+
*/
|
|
150
|
+
export interface AxiosError {
|
|
151
|
+
response?: {
|
|
152
|
+
data?: {
|
|
153
|
+
detail?: string
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
message?: string
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* PrimeVue confirm service interface
|
|
161
|
+
*/
|
|
162
|
+
export interface ConfirmService {
|
|
163
|
+
require: (options: {
|
|
164
|
+
message: string
|
|
165
|
+
header: string
|
|
166
|
+
icon: string
|
|
167
|
+
acceptClass?: string
|
|
168
|
+
accept: () => void
|
|
169
|
+
}) => void
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Options for useEntityItemFormPage
|
|
174
|
+
*/
|
|
175
|
+
export interface UseEntityItemFormPageOptions<T extends Record<string, unknown> = Record<string, unknown>> {
|
|
176
|
+
/** Entity name for EntityManager */
|
|
177
|
+
entity: string
|
|
178
|
+
/** Custom function to extract ID from route */
|
|
179
|
+
getId?: (() => string | number | null) | null
|
|
180
|
+
/** Route name suffix for create mode (default: 'create') */
|
|
181
|
+
createRouteSuffix?: string
|
|
182
|
+
/** Route name suffix for edit mode (default: 'edit') */
|
|
183
|
+
editRouteSuffix?: string
|
|
184
|
+
/** Auto-load entity on mount (default: true) */
|
|
185
|
+
loadOnMount?: boolean
|
|
186
|
+
/** Enable unsaved changes guard (default: true) */
|
|
187
|
+
enableGuard?: boolean
|
|
188
|
+
/** Use PATCH instead of PUT for updates (default: false) */
|
|
189
|
+
usePatch?: boolean
|
|
190
|
+
/** Transform loaded data before setting form */
|
|
191
|
+
transformLoad?: (data: unknown) => T
|
|
192
|
+
/** Transform form data before saving */
|
|
193
|
+
transformSave?: (data: unknown) => unknown
|
|
194
|
+
/** Callback on successful load */
|
|
195
|
+
onLoadSuccess?: ((data: T) => Promise<void> | void) | null
|
|
196
|
+
/** Callback on successful save */
|
|
197
|
+
onSaveSuccess?: ((data: unknown, andClose: boolean) => Promise<void> | void) | null
|
|
198
|
+
/** Callback on successful delete */
|
|
199
|
+
onDeleteSuccess?: (() => Promise<void> | void) | null
|
|
200
|
+
/** Validate field on blur (default: true) */
|
|
201
|
+
validateOnBlur?: boolean
|
|
202
|
+
/** Validate all fields before submit (default: true) */
|
|
203
|
+
validateOnSubmit?: boolean
|
|
204
|
+
/** Show error summary at top of form (default: false) */
|
|
205
|
+
showErrorSummary?: boolean
|
|
206
|
+
/** Auto-generate fields from manager schema (default: true) */
|
|
207
|
+
generateFormFields?: boolean
|
|
208
|
+
/** Custom dirty state getter */
|
|
209
|
+
getDirtyState?: (() => Record<string, unknown>) | null
|
|
210
|
+
/** Override manager.entityName */
|
|
211
|
+
entityName?: string
|
|
212
|
+
/** Override manager.routePrefix */
|
|
213
|
+
routePrefix?: string
|
|
214
|
+
/** Override manager.getInitialData() */
|
|
215
|
+
initialData?: Record<string, unknown>
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Options for generateFields
|
|
220
|
+
*/
|
|
221
|
+
export interface GenerateFieldsOptions {
|
|
222
|
+
/** Only include these fields */
|
|
223
|
+
only?: string[] | null
|
|
224
|
+
/** Exclude these fields (merged with excludeField calls) */
|
|
225
|
+
exclude?: string[]
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Options for addField
|
|
230
|
+
*/
|
|
231
|
+
export interface AddFieldOptions {
|
|
232
|
+
/** Insert after this field */
|
|
233
|
+
after?: string | null
|
|
234
|
+
/** Insert before this field */
|
|
235
|
+
before?: string | null
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Options for addSaveAction
|
|
240
|
+
*/
|
|
241
|
+
export interface AddSaveActionOptions {
|
|
242
|
+
/** Custom label */
|
|
243
|
+
label?: string
|
|
244
|
+
/** Close after save (default: true) */
|
|
245
|
+
andClose?: boolean
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Options for addDeleteAction
|
|
250
|
+
*/
|
|
251
|
+
export interface AddDeleteActionOptions {
|
|
252
|
+
/** Custom label (default: 'Delete') */
|
|
253
|
+
label?: string
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Options for addCancelAction
|
|
258
|
+
*/
|
|
259
|
+
export interface AddCancelActionOptions {
|
|
260
|
+
/** Custom label (default: 'Cancel') */
|
|
261
|
+
label?: string
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Return type for useEntityItemFormPage
|
|
266
|
+
*/
|
|
267
|
+
export interface UseEntityItemFormPageReturn<T extends Record<string, unknown> = Record<string, unknown>> {
|
|
268
|
+
// Manager access
|
|
269
|
+
manager: EntityManager
|
|
270
|
+
|
|
271
|
+
// Mode
|
|
272
|
+
mode: ComputedRef<'create' | 'edit'>
|
|
273
|
+
isEdit: ComputedRef<boolean>
|
|
274
|
+
isCreate: ComputedRef<boolean>
|
|
275
|
+
entityId: ComputedRef<string | number | null>
|
|
276
|
+
|
|
277
|
+
// Parent chain (from route.meta.parent, supports N-level nesting)
|
|
278
|
+
parentConfig: ComputedRef<ParentConfig | null>
|
|
279
|
+
parentId: ComputedRef<string | number | null>
|
|
280
|
+
parentData: ComputedRef<unknown | null>
|
|
281
|
+
parentChain: Ref<Map<number, unknown>>
|
|
282
|
+
getChainDepth: (config?: ParentConfig | null) => number
|
|
283
|
+
|
|
284
|
+
// State
|
|
285
|
+
data: Ref<T>
|
|
286
|
+
loading: Ref<boolean>
|
|
287
|
+
saving: Ref<boolean>
|
|
288
|
+
dirty: Ref<boolean>
|
|
289
|
+
dirtyFields: Ref<string[]>
|
|
290
|
+
originalData: Ref<unknown>
|
|
291
|
+
|
|
292
|
+
// Actions
|
|
293
|
+
load: () => Promise<void>
|
|
294
|
+
submit: (andClose?: boolean) => Promise<unknown>
|
|
295
|
+
cancel: () => void
|
|
296
|
+
remove: () => Promise<void>
|
|
297
|
+
confirmDelete: () => void
|
|
298
|
+
reset: () => void
|
|
299
|
+
goToList: () => void
|
|
300
|
+
findListRoute: () => { name: string; params?: Record<string, unknown> }
|
|
301
|
+
|
|
302
|
+
// Dirty tracking
|
|
303
|
+
takeSnapshot: () => void
|
|
304
|
+
checkDirty: () => void
|
|
305
|
+
isFieldDirty: (fieldPath: string) => boolean
|
|
306
|
+
|
|
307
|
+
// Field management
|
|
308
|
+
fields: ComputedRef<ResolvedFieldConfig[]>
|
|
309
|
+
generateFields: (options?: GenerateFieldsOptions) => UseEntityItemFormPageReturn<T>
|
|
310
|
+
resolveReferences: () => Promise<void>
|
|
311
|
+
addField: (
|
|
312
|
+
name: string,
|
|
313
|
+
fieldConfig: Partial<FieldDefinition>,
|
|
314
|
+
options?: AddFieldOptions
|
|
315
|
+
) => UseEntityItemFormPageReturn<T>
|
|
316
|
+
updateField: (name: string, fieldConfig: Partial<FieldDefinition>) => UseEntityItemFormPageReturn<T>
|
|
317
|
+
removeField: (name: string) => UseEntityItemFormPageReturn<T>
|
|
318
|
+
excludeField: (name: string) => UseEntityItemFormPageReturn<T>
|
|
319
|
+
getFieldConfig: (name: string) => ResolvedFieldConfig | undefined
|
|
320
|
+
getFields: () => ResolvedFieldConfig[]
|
|
321
|
+
setFieldOrder: (order: string[]) => UseEntityItemFormPageReturn<T>
|
|
322
|
+
moveField: (name: string, position: MoveFieldPosition) => UseEntityItemFormPageReturn<T>
|
|
323
|
+
|
|
324
|
+
// Group management
|
|
325
|
+
groups: ComputedRef<FieldGroup<ResolvedFieldConfig>[]>
|
|
326
|
+
group: (name: string, fieldsOrOptions?: string[] | GroupOptions, options?: GroupOptions) => UseEntityItemFormPageReturn<T>
|
|
327
|
+
defineGroups: (definitions: Record<string, GroupDefinition>) => UseEntityItemFormPageReturn<T>
|
|
328
|
+
getGroup: (name: string) => FieldGroup<ResolvedFieldConfig> | undefined
|
|
329
|
+
getFieldsByGroup: (groupName: string) => ResolvedFieldConfig[]
|
|
330
|
+
getUngroupedFields: () => ResolvedFieldConfig[]
|
|
331
|
+
|
|
332
|
+
// Validation
|
|
333
|
+
errors: Ref<Record<string, string>>
|
|
334
|
+
hasErrors: ComputedRef<boolean>
|
|
335
|
+
errorSummary: ComputedRef<ErrorSummaryItem[]>
|
|
336
|
+
submitted: Ref<boolean>
|
|
337
|
+
validate: () => boolean
|
|
338
|
+
validateField: (name: string) => string | null
|
|
339
|
+
clearErrors: () => void
|
|
340
|
+
clearFieldError: (name: string) => void
|
|
341
|
+
getFieldError: (name: string) => string | null
|
|
342
|
+
handleFieldBlur: (name: string) => void
|
|
343
|
+
|
|
344
|
+
// Action management
|
|
345
|
+
actions: ComputedRef<ResolvedAction[]>
|
|
346
|
+
addAction: (name: string, actionConfig: Omit<ActionConfig, 'name'>) => void
|
|
347
|
+
removeAction: (name: string) => void
|
|
348
|
+
getActions: () => ResolvedAction[]
|
|
349
|
+
addSaveAction: (options?: AddSaveActionOptions) => void
|
|
350
|
+
addDeleteAction: (options?: AddDeleteActionOptions) => void
|
|
351
|
+
addCancelAction: (options?: AddCancelActionOptions) => void
|
|
352
|
+
|
|
353
|
+
// Permissions
|
|
354
|
+
canSave: ComputedRef<boolean>
|
|
355
|
+
canDeleteRecord: ComputedRef<boolean>
|
|
356
|
+
|
|
357
|
+
// Breadcrumb
|
|
358
|
+
breadcrumb: ComputedRef<BreadcrumbDisplayItem[]>
|
|
359
|
+
|
|
360
|
+
// Guard dialog (for UnsavedChangesDialog - pass to PageLayout)
|
|
361
|
+
guardDialog: GuardDialogState | null
|
|
362
|
+
|
|
363
|
+
// Title helpers
|
|
364
|
+
entityLabel: ComputedRef<string>
|
|
365
|
+
pageTitle: ComputedRef<string>
|
|
366
|
+
pageTitleParts: ComputedRef<PageTitleParts>
|
|
367
|
+
|
|
368
|
+
// Utilities
|
|
369
|
+
toast: ToastHelper
|
|
370
|
+
confirm: ConfirmService
|
|
371
|
+
router: Router
|
|
372
|
+
route: RouteLocationNormalizedLoaded
|
|
373
|
+
|
|
374
|
+
// FormPage integration
|
|
375
|
+
props: ComputedRef<FormPageProps>
|
|
376
|
+
events: FormPageEvents
|
|
377
|
+
|
|
378
|
+
// Stack hydrator (for setting entity data on navigation context)
|
|
379
|
+
hydrator: StackHydratorReturn
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Type mapping from schema types to input component types
|
|
384
|
+
*/
|
|
385
|
+
export const TYPE_MAPPINGS: Record<string, string> = {
|
|
386
|
+
text: 'text',
|
|
387
|
+
string: 'text',
|
|
388
|
+
email: 'email',
|
|
389
|
+
password: 'password',
|
|
390
|
+
number: 'number',
|
|
391
|
+
integer: 'number',
|
|
392
|
+
float: 'number',
|
|
393
|
+
boolean: 'boolean',
|
|
394
|
+
checkbox: 'boolean',
|
|
395
|
+
select: 'select',
|
|
396
|
+
dropdown: 'select',
|
|
397
|
+
date: 'date',
|
|
398
|
+
datetime: 'datetime',
|
|
399
|
+
textarea: 'textarea',
|
|
400
|
+
array: 'array',
|
|
401
|
+
object: 'object',
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* Built-in validators by type
|
|
406
|
+
*/
|
|
407
|
+
export const TYPE_VALIDATORS: Record<string, (value: unknown) => boolean | string> = {
|
|
408
|
+
email: (value) => {
|
|
409
|
+
if (!value) return true // Empty handled by required
|
|
410
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
|
|
411
|
+
return emailRegex.test(value as string) || 'Invalid email address'
|
|
412
|
+
},
|
|
413
|
+
number: (value) => {
|
|
414
|
+
if (value === null || value === undefined || value === '') return true
|
|
415
|
+
return !isNaN(Number(value)) || 'Must be a number'
|
|
416
|
+
},
|
|
417
|
+
integer: (value) => {
|
|
418
|
+
if (value === null || value === undefined || value === '') return true
|
|
419
|
+
return Number.isInteger(Number(value)) || 'Must be an integer'
|
|
420
|
+
},
|
|
421
|
+
url: (value) => {
|
|
422
|
+
if (!value) return true
|
|
423
|
+
try {
|
|
424
|
+
new URL(value as string)
|
|
425
|
+
return true
|
|
426
|
+
} catch {
|
|
427
|
+
return 'Invalid URL'
|
|
428
|
+
}
|
|
429
|
+
},
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* Helper: Convert snake_case to Title Case
|
|
434
|
+
*/
|
|
435
|
+
export function snakeCaseToTitle(str: string): string {
|
|
436
|
+
if (!str) return ''
|
|
437
|
+
return str
|
|
438
|
+
.split('_')
|
|
439
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
440
|
+
.join(' ')
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
/**
|
|
444
|
+
* Check if a value is "empty" for required validation
|
|
445
|
+
*/
|
|
446
|
+
export function isEmpty(value: unknown): boolean {
|
|
447
|
+
if (value === null || value === undefined) return true
|
|
448
|
+
if (typeof value === 'string') return value.trim() === ''
|
|
449
|
+
if (Array.isArray(value)) return value.length === 0
|
|
450
|
+
return false
|
|
451
|
+
}
|