@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.
Files changed (291) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +111 -0
  3. package/package.json +101 -0
  4. package/src/assets/logo.svg +6 -0
  5. package/src/auth/SessionAuthAdapter.ts +459 -0
  6. package/src/auth/index.ts +15 -0
  7. package/src/chain/ActiveStack.ts +154 -0
  8. package/src/chain/StackHydrator.ts +292 -0
  9. package/src/chain/index.ts +25 -0
  10. package/src/chain/useActiveStack.ts +120 -0
  11. package/src/chain/useStackHydrator.ts +155 -0
  12. package/src/components/BoolCell.vue +34 -0
  13. package/src/components/InfoBanner.vue +73 -0
  14. package/src/components/QdadmRoot.vue +52 -0
  15. package/src/components/SeverityTag.vue +86 -0
  16. package/src/components/dialogs/BulkStatusDialog.vue +60 -0
  17. package/src/components/dialogs/MultiStepDialog.vue +331 -0
  18. package/src/components/dialogs/SimpleDialog.vue +122 -0
  19. package/src/components/dialogs/UnsavedChangesDialog.vue +80 -0
  20. package/src/components/display/BannerZone.vue +65 -0
  21. package/src/components/display/CardsGrid.vue +72 -0
  22. package/src/components/display/CopyableId.vue +84 -0
  23. package/src/components/display/EmptyState.vue +62 -0
  24. package/src/components/display/IntensityBar.vue +190 -0
  25. package/src/components/display/RichCardsGrid.vue +101 -0
  26. package/src/components/edit/FormActions.vue +78 -0
  27. package/src/components/edit/FormField.vue +82 -0
  28. package/src/components/edit/FormInput.vue +158 -0
  29. package/src/components/edit/FormPage.vue +260 -0
  30. package/src/components/edit/FormTab.vue +217 -0
  31. package/src/components/edit/FormTabs.vue +120 -0
  32. package/src/components/edit/LookupField.vue +406 -0
  33. package/src/components/edit/LookupPickerDialog.vue +230 -0
  34. package/src/components/editors/JsonEditorFoldable.vue +470 -0
  35. package/src/components/editors/JsonStructuredField.vue +264 -0
  36. package/src/components/editors/JsonViewer.vue +51 -0
  37. package/src/components/editors/KeyValueEditor.vue +314 -0
  38. package/src/components/editors/LanguageEditor.vue +259 -0
  39. package/src/components/editors/PermissionEditor.vue +558 -0
  40. package/src/components/editors/ScopeEditor.vue +372 -0
  41. package/src/components/editors/VanillaJsonEditor.vue +183 -0
  42. package/src/components/index.ts +83 -0
  43. package/src/components/item/FieldGroups.vue +392 -0
  44. package/src/components/layout/AppLayout.vue +1032 -0
  45. package/src/components/layout/BaseLayout.vue +190 -0
  46. package/src/components/layout/Breadcrumb.vue +55 -0
  47. package/src/components/layout/DashboardLayout.vue +104 -0
  48. package/src/components/layout/FormLayout.vue +256 -0
  49. package/src/components/layout/ListLayout.vue +278 -0
  50. package/src/components/layout/PageHeader.vue +156 -0
  51. package/src/components/layout/PageLayout.vue +126 -0
  52. package/src/components/layout/PageNav.vue +192 -0
  53. package/src/components/layout/SidebarBox.vue +87 -0
  54. package/src/components/layout/Zone.vue +182 -0
  55. package/src/components/layout/defaults/DefaultBreadcrumb.vue +149 -0
  56. package/src/components/layout/defaults/DefaultFooter.vue +89 -0
  57. package/src/components/layout/defaults/DefaultFormActions.vue +67 -0
  58. package/src/components/layout/defaults/DefaultHeader.vue +78 -0
  59. package/src/components/layout/defaults/DefaultMenu.vue +188 -0
  60. package/src/components/layout/defaults/DefaultPagination.vue +75 -0
  61. package/src/components/layout/defaults/DefaultTable.vue +137 -0
  62. package/src/components/layout/defaults/DefaultUserInfo.vue +111 -0
  63. package/src/components/layout/defaults/index.ts +16 -0
  64. package/src/components/lists/ActionButtons.vue +49 -0
  65. package/src/components/lists/ActionColumn.vue +40 -0
  66. package/src/components/lists/FilterBar.vue +54 -0
  67. package/src/components/lists/ListPage.vue +467 -0
  68. package/src/components/pages/LoginPage.vue +334 -0
  69. package/src/components/pages/NotFoundPage.vue +98 -0
  70. package/src/components/show/ShowDisplay.vue +343 -0
  71. package/src/components/show/ShowField.vue +67 -0
  72. package/src/components/show/ShowPage.vue +431 -0
  73. package/src/composables/index.ts +155 -0
  74. package/src/composables/useApp.ts +67 -0
  75. package/src/composables/useAuth.ts +98 -0
  76. package/src/composables/useBareForm.ts +319 -0
  77. package/src/composables/useBreadcrumb.ts +252 -0
  78. package/src/composables/useChildPage.ts +113 -0
  79. package/src/composables/useCurrentEntity.ts +60 -0
  80. package/src/composables/useDeferred.ts +94 -0
  81. package/src/composables/useDirtyState.ts +138 -0
  82. package/src/composables/useEntityItemFormPage.ts +942 -0
  83. package/src/composables/useEntityItemFormPage.types.ts +451 -0
  84. package/src/composables/useEntityItemPage.ts +438 -0
  85. package/src/composables/useEntityItemShowPage.ts +722 -0
  86. package/src/composables/useFieldManager.ts +692 -0
  87. package/src/composables/useForm.ts +544 -0
  88. package/src/composables/useGuardStore.ts +53 -0
  89. package/src/composables/useHooks.ts +56 -0
  90. package/src/composables/useInfoBanner.ts +217 -0
  91. package/src/composables/useJsonSyntax.ts +122 -0
  92. package/src/composables/useLayoutResolver.ts +329 -0
  93. package/src/composables/useListPage.ts +1535 -0
  94. package/src/composables/useListPage.types.ts +437 -0
  95. package/src/composables/useListPage.utils.ts +101 -0
  96. package/src/composables/useNavContext.ts +439 -0
  97. package/src/composables/useNavigation.ts +216 -0
  98. package/src/composables/useOptionsLookup.ts +323 -0
  99. package/src/composables/usePageTitle.ts +84 -0
  100. package/src/composables/useSSEBridge.ts +142 -0
  101. package/src/composables/useSemanticBreadcrumb.ts +222 -0
  102. package/src/composables/useSidebarState.ts +24 -0
  103. package/src/composables/useSignals.ts +52 -0
  104. package/src/composables/useUnsavedChangesGuard.ts +155 -0
  105. package/src/composables/useUserImpersonator.ts +317 -0
  106. package/src/composables/useZoneRegistry.ts +252 -0
  107. package/src/core/bundles.ts +558 -0
  108. package/src/core/decorator.ts +420 -0
  109. package/src/core/extension.ts +470 -0
  110. package/src/core/index.ts +59 -0
  111. package/src/deferred/DeferredRegistry.ts +353 -0
  112. package/src/deferred/index.ts +15 -0
  113. package/src/editors/index.ts +12 -0
  114. package/src/entity/EntityManager.cache.ts +530 -0
  115. package/src/entity/EntityManager.crud.ts +615 -0
  116. package/src/entity/EntityManager.interface.ts +78 -0
  117. package/src/entity/EntityManager.query.ts +221 -0
  118. package/src/entity/EntityManager.relations.ts +151 -0
  119. package/src/entity/EntityManager.ts +944 -0
  120. package/src/entity/EntityManager.types.ts +288 -0
  121. package/src/entity/auth/CompositeAuthAdapter.ts +194 -0
  122. package/src/entity/auth/EntityAuthAdapter.ts +119 -0
  123. package/src/entity/auth/PermissiveAdapter.ts +43 -0
  124. package/src/entity/auth/RoleHierarchy.ts +128 -0
  125. package/src/entity/auth/SecurityChecker.ts +202 -0
  126. package/src/entity/auth/factory.ts +203 -0
  127. package/src/entity/auth/index.ts +47 -0
  128. package/src/entity/factory.test.js +189 -0
  129. package/src/entity/factory.ts +146 -0
  130. package/src/entity/index.ts +49 -0
  131. package/src/entity/storage/ApiStorage.ts +228 -0
  132. package/src/entity/storage/IStorage.ts +100 -0
  133. package/src/entity/storage/LocalStorage.ts +200 -0
  134. package/src/entity/storage/MemoryStorage.ts +184 -0
  135. package/src/entity/storage/MockApiStorage.ts +318 -0
  136. package/src/entity/storage/SdkStorage.ts +377 -0
  137. package/src/entity/storage/factory.test.js +159 -0
  138. package/src/entity/storage/factory.ts +209 -0
  139. package/src/entity/storage/index.ts +75 -0
  140. package/src/gen/FieldMapper.ts +122 -0
  141. package/src/gen/StorageProfileFactory.ts +93 -0
  142. package/src/gen/connectors/BaseConnector.ts +150 -0
  143. package/src/gen/connectors/ManualConnector.test.js +499 -0
  144. package/src/gen/connectors/ManualConnector.ts +414 -0
  145. package/src/gen/connectors/OpenAPIConnector.test.js +836 -0
  146. package/src/gen/connectors/OpenAPIConnector.ts +693 -0
  147. package/src/gen/connectors/__fixtures__/sample-openapi.json +311 -0
  148. package/src/gen/connectors/index.ts +27 -0
  149. package/src/gen/createManagers.ts +245 -0
  150. package/src/gen/decorators.ts +134 -0
  151. package/src/gen/generateManagers.test.js +540 -0
  152. package/src/gen/generateManagers.ts +398 -0
  153. package/src/gen/index.ts +66 -0
  154. package/src/gen/schema.ts +248 -0
  155. package/src/gen/vite-plugin.ts +114 -0
  156. package/src/generated/managers/testManager.js +45 -0
  157. package/src/generated/managers/testManager.ts +46 -0
  158. package/src/hooks/HookRegistry.ts +16 -0
  159. package/src/hooks/index.ts +15 -0
  160. package/src/i18n/I18n.ts +344 -0
  161. package/src/i18n/IncrementalDomainProvider.ts +153 -0
  162. package/src/i18n/InlineTranslationProvider.ts +4 -0
  163. package/src/i18n/LazyTranslationProvider.ts +102 -0
  164. package/src/i18n/MessagesRegistry.ts +4 -0
  165. package/src/i18n/Resolver.ts +4 -0
  166. package/src/i18n/__tests__/I18n.test.ts +169 -0
  167. package/src/i18n/__tests__/IncrementalDomainProvider.test.ts +146 -0
  168. package/src/i18n/__tests__/LazyTranslationProvider.test.ts +100 -0
  169. package/src/i18n/__tests__/Resolver.test.ts +271 -0
  170. package/src/i18n/defaults/DefaultCoreProvider.ts +28 -0
  171. package/src/i18n/defaults/core.en.yml +55 -0
  172. package/src/i18n/defaults/core.fr.yml +55 -0
  173. package/src/i18n/index.ts +55 -0
  174. package/src/i18n/loaders/raw-modules.d.ts +15 -0
  175. package/src/i18n/loaders/yaml.ts +35 -0
  176. package/src/i18n/strategies.ts +4 -0
  177. package/src/i18n/types.ts +34 -0
  178. package/src/i18n/useI18n.ts +34 -0
  179. package/src/index.ts +453 -0
  180. package/src/kernel/EventRouter.ts +23 -0
  181. package/src/kernel/Kernel.api.ts +79 -0
  182. package/src/kernel/Kernel.auth.ts +120 -0
  183. package/src/kernel/Kernel.i18n.ts +29 -0
  184. package/src/kernel/Kernel.modules.ts +170 -0
  185. package/src/kernel/Kernel.registries.ts +237 -0
  186. package/src/kernel/Kernel.routing.ts +334 -0
  187. package/src/kernel/Kernel.ts +460 -0
  188. package/src/kernel/Kernel.types.ts +263 -0
  189. package/src/kernel/Kernel.vue.ts +304 -0
  190. package/src/kernel/KernelContext.entities.ts +80 -0
  191. package/src/kernel/KernelContext.events.ts +57 -0
  192. package/src/kernel/KernelContext.i18n.ts +37 -0
  193. package/src/kernel/KernelContext.permissions.ts +38 -0
  194. package/src/kernel/KernelContext.routing.ts +280 -0
  195. package/src/kernel/KernelContext.ts +252 -0
  196. package/src/kernel/KernelContext.types.ts +173 -0
  197. package/src/kernel/KernelContext.zones.ts +54 -0
  198. package/src/kernel/Module.ts +169 -0
  199. package/src/kernel/ModuleLoader.ts +645 -0
  200. package/src/kernel/SSEBridge.ts +11 -0
  201. package/src/kernel/SignalBus.ts +48 -0
  202. package/src/kernel/index.ts +56 -0
  203. package/src/module/index.ts +33 -0
  204. package/src/module/moduleRegistry.ts +492 -0
  205. package/src/modules/debug/AuthCollector.ts +501 -0
  206. package/src/modules/debug/Collector.ts +20 -0
  207. package/src/modules/debug/DebugBridge.ts +14 -0
  208. package/src/modules/debug/DebugModule.ts +220 -0
  209. package/src/modules/debug/EntitiesCollector.ts +839 -0
  210. package/src/modules/debug/ErrorCollector.ts +4 -0
  211. package/src/modules/debug/I18nCollector.ts +9 -0
  212. package/src/modules/debug/LocalStorageAdapter.ts +7 -0
  213. package/src/modules/debug/RouterCollector.ts +449 -0
  214. package/src/modules/debug/SignalCollector.ts +4 -0
  215. package/src/modules/debug/ToastCollector.ts +4 -0
  216. package/src/modules/debug/ZonesCollector.ts +447 -0
  217. package/src/modules/debug/components/DebugBar.vue +31 -0
  218. package/src/modules/debug/components/adminPanelsConfig.ts +42 -0
  219. package/src/modules/debug/components/index.ts +9 -0
  220. package/src/modules/debug/components/panels/AuthPanel.vue +267 -0
  221. package/src/modules/debug/components/panels/EntitiesPanel.vue +572 -0
  222. package/src/modules/debug/components/panels/I18nPanel.vue +738 -0
  223. package/src/modules/debug/components/panels/RouterPanel.vue +440 -0
  224. package/src/modules/debug/components/panels/ZonesPanel.vue +133 -0
  225. package/src/modules/debug/components/panels/index.ts +16 -0
  226. package/src/modules/debug/index.ts +58 -0
  227. package/src/modules/debug/styles.scss +2671 -0
  228. package/src/notifications/NotificationBadge.vue +35 -0
  229. package/src/notifications/NotificationListener.vue +71 -0
  230. package/src/notifications/NotificationModule.ts +76 -0
  231. package/src/notifications/NotificationPanel.vue +478 -0
  232. package/src/notifications/NotificationStore.ts +288 -0
  233. package/src/notifications/index.ts +42 -0
  234. package/src/notifications/styles.scss +32 -0
  235. package/src/orchestrator/Orchestrator.ts +427 -0
  236. package/src/orchestrator/index.ts +8 -0
  237. package/src/orchestrator/useOrchestrator.ts +80 -0
  238. package/src/plugin.ts +251 -0
  239. package/src/query/FilterQuery.ts +306 -0
  240. package/src/query/QueryExecutor.ts +341 -0
  241. package/src/query/index.ts +16 -0
  242. package/src/security/EntityRolesProvider.ts +385 -0
  243. package/src/security/PermissionMatcher.ts +152 -0
  244. package/src/security/PermissionRegistry.ts +273 -0
  245. package/src/security/PersistableRolesProvider.ts +584 -0
  246. package/src/security/RolesManager.ts +136 -0
  247. package/src/security/RolesProvider.ts +167 -0
  248. package/src/security/RolesProviderStorage.ts +211 -0
  249. package/src/security/SecurityModule.ts +94 -0
  250. package/src/security/StaticRolesProvider.ts +117 -0
  251. package/src/security/UsersManager.ts +163 -0
  252. package/src/security/index.ts +77 -0
  253. package/src/security/pages/RoleForm.vue +276 -0
  254. package/src/security/pages/RoleList.vue +123 -0
  255. package/src/styles/_alerts.scss +95 -0
  256. package/src/styles/_buttons.scss +391 -0
  257. package/src/styles/_cards.scss +241 -0
  258. package/src/styles/_code.scss +78 -0
  259. package/src/styles/_dialogs.scss +55 -0
  260. package/src/styles/_filter-bar.scss +70 -0
  261. package/src/styles/_forms.scss +434 -0
  262. package/src/styles/_helpers.scss +153 -0
  263. package/src/styles/_lists.scss +225 -0
  264. package/src/styles/_main.scss +356 -0
  265. package/src/styles/_markdown.scss +88 -0
  266. package/src/styles/_responsive.scss +255 -0
  267. package/src/styles/_show-pages.scss +186 -0
  268. package/src/styles/_sidebar.scss +380 -0
  269. package/src/styles/_states.scss +115 -0
  270. package/src/styles/_stats.scss +47 -0
  271. package/src/styles/_variables.scss +224 -0
  272. package/src/styles/index.scss +38 -0
  273. package/src/styles/theme/_components.scss +331 -0
  274. package/src/styles/theme/_index.scss +10 -0
  275. package/src/styles/theme/_tokens.scss +147 -0
  276. package/src/styles/theme/_utilities.scss +175 -0
  277. package/src/toast/ToastBridgeModule.ts +68 -0
  278. package/src/toast/ToastListener.vue +55 -0
  279. package/src/toast/index.ts +26 -0
  280. package/src/toast/useSignalToast.ts +154 -0
  281. package/src/types/index.ts +285 -0
  282. package/src/types/pluralize.d.ts +19 -0
  283. package/src/types/quarkernel.d.ts +50 -0
  284. package/src/utils/formatters.ts +174 -0
  285. package/src/utils/index.ts +35 -0
  286. package/src/utils/transformers.ts +131 -0
  287. package/src/vite/qdadmDebugPlugin.ts +401 -0
  288. package/src/vite-env.d.ts +50 -0
  289. package/src/zones/ZoneRegistry.ts +934 -0
  290. package/src/zones/index.ts +29 -0
  291. package/src/zones/zones.ts +191 -0
@@ -0,0 +1,437 @@
1
+ /**
2
+ * useListPage - Type definitions
3
+ *
4
+ * Extracted from useListPage.ts for maintainability.
5
+ */
6
+ import type { Ref, ComputedRef } from 'vue'
7
+ import type { Router } from 'vue-router'
8
+ import type { FilterQuery } from '../query/FilterQuery'
9
+ import type { ParentConfig, UseEntityItemPageReturn } from './useEntityItemPage.js'
10
+ import type { EntityManagerRead } from '../entity/EntityManager.interface'
11
+
12
+ /**
13
+ * Entity manager interface for list pages (re-export for convenience)
14
+ */
15
+ export type EntityManager = EntityManagerRead
16
+
17
+ /**
18
+ * List response from API
19
+ */
20
+ export interface ListResponse<T = unknown> {
21
+ items: T[]
22
+ total?: number
23
+ fromCache?: boolean
24
+ [key: string]: unknown
25
+ }
26
+
27
+ /**
28
+ * Orchestrator interface
29
+ */
30
+ export interface Orchestrator {
31
+ get: (entityName: string) => EntityManager
32
+ toast: {
33
+ success: (summary: string, detail?: string, emitter?: unknown) => void
34
+ error: (summary: string, detail?: string, emitter?: unknown) => void
35
+ warn: (summary: string, detail?: string, emitter?: unknown) => void
36
+ info: (summary: string, detail?: string, emitter?: unknown) => void
37
+ [key: string]: ((summary: string, detail?: string, emitter?: unknown) => void) | undefined
38
+ }
39
+ }
40
+
41
+ /**
42
+ * Toast helper interface
43
+ */
44
+ export interface ToastHelper {
45
+ add: (options: {
46
+ severity: 'success' | 'error' | 'warn' | 'info'
47
+ summary: string
48
+ detail?: string
49
+ emitter?: unknown
50
+ life?: number
51
+ }) => void
52
+ }
53
+
54
+ /**
55
+ * PrimeVue confirm service interface
56
+ */
57
+ export interface ConfirmService {
58
+ require: (options: {
59
+ message: string
60
+ header: string
61
+ icon: string
62
+ acceptClass?: string
63
+ accept: () => void
64
+ }) => void
65
+ }
66
+
67
+ /**
68
+ * Column configuration
69
+ */
70
+ export interface ColumnConfig {
71
+ field: string
72
+ header?: string
73
+ sortable?: boolean
74
+ style?: string
75
+ body?: (row: unknown) => unknown
76
+ [key: string]: unknown
77
+ }
78
+
79
+ /**
80
+ * Filter configuration
81
+ */
82
+ export interface FilterConfig {
83
+ name: string
84
+ type?: 'select' | 'multiselect' | 'date' | 'checkbox' | 'dropdown' | 'autocomplete'
85
+ placeholder?: string
86
+ options?: Array<{ label: string; value: unknown }>
87
+ default?: unknown
88
+ persist?: boolean
89
+ allLabel?: string
90
+ optionsEntity?: string
91
+ optionsEndpoint?: string | boolean
92
+ optionsFromCache?: string | boolean
93
+ optionLabel?: string
94
+ optionValue?: string
95
+ cacheOptions?: boolean | 'auto'
96
+ component?: 'dropdown' | 'autocomplete'
97
+ reference?: string
98
+ processor?: (options: Array<{ label: string; value: unknown }>) => Array<{ label: string; value: unknown }>
99
+ toQuery?: (value: unknown) => Record<string, unknown>
100
+ local_filter?: (item: unknown, value: unknown) => boolean
101
+ _filterQuery?: FilterQuery | unknown
102
+ _cacheOptions?: boolean
103
+ _optionsLoaded?: boolean
104
+ [key: string]: unknown
105
+ }
106
+
107
+ /**
108
+ * Row action configuration
109
+ */
110
+ export interface ActionConfig {
111
+ name: string
112
+ icon?: string | ((row: unknown) => string)
113
+ tooltip?: string | ((row: unknown) => string)
114
+ severity?: string | ((row: unknown) => string)
115
+ onClick: (row: unknown) => void | Promise<void>
116
+ visible?: (row: unknown) => boolean
117
+ disabled?: (row: unknown) => boolean
118
+ }
119
+
120
+ /**
121
+ * Resolved row action for rendering
122
+ */
123
+ export interface ResolvedAction {
124
+ name: string
125
+ icon: string | undefined
126
+ tooltip: string | undefined
127
+ severity: string
128
+ isDisabled: boolean
129
+ handler: () => void | Promise<void>
130
+ }
131
+
132
+ /**
133
+ * Header action state context
134
+ */
135
+ export interface HeaderActionState {
136
+ hasSelection: boolean
137
+ selectionCount: number
138
+ deleting: boolean
139
+ }
140
+
141
+ /**
142
+ * Header action configuration
143
+ */
144
+ export interface HeaderActionConfig {
145
+ name: string
146
+ label: string | ((state: HeaderActionState) => string)
147
+ icon?: string
148
+ severity?: string
149
+ onClick: () => void | Promise<void>
150
+ visible?: (state: HeaderActionState) => boolean
151
+ loading?: (state: HeaderActionState) => boolean
152
+ }
153
+
154
+ /**
155
+ * Resolved header action for rendering
156
+ */
157
+ export interface ResolvedHeaderAction extends HeaderActionConfig {
158
+ isLoading: boolean
159
+ }
160
+
161
+ /**
162
+ * Card configuration
163
+ */
164
+ export interface CardConfig {
165
+ name: string
166
+ [key: string]: unknown
167
+ }
168
+
169
+ /**
170
+ * Search configuration
171
+ */
172
+ export interface SearchConfig {
173
+ placeholder?: string
174
+ fields?: string[]
175
+ debounce?: number
176
+ local_search?: (item: unknown, query: string) => boolean
177
+ }
178
+
179
+ /**
180
+ * Entity context for multi-storage routing
181
+ */
182
+ export interface EntityContext {
183
+ parentChain: Array<{ entity: string; id: string | number }>
184
+ }
185
+
186
+ /**
187
+ * Bulk status action return type
188
+ */
189
+ export interface BulkStatusActionReturn {
190
+ showDialog: Ref<boolean>
191
+ selectedStatus: Ref<unknown>
192
+ updating: Ref<boolean>
193
+ statusOptions: Ref<Array<{ label: string; value: unknown }>>
194
+ dialogTitle: string
195
+ execute: () => Promise<void>
196
+ cancel: () => void
197
+ setOptions: (options: Array<{ label: string; value: unknown }>) => void
198
+ }
199
+
200
+ /**
201
+ * Axios-like error interface
202
+ */
203
+ export interface AxiosError {
204
+ response?: {
205
+ data?: {
206
+ detail?: string
207
+ }
208
+ }
209
+ message?: string
210
+ }
211
+
212
+ /**
213
+ * Options for useListPage
214
+ */
215
+ export interface UseListPageOptions<T = unknown> {
216
+ /** Entity name for EntityManager */
217
+ entity: string
218
+ /** Custom data key field (default: manager.idField) */
219
+ dataKey?: string
220
+ /** Default sort field */
221
+ defaultSort?: string | null
222
+ /** Default sort order (-1 = desc, 1 = asc) */
223
+ defaultSortOrder?: -1 | 1
224
+ /** Enable server-side pagination/sorting */
225
+ serverSide?: boolean
226
+ /** Default page size */
227
+ pageSize?: number
228
+ /** Auto-load on mount (default: true) */
229
+ loadOnMount?: boolean
230
+ /** Persist filters to sessionStorage (default: true) */
231
+ persistFilters?: boolean
232
+ /** Sync filters to URL query params (default: true) */
233
+ syncUrlParams?: boolean
234
+ /** Filter mode: 'auto' | 'manager' | 'local' */
235
+ filterMode?: 'auto' | 'manager' | 'local'
236
+ /** Auto-filter threshold for 'auto' mode */
237
+ autoFilterThreshold?: number
238
+ /** Auto-load filters from registry (default: true) */
239
+ autoLoadFilters?: boolean
240
+ /** Callback before load */
241
+ onBeforeLoad?: ((params: Record<string, unknown>) => Record<string, unknown> | void) | null
242
+ /** Callback after load */
243
+ onAfterLoad?: ((response: ListResponse<T>, processedData: { items: T[]; total: number }) => void) | null
244
+ /** Transform response */
245
+ transformResponse?: ((response: ListResponse<T>) => { items: T[]; total: number }) | null
246
+ /** Override manager.entityName */
247
+ entityName?: string
248
+ /** Override manager.labelPlural */
249
+ entityNamePlural?: string
250
+ /** Override manager.routePrefix */
251
+ routePrefix?: string
252
+ }
253
+
254
+ /**
255
+ * List page props for ListPage component
256
+ */
257
+ export interface ListPageProps {
258
+ title: string | undefined
259
+ headerActions: ResolvedHeaderAction[]
260
+ cards: CardConfig[]
261
+ columns: ColumnConfig[]
262
+ items: unknown[]
263
+ loading: boolean
264
+ dataKey: string
265
+ selected: unknown[]
266
+ selectable: boolean
267
+ lazy: boolean
268
+ totalRecords: number
269
+ rows: number
270
+ rowsPerPageOptions: number[]
271
+ sortField: string | null
272
+ sortOrder: number
273
+ searchQuery: string
274
+ searchPlaceholder: string
275
+ filters: FilterConfig[]
276
+ filterValues: Record<string, unknown>
277
+ isFilterAtDefault: (name: string) => boolean
278
+ getActions: (row: unknown) => ResolvedAction[]
279
+ hasRowTapAction: boolean
280
+ }
281
+
282
+ /**
283
+ * List page events for ListPage component
284
+ */
285
+ export interface ListPageEvents {
286
+ 'update:selected': (value: unknown[]) => void
287
+ 'update:searchQuery': (value: string) => void
288
+ 'update:filterValues': (values: Record<string, unknown>) => void
289
+ page: (event: { page: number; rows: number }) => void
290
+ sort: (event: { sortField: string; sortOrder: number }) => void
291
+ 'row-click': (item: unknown, event: Event) => void
292
+ }
293
+
294
+ /**
295
+ * Create action options
296
+ */
297
+ export interface CreateActionOptions {
298
+ label?: string
299
+ routeName?: string
300
+ params?: Record<string, unknown>
301
+ }
302
+
303
+ /**
304
+ * Bulk status action options
305
+ */
306
+ export interface BulkStatusActionOptions {
307
+ statusField?: string
308
+ idsField?: string
309
+ bulkEndpoint?: string | null
310
+ options?: Array<{ label: string; value: unknown }>
311
+ label?: string
312
+ icon?: string
313
+ dialogTitle?: string
314
+ }
315
+
316
+ /**
317
+ * Return type for useListPage
318
+ */
319
+ export interface UseListPageReturn<T = unknown> {
320
+ // Manager access
321
+ manager: EntityManager
322
+
323
+ // Parent chain (when list is child of parent entity)
324
+ parentConfig: ComputedRef<ParentConfig | null>
325
+ parentId: ComputedRef<string | number | null>
326
+ parentData: ComputedRef<unknown>
327
+ parentLoading: ComputedRef<boolean>
328
+ parentChain: ComputedRef<Map<number, unknown>>
329
+ parentPage: UseEntityItemPageReturn | null
330
+
331
+ // State
332
+ items: Ref<T[]>
333
+ displayItems: ComputedRef<T[]>
334
+ loading: Ref<boolean>
335
+ selected: Ref<T[]>
336
+ deleting: Ref<boolean>
337
+
338
+ // Pagination
339
+ page: Ref<number>
340
+ pageSize: Ref<number>
341
+ totalRecords: Ref<number>
342
+ rowsPerPageOptions: number[]
343
+ sortField: Ref<string | null>
344
+ sortOrder: Ref<number>
345
+ onPage: (event: { page: number; rows: number }) => void
346
+ onSort: (event: { sortField: string; sortOrder: number }) => void
347
+
348
+ // Search
349
+ searchQuery: Ref<string>
350
+ searchConfig: Ref<SearchConfig>
351
+ setSearch: (config: Partial<SearchConfig>) => void
352
+
353
+ // Columns
354
+ columns: ComputedRef<ColumnConfig[]>
355
+ addColumn: (field: string, config?: Partial<ColumnConfig>) => void
356
+ removeColumn: (field: string) => void
357
+ updateColumn: (field: string, updates: Partial<ColumnConfig>) => void
358
+
359
+ // Header Actions
360
+ headerActions: ComputedRef<ResolvedHeaderAction[]>
361
+ addHeaderAction: (name: string, config: Omit<HeaderActionConfig, 'name'>) => void
362
+ removeHeaderAction: (name: string) => void
363
+ getHeaderActions: () => ResolvedHeaderAction[]
364
+ addCreateAction: (labelOrOptions?: string | CreateActionOptions | null) => void
365
+ addBulkDeleteAction: () => void
366
+ addBulkStatusAction: (options?: BulkStatusActionOptions) => BulkStatusActionReturn
367
+ hasBulkActions: ComputedRef<boolean>
368
+
369
+ // Cards
370
+ cards: ComputedRef<CardConfig[]>
371
+ addCard: (name: string, config: Omit<CardConfig, 'name'>) => void
372
+ updateCard: (name: string, config: Partial<CardConfig>) => void
373
+ removeCard: (name: string) => void
374
+
375
+ // Filters
376
+ filters: ComputedRef<FilterConfig[]>
377
+ filterValues: Ref<Record<string, unknown>>
378
+ filteredItems: ComputedRef<T[]>
379
+ fromCache: Ref<boolean>
380
+ addFilter: (name: string, config: Omit<FilterConfig, 'name'>) => void
381
+ removeFilter: (name: string) => void
382
+ setFilterValue: (name: string, value: unknown) => void
383
+ updateFilters: (values: Record<string, unknown>) => void
384
+ clearFilters: () => void
385
+ isFilterAtDefault: (name: string) => boolean
386
+ hasActiveFilters: ComputedRef<boolean>
387
+ loadFilterOptions: () => Promise<void>
388
+ initFromRegistry: () => void
389
+ restoreFilters: () => void
390
+
391
+ // Actions
392
+ addAction: (name: string, config: Omit<ActionConfig, 'name'>) => void
393
+ removeAction: (name: string) => void
394
+ getActions: (row: unknown) => ResolvedAction[]
395
+ getRowActions: (row: unknown) => ResolvedAction[]
396
+ addViewAction: (options?: Partial<ActionConfig>) => void
397
+ addEditAction: (options?: Partial<ActionConfig>) => void
398
+ addDeleteAction: (options?: Partial<ActionConfig> & { labelField?: string }) => void
399
+
400
+ // Permissions
401
+ canCreate: ComputedRef<boolean>
402
+ canDelete: ComputedRef<boolean>
403
+ canEditRow: (row: unknown) => boolean
404
+ canDeleteRow: (row: unknown) => boolean
405
+
406
+ // Data
407
+ loadItems: (extraParams?: Record<string, unknown>, options?: { force?: boolean }) => Promise<void>
408
+
409
+ // Navigation
410
+ goToCreate: () => void
411
+ goToEdit: (item: unknown) => void
412
+ goToShow: (item: unknown) => void
413
+
414
+ // Mobile row tap
415
+ isMobile: Ref<boolean>
416
+ hasRowTapAction: ComputedRef<boolean>
417
+ getPrimaryRowAction: () => 'edit' | 'show' | null
418
+ onRowClick: (item: unknown, event: Event) => void
419
+
420
+ // Delete
421
+ deleteItem: (item: unknown, labelField?: string) => Promise<void>
422
+ confirmDelete: (item: unknown, labelField?: string) => void
423
+ bulkDelete: () => Promise<void>
424
+ confirmBulkDelete: () => void
425
+ hasSelection: ComputedRef<boolean>
426
+ selectionCount: ComputedRef<number>
427
+
428
+ // Utilities
429
+ formatDate: (dateStr: string | null | undefined, options?: Intl.DateTimeFormatOptions) => string
430
+ toast: ToastHelper
431
+ confirm: ConfirmService
432
+ router: Router
433
+
434
+ // ListPage integration
435
+ props: ComputedRef<ListPageProps>
436
+ events: ListPageEvents
437
+ }
@@ -0,0 +1,101 @@
1
+ /**
2
+ * useListPage helpers — stateless utilities used by the list page composable.
3
+ *
4
+ * Kept module-local so they're trivially importable from the orchestrator
5
+ * file (`useListPage.ts`) and from any future split modules without dragging
6
+ * the full `useListPage` runtime context along.
7
+ */
8
+
9
+ // ─────────────────────────────────────────────────────────────────────────────
10
+ // Pagination cookie persistence
11
+ // ─────────────────────────────────────────────────────────────────────────────
12
+
13
+ const COOKIE_NAME = 'qdadm_pageSize'
14
+ const COOKIE_EXPIRY_DAYS = 365
15
+
16
+ export function getCookie(name: string): string | null {
17
+ const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'))
18
+ return match?.[2] ?? null
19
+ }
20
+
21
+ export function setCookie(name: string, value: string | number, days: number): void {
22
+ const expires = new Date(Date.now() + days * 864e5).toUTCString()
23
+ document.cookie = `${name}=${value}; expires=${expires}; path=/; SameSite=Lax`
24
+ }
25
+
26
+ /**
27
+ * Read the saved page size from cookie. Returns the default when absent or
28
+ * not in the canonical {@link PAGE_SIZE_OPTIONS} list.
29
+ */
30
+ export function getSavedPageSize(defaultSize: number): number {
31
+ const saved = getCookie(COOKIE_NAME)
32
+ if (saved) {
33
+ const parsed = parseInt(saved, 10)
34
+ if (PAGE_SIZE_OPTIONS.includes(parsed)) return parsed
35
+ }
36
+ return defaultSize
37
+ }
38
+
39
+ export function persistPageSize(size: number): void {
40
+ setCookie(COOKIE_NAME, size, COOKIE_EXPIRY_DAYS)
41
+ }
42
+
43
+ // ─────────────────────────────────────────────────────────────────────────────
44
+ // Default label formatter (snake_case → Title Case)
45
+ // ─────────────────────────────────────────────────────────────────────────────
46
+
47
+ export function snakeToTitle(str: string): string {
48
+ if (!str) return 'Unknown'
49
+ return String(str)
50
+ .split('_')
51
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
52
+ .join(' ')
53
+ }
54
+
55
+ // ─────────────────────────────────────────────────────────────────────────────
56
+ // Pagination options
57
+ // ─────────────────────────────────────────────────────────────────────────────
58
+
59
+ /** Canonical page size options offered to the user. */
60
+ export const PAGE_SIZE_OPTIONS = [10, 50, 100]
61
+
62
+ // ─────────────────────────────────────────────────────────────────────────────
63
+ // Filter session storage
64
+ // ─────────────────────────────────────────────────────────────────────────────
65
+
66
+ const FILTER_SESSION_PREFIX = 'qdadm_filters_'
67
+
68
+ export function getSessionFilters(key: string): Record<string, unknown> | null {
69
+ try {
70
+ const stored = sessionStorage.getItem(FILTER_SESSION_PREFIX + key)
71
+ return stored ? JSON.parse(stored) : null
72
+ } catch {
73
+ return null
74
+ }
75
+ }
76
+
77
+ export function setSessionFilters(key: string, filters: Record<string, unknown>): void {
78
+ try {
79
+ sessionStorage.setItem(FILTER_SESSION_PREFIX + key, JSON.stringify(filters))
80
+ } catch {
81
+ // Ignore storage errors (quota exceeded, disabled by user, …).
82
+ }
83
+ }
84
+
85
+ export function clearSessionFilters(key: string): void {
86
+ try {
87
+ sessionStorage.removeItem(FILTER_SESSION_PREFIX + key)
88
+ } catch {
89
+ // Ignore storage errors.
90
+ }
91
+ }
92
+
93
+ // ─────────────────────────────────────────────────────────────────────────────
94
+ // Smart filter discovery
95
+ // ─────────────────────────────────────────────────────────────────────────────
96
+
97
+ /**
98
+ * Threshold below which the list switches to client-side filtering when
99
+ * `filterMode: 'auto'` is in effect.
100
+ */
101
+ export const SMART_FILTER_THRESHOLD = 50