@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,155 @@
1
+ /**
2
+ * useStackHydrator - Access hydrated navigation stack
3
+ *
4
+ * Provides async-hydrated levels with entity data and labels.
5
+ * Each level has its own promise for fine-grained control.
6
+ *
7
+ * Listens to SignalBus events for reactivity:
8
+ * - stack:hydrated - when hydration completes (batched)
9
+ *
10
+ * @example
11
+ * const hydrator = useStackHydrator()
12
+ *
13
+ * // Reactive usage (shows loading state, updates when ready)
14
+ * const parentLabel = computed(() =>
15
+ * hydrator.parent.value?.hydrated
16
+ * ? hydrator.parent.value.label
17
+ * : 'Loading...'
18
+ * )
19
+ *
20
+ * // Await specific level
21
+ * await hydrator.getParent()?.promise
22
+ *
23
+ * // Await all levels
24
+ * await Promise.all(hydrator.getLevels().map(l => l.promise))
25
+ */
26
+
27
+ import { inject, ref, computed, onUnmounted, type Ref, type ComputedRef } from 'vue'
28
+ import type { SignalBus } from '../kernel/SignalBus'
29
+
30
+ /**
31
+ * Hydrated level data
32
+ */
33
+ export interface HydratedLevel {
34
+ entity: string
35
+ id: string | number
36
+ data: unknown | null
37
+ label: string | null
38
+ hydrated: boolean
39
+ promise: Promise<unknown>
40
+ }
41
+
42
+ /**
43
+ * Stack hydrator interface (from StackHydrator class)
44
+ */
45
+ interface StackHydratorClass {
46
+ getLevels: () => HydratedLevel[]
47
+ getLevel: (index: number) => HydratedLevel | null
48
+ getLevelByEntity: (entity: string) => HydratedLevel | null
49
+ getCurrent: () => HydratedLevel | null
50
+ getParent: () => HydratedLevel | null
51
+ setCurrentData: (data: unknown) => void
52
+ setEntityData: (entity: string, data: unknown) => void
53
+ }
54
+
55
+ /**
56
+ * Return type for useStackHydrator
57
+ */
58
+ export interface StackHydratorReturn {
59
+ // Computed refs (reactive)
60
+ levels: Ref<HydratedLevel[]>
61
+ current: ComputedRef<HydratedLevel | null>
62
+ parent: ComputedRef<HydratedLevel | null>
63
+ root: ComputedRef<HydratedLevel | null>
64
+
65
+ // Sync accessors (for immediate access + promise)
66
+ getLevel: (index: number) => HydratedLevel | null
67
+ getLevelByEntity: (entity: string) => HydratedLevel | null
68
+ getCurrent: () => HydratedLevel | null
69
+ getParent: () => HydratedLevel | null
70
+ getLevels: () => HydratedLevel[]
71
+
72
+ // Manual data setters (for pages that load their own data)
73
+ setCurrentData: (data: unknown) => void
74
+ setEntityData: (entity: string, data: unknown) => void
75
+ }
76
+
77
+ export function useStackHydrator(): StackHydratorReturn {
78
+ const hydrator = inject<StackHydratorClass | null>('qdadmStackHydrator', null)
79
+ const signalBus = inject<SignalBus | null>('qdadmSignals', null)
80
+
81
+ if (!hydrator) {
82
+ console.warn('[useStackHydrator] StackHydrator not provided')
83
+ return createEmptyHydrator()
84
+ }
85
+
86
+ // Reactive state - updated via SignalBus
87
+ const levels = ref<HydratedLevel[]>(hydrator.getLevels())
88
+
89
+ // Subscribe to hydration changes (batched signal)
90
+ // QuarKernel passes (event, ctx) where event.data contains the payload
91
+ let unsubscribe: (() => void) | null = null
92
+ if (signalBus) {
93
+ const handler = (event: unknown): void => {
94
+ const eventData = event as { data?: { levels?: HydratedLevel[] } }
95
+ const newLevels = eventData.data?.levels
96
+ if (newLevels) {
97
+ // Create new array reference to trigger reactivity
98
+ levels.value = [...newLevels]
99
+ }
100
+ }
101
+ unsubscribe = signalBus.on('stack:hydrated', handler)
102
+ }
103
+
104
+ // Cleanup on unmount
105
+ onUnmounted(() => {
106
+ if (unsubscribe) {
107
+ unsubscribe()
108
+ }
109
+ })
110
+
111
+ // Computed accessors
112
+ const current = computed(() => levels.value.at(-1) ?? null)
113
+ const parent = computed(() => levels.value.at(-2) ?? null)
114
+ const root = computed(() => levels.value[0] ?? null)
115
+
116
+ return {
117
+ // Computed refs (reactive)
118
+ levels,
119
+ current,
120
+ parent,
121
+ root,
122
+
123
+ // Sync accessors (for immediate access + promise)
124
+ getLevel: (i: number) => hydrator.getLevel(i),
125
+ getLevelByEntity: (e: string) => hydrator.getLevelByEntity(e),
126
+ getCurrent: () => hydrator.getCurrent(),
127
+ getParent: () => hydrator.getParent(),
128
+ getLevels: () => hydrator.getLevels(),
129
+
130
+ // Manual data setters (for pages that load their own data)
131
+ setCurrentData: (data: unknown) => hydrator.setCurrentData(data),
132
+ setEntityData: (entity: string, data: unknown) => hydrator.setEntityData(entity, data),
133
+ }
134
+ }
135
+
136
+ /**
137
+ * Fallback when StackHydrator not available
138
+ */
139
+ function createEmptyHydrator(): StackHydratorReturn {
140
+ return {
141
+ levels: ref<HydratedLevel[]>([]),
142
+ current: computed(() => null),
143
+ parent: computed(() => null),
144
+ root: computed(() => null),
145
+ getLevel: () => null,
146
+ getLevelByEntity: () => null,
147
+ getCurrent: () => null,
148
+ getParent: () => null,
149
+ getLevels: () => [],
150
+ setCurrentData: () => {},
151
+ setEntityData: () => {},
152
+ }
153
+ }
154
+
155
+ export default useStackHydrator
@@ -0,0 +1,34 @@
1
+ <script setup lang="ts">
2
+ /**
3
+ * BoolCell - Standardized boolean display for list columns
4
+ *
5
+ * Tristate display:
6
+ * - true / "true" / 1: green check
7
+ * - false / "false" / 0: red cross
8
+ * - null/undefined: empty
9
+ *
10
+ * Usage:
11
+ * <Column field="read" header="Read">
12
+ * <template #body="{ data }">
13
+ * <BoolCell :value="data.read" />
14
+ * </template>
15
+ * </Column>
16
+ */
17
+ import { computed } from 'vue'
18
+
19
+ interface Props {
20
+ value?: boolean | string | number | null
21
+ }
22
+
23
+ const props = withDefaults(defineProps<Props>(), {
24
+ value: null
25
+ })
26
+
27
+ const isTrue = computed(() => props.value === true || props.value === 'true' || props.value === 1)
28
+ const isFalse = computed(() => props.value === false || props.value === 'false' || props.value === 0)
29
+ </script>
30
+
31
+ <template>
32
+ <i v-if="isTrue" class="pi pi-check" style="color: var(--p-green-500)" />
33
+ <i v-else-if="isFalse" class="pi pi-times" style="color: var(--p-red-500)" />
34
+ </template>
@@ -0,0 +1,73 @@
1
+ <script setup lang="ts">
2
+ /**
3
+ * InfoBanner - Consistent message banner component
4
+ *
5
+ * Wraps PrimeVue Message with standardized styling and icon support.
6
+ *
7
+ * @example
8
+ * // Simple usage
9
+ * <InfoBanner severity="warn">
10
+ * Settings will be lost on refresh.
11
+ * </InfoBanner>
12
+ *
13
+ * // With custom icon
14
+ * <InfoBanner severity="success" icon="pi-check-circle">
15
+ * Operation completed successfully.
16
+ * </InfoBanner>
17
+ *
18
+ * // Without icon
19
+ * <InfoBanner severity="info" :icon="false">
20
+ * Just some information.
21
+ * </InfoBanner>
22
+ */
23
+ import Message from 'primevue/message'
24
+ import { computed } from 'vue'
25
+
26
+ type Severity = 'info' | 'success' | 'warn' | 'error' | 'secondary' | 'contrast'
27
+
28
+ interface Props {
29
+ /** Severity level: info, success, warn, error, secondary, contrast */
30
+ severity?: Severity
31
+ /** Custom icon class (e.g., 'pi-user'). Set to false to hide icon. */
32
+ icon?: string | boolean | null
33
+ /** Allow closing the banner (default: true) */
34
+ closable?: boolean
35
+ }
36
+
37
+ const props = withDefaults(defineProps<Props>(), {
38
+ severity: 'info',
39
+ icon: null,
40
+ closable: true
41
+ })
42
+
43
+ // Default icons per severity
44
+ const defaultIcons: Record<Severity, string> = {
45
+ info: 'pi-info-circle',
46
+ success: 'pi-check-circle',
47
+ warn: 'pi-exclamation-triangle',
48
+ error: 'pi-times-circle',
49
+ secondary: 'pi-info-circle',
50
+ contrast: 'pi-info-circle'
51
+ }
52
+
53
+ const iconClass = computed(() => {
54
+ if (props.icon === false) return null
55
+ if (props.icon && typeof props.icon === 'string') return `pi ${props.icon}`
56
+ return `pi ${defaultIcons[props.severity]}`
57
+ })
58
+ </script>
59
+
60
+ <template>
61
+ <Message
62
+ :severity="severity"
63
+ :closable="closable"
64
+ class="info-banner"
65
+ >
66
+ <div class="info-banner-content">
67
+ <i v-if="iconClass" :class="iconClass" class="info-banner-icon"></i>
68
+ <span class="info-banner-text">
69
+ <slot />
70
+ </span>
71
+ </div>
72
+ </Message>
73
+ </template>
@@ -0,0 +1,52 @@
1
+ <script setup lang="ts">
2
+ /**
3
+ * QdadmRoot — drop-in helper for hosts that own their own Vue app
4
+ * and want qdadm's DOM extras (Toast, ToastListener, DebugBar)
5
+ * rendered alongside.
6
+ *
7
+ * Equivalent to the wrapper Kernel produces internally when it owns
8
+ * `createApp`. When `Kernel({ existingApp })` is used, the host's
9
+ * App.vue should render `<QdadmRoot />` somewhere visible (typically
10
+ * at the end of the template) so toasts and the debug bar appear.
11
+ *
12
+ * The Toast / DebugBar children are conditional on what the Kernel
13
+ * was configured with (PrimeVue presence, debugBar option) — render
14
+ * is a no-op otherwise, so it's always safe to include.
15
+ */
16
+
17
+ import { computed, inject, type Component } from 'vue'
18
+ import Toast from 'primevue/toast'
19
+ import ToastListener from '../toast/ToastListener.vue'
20
+ import { getQdadmDebugBarRef } from '../kernel/Kernel.vue'
21
+
22
+ const props = withDefaults(
23
+ defineProps<{
24
+ /**
25
+ * Render the qdadm debug bar inline. Default true preserves the
26
+ * legacy behaviour. Set false in hosts that already render their
27
+ * own (shared) `<DebugBar />` to avoid two bars on screen.
28
+ */
29
+ debugBar?: boolean
30
+ }>(),
31
+ { debugBar: true },
32
+ )
33
+
34
+ // Read the singleton-on-window debug bar ref. Using a getter (instead
35
+ // of importing the module-level const) makes this resilient to Vite
36
+ // HMR's module fragmentation in dev, where a top-level `const ref`
37
+ // can be torn into separate instances per importer.
38
+ const debugBarRef = getQdadmDebugBarRef()
39
+ const debugBarComp = computed<Component | null>(() =>
40
+ props.debugBar ? debugBarRef.value : null,
41
+ )
42
+
43
+ // `qdadmHasPrimeVue` is provided by the Kernel during _installPlugins.
44
+ // True when PrimeVue is wired (so Toast / ToastListener are usable).
45
+ const hasToast = inject<boolean>('qdadmHasPrimeVue', false)
46
+ </script>
47
+
48
+ <template>
49
+ <Toast v-if="hasToast" />
50
+ <ToastListener v-if="hasToast" />
51
+ <component v-if="debugBarComp" :is="debugBarComp" />
52
+ </template>
@@ -0,0 +1,86 @@
1
+ <script setup lang="ts">
2
+ /**
3
+ * SeverityTag - Auto-discovers severity from EntityManager
4
+ *
5
+ * Renders a PrimeVue Tag for simple severity strings, or a rich badge
6
+ * with icon (including animated spinners) when the severity map provides
7
+ * a descriptor with an `icon` field.
8
+ *
9
+ * Entity can be specified explicitly or auto-discovered from list context.
10
+ *
11
+ * @example
12
+ * // Explicit entity
13
+ * <SeverityTag entity="jobs" field="status" :value="job.status" />
14
+ *
15
+ * // Auto-discover from list context (inside ListPage)
16
+ * <SeverityTag field="status" :value="data.status" />
17
+ *
18
+ * // With custom label
19
+ * <SeverityTag entity="stories" field="status" :value="story.status" label="Published" />
20
+ */
21
+ import { computed, inject } from 'vue'
22
+ import Tag from 'primevue/tag'
23
+ import type { Orchestrator } from '../orchestrator/Orchestrator'
24
+ import type { EntityManager } from '../entity/EntityManager'
25
+
26
+ interface Props {
27
+ /** Entity name (e.g., 'jobs', 'stories') - optional if inside ListPage context */
28
+ entity?: string | null
29
+ /** Field name for severity lookup (e.g., 'status') */
30
+ field: string
31
+ /** Field value */
32
+ value?: string | number | boolean | null
33
+ /** Optional custom label (defaults to value) */
34
+ label?: string | null
35
+ /** Default severity if no mapping found */
36
+ defaultSeverity?: string
37
+ }
38
+
39
+ const props = withDefaults(defineProps<Props>(), {
40
+ entity: null,
41
+ value: null,
42
+ label: null,
43
+ defaultSeverity: 'secondary'
44
+ })
45
+
46
+ const orchestrator = inject<Orchestrator | null>('qdadmOrchestrator', null)
47
+ // Auto-discover entity from page context (provided by useListPage, useBareForm, etc.)
48
+ const mainEntity = inject<string | null>('mainEntity', null)
49
+
50
+ const resolvedEntity = computed(() => props.entity || mainEntity)
51
+
52
+ const manager = computed<EntityManager | null>(() => {
53
+ if (!resolvedEntity.value) return null
54
+ return orchestrator?.get(resolvedEntity.value) ?? null
55
+ })
56
+
57
+ const fieldValue = computed(() => {
58
+ if (props.value === null || props.value === undefined) return ''
59
+ return typeof props.value === 'boolean' ? String(props.value) : props.value
60
+ })
61
+
62
+ const descriptor = computed(() => {
63
+ if (!manager.value?.getSeverityDescriptor) {
64
+ return { severity: manager.value?.getSeverity?.(props.field, fieldValue.value as string | number, props.defaultSeverity) ?? props.defaultSeverity }
65
+ }
66
+ return manager.value.getSeverityDescriptor(props.field, fieldValue.value as string | number, props.defaultSeverity)
67
+ })
68
+
69
+ const severity = computed(() => descriptor.value.severity)
70
+
71
+ const displayLabel = computed(() => {
72
+ return props.label ?? descriptor.value.label ?? props.value
73
+ })
74
+
75
+ const hasIcon = computed(() => !!descriptor.value.icon)
76
+ </script>
77
+
78
+ <template>
79
+ <!-- Rich badge with icon -->
80
+ <span v-if="hasIcon" class="p-tag p-component" :class="`p-tag-${severity}`">
81
+ <i :class="descriptor.icon" />
82
+ <span class="p-tag-label">{{ displayLabel }}</span>
83
+ </span>
84
+ <!-- Simple PrimeVue Tag -->
85
+ <Tag v-else :value="displayLabel" :severity="severity" />
86
+ </template>
@@ -0,0 +1,60 @@
1
+ <script setup lang="ts">
2
+ import SimpleDialog from './SimpleDialog.vue'
3
+ import Select from 'primevue/select'
4
+
5
+ interface StatusOption {
6
+ label: string
7
+ value: string | number
8
+ }
9
+
10
+ interface Props {
11
+ visible?: boolean
12
+ title?: string
13
+ options: StatusOption[]
14
+ modelValue?: string | number
15
+ loading?: boolean
16
+ selectionCount?: number
17
+ }
18
+
19
+ withDefaults(defineProps<Props>(), {
20
+ visible: false,
21
+ title: 'Change Status',
22
+ loading: false,
23
+ selectionCount: 0
24
+ })
25
+
26
+ defineEmits<{
27
+ 'update:visible': [value: boolean]
28
+ 'update:modelValue': [value: string | number]
29
+ confirm: []
30
+ cancel: []
31
+ }>()
32
+ </script>
33
+
34
+ <template>
35
+ <SimpleDialog
36
+ :visible="visible"
37
+ :title="title"
38
+ width="400px"
39
+ :loading="loading"
40
+ confirmLabel="Update"
41
+ confirmIcon="pi pi-check"
42
+ :confirmDisabled="!modelValue"
43
+ @update:visible="$emit('update:visible', $event)"
44
+ @confirm="$emit('confirm')"
45
+ @cancel="$emit('cancel')"
46
+ >
47
+ <p v-if="selectionCount > 0" class="mb-3">
48
+ Change status for {{ selectionCount }} selected item(s):
49
+ </p>
50
+ <Select
51
+ :modelValue="modelValue"
52
+ :options="options"
53
+ optionLabel="label"
54
+ optionValue="value"
55
+ placeholder="Select new status"
56
+ class="w-full"
57
+ @update:modelValue="$emit('update:modelValue', $event)"
58
+ />
59
+ </SimpleDialog>
60
+ </template>