qdadm 0.48.0 → 0.49.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -17,9 +17,9 @@
|
|
|
17
17
|
* - entity: Current entity data (for dynamic labels in breadcrumb)
|
|
18
18
|
* - parentEntity: Parent entity data (for parent label in breadcrumb)
|
|
19
19
|
*/
|
|
20
|
-
import { computed, ref, watch,
|
|
20
|
+
import { computed, ref, watch, inject } from 'vue'
|
|
21
21
|
import { useRoute, useRouter } from 'vue-router'
|
|
22
|
-
import { getSiblingRoutes } from '../../module/moduleRegistry.js'
|
|
22
|
+
import { getSiblingRoutes, getChildRoutes } from '../../module/moduleRegistry.js'
|
|
23
23
|
import { useOrchestrator } from '../../orchestrator/useOrchestrator.js'
|
|
24
24
|
|
|
25
25
|
// Inject override refs from AppLayout
|
|
@@ -129,7 +129,7 @@ const breadcrumbItems = computed(() => {
|
|
|
129
129
|
})
|
|
130
130
|
|
|
131
131
|
// Sibling navlinks (routes with same parent)
|
|
132
|
-
const
|
|
132
|
+
const siblingNavlinks = computed(() => {
|
|
133
133
|
if (!parentConfig.value) return []
|
|
134
134
|
|
|
135
135
|
const { entity: parentEntityName, param } = parentConfig.value
|
|
@@ -148,52 +148,91 @@ const navlinks = computed(() => {
|
|
|
148
148
|
})
|
|
149
149
|
})
|
|
150
150
|
|
|
151
|
-
//
|
|
151
|
+
// Child navlinks (when on parent detail page, show links to children)
|
|
152
|
+
const childNavlinks = computed(() => {
|
|
153
|
+
// Only when NOT on a child route (no parentConfig)
|
|
154
|
+
if (parentConfig.value) return []
|
|
155
|
+
|
|
156
|
+
const entityName = route.meta?.entity
|
|
157
|
+
if (!entityName) return []
|
|
158
|
+
|
|
159
|
+
const children = getChildRoutes(entityName)
|
|
160
|
+
if (children.length === 0) return []
|
|
161
|
+
|
|
162
|
+
const entityId = route.params.id
|
|
163
|
+
|
|
164
|
+
// Build navlinks to child routes
|
|
165
|
+
return children.map(childRoute => {
|
|
166
|
+
const childManager = childRoute.meta?.entity ? getManager(childRoute.meta.entity) : null
|
|
167
|
+
const label = childRoute.meta?.navLabel || childManager?.labelPlural || childRoute.name
|
|
168
|
+
const parentParam = childRoute.meta?.parent?.param || 'id'
|
|
169
|
+
|
|
170
|
+
return {
|
|
171
|
+
label,
|
|
172
|
+
to: { name: childRoute.name, params: { [parentParam]: entityId } },
|
|
173
|
+
active: false
|
|
174
|
+
}
|
|
175
|
+
})
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
// Combined navlinks with "Details" link
|
|
152
179
|
const allNavlinks = computed(() => {
|
|
153
|
-
|
|
180
|
+
// Case 1: On a child route - show siblings + Details link to parent
|
|
181
|
+
if (parentConfig.value) {
|
|
182
|
+
const { entity: parentEntityName, param, itemRoute } = parentConfig.value
|
|
183
|
+
const parentId = route.params[param]
|
|
184
|
+
const parentManager = getManager(parentEntityName)
|
|
154
185
|
|
|
155
|
-
|
|
156
|
-
const parentId = route.params[param]
|
|
157
|
-
const parentManager = getManager(parentEntityName)
|
|
186
|
+
if (!parentManager) return siblingNavlinks.value
|
|
158
187
|
|
|
159
|
-
|
|
188
|
+
const defaultSuffix = parentManager.readOnly ? '-show' : '-edit'
|
|
189
|
+
const parentRouteName = itemRoute || `${parentManager.routePrefix}${defaultSuffix}`
|
|
190
|
+
const isOnParentRoute = route.name === parentRouteName
|
|
191
|
+
|
|
192
|
+
// Details link to parent item page
|
|
193
|
+
// CONVENTION: Entity item routes MUST use :id as param name (e.g., /books/:id)
|
|
194
|
+
// This is a qdadm convention - all entity detail/edit routes expect 'id' param
|
|
195
|
+
const detailsLink = {
|
|
196
|
+
label: 'Details',
|
|
197
|
+
to: { name: parentRouteName, params: { id: parentId } },
|
|
198
|
+
active: isOnParentRoute
|
|
199
|
+
}
|
|
160
200
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
const isOnParentRoute = route.name === parentRouteName
|
|
201
|
+
return [detailsLink, ...siblingNavlinks.value]
|
|
202
|
+
}
|
|
164
203
|
|
|
165
|
-
//
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
204
|
+
// Case 2: On parent detail page - show children + Details (active)
|
|
205
|
+
if (childNavlinks.value.length > 0) {
|
|
206
|
+
const detailsLink = {
|
|
207
|
+
label: 'Details',
|
|
208
|
+
to: { name: route.name, params: route.params },
|
|
209
|
+
active: true
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
return [detailsLink, ...childNavlinks.value]
|
|
170
213
|
}
|
|
171
214
|
|
|
172
|
-
return [
|
|
215
|
+
return []
|
|
173
216
|
})
|
|
174
217
|
|
|
175
218
|
// Sync breadcrumb and navlinks to AppLayout via provide/inject
|
|
176
|
-
|
|
219
|
+
// Watch computed values + route changes to ensure updates after navigation
|
|
220
|
+
watch([breadcrumbItems, () => route.fullPath], ([items]) => {
|
|
177
221
|
if (breadcrumbOverride) {
|
|
178
222
|
breadcrumbOverride.value = items
|
|
179
223
|
}
|
|
180
224
|
}, { immediate: true })
|
|
181
225
|
|
|
182
|
-
watch(allNavlinks, (links) => {
|
|
226
|
+
watch([allNavlinks, () => route.fullPath], ([links]) => {
|
|
183
227
|
if (navlinksOverride) {
|
|
184
228
|
navlinksOverride.value = links
|
|
185
229
|
}
|
|
186
230
|
}, { immediate: true })
|
|
187
231
|
|
|
188
|
-
//
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
}
|
|
193
|
-
if (navlinksOverride) {
|
|
194
|
-
navlinksOverride.value = null
|
|
195
|
-
}
|
|
196
|
-
})
|
|
232
|
+
// Note: We intentionally do NOT clear overrides in onUnmounted.
|
|
233
|
+
// When navigating between routes, the new PageNav's watch will overwrite the values.
|
|
234
|
+
// Clearing in onUnmounted causes a race condition where the old PageNav clears
|
|
235
|
+
// AFTER the new PageNav has already set its values.
|
|
197
236
|
</script>
|
|
198
237
|
|
|
199
238
|
<template>
|
|
@@ -49,13 +49,21 @@ let alterationPromise = null
|
|
|
49
49
|
const registry = {
|
|
50
50
|
/**
|
|
51
51
|
* Add routes for this module
|
|
52
|
-
*
|
|
52
|
+
*
|
|
53
|
+
* CONVENTION: Entity item routes MUST use :id as param name
|
|
54
|
+
* - List route: 'books' → /books
|
|
55
|
+
* - Item route: 'books/:id' → /books/:id (MUST be :id, not :bookId or :uuid)
|
|
56
|
+
* - Child route: 'books/:id/reviews' → parent.param = 'id'
|
|
57
|
+
*
|
|
58
|
+
* This convention is required for PageNav, breadcrumbs, and navigation to work correctly.
|
|
59
|
+
*
|
|
60
|
+
* @param {string} prefix - Path prefix for all routes (e.g., 'books' or 'books/:id/reviews')
|
|
53
61
|
* @param {Array} moduleRoutes - Route definitions with relative paths
|
|
54
62
|
* @param {object} options - Route options
|
|
55
63
|
* @param {string} [options.entity] - Entity name for permission checking
|
|
56
64
|
* @param {object} [options.parent] - Parent entity config for child routes
|
|
57
65
|
* @param {string} options.parent.entity - Parent entity name (e.g., 'books')
|
|
58
|
-
* @param {string} options.parent.param - Route param for parent ID (
|
|
66
|
+
* @param {string} options.parent.param - Route param for parent ID (MUST be 'id')
|
|
59
67
|
* @param {string} options.parent.foreignKey - Foreign key field (e.g., 'book_id')
|
|
60
68
|
* @param {string} [options.parent.itemRoute] - Override parent item route (auto: parentEntity.routePrefix + '-edit')
|
|
61
69
|
* @param {string} [options.label] - Label for navlinks (defaults to entity labelPlural)
|
|
@@ -341,6 +349,18 @@ export function getSiblingRoutes(parentEntity, parentParam) {
|
|
|
341
349
|
})
|
|
342
350
|
}
|
|
343
351
|
|
|
352
|
+
/**
|
|
353
|
+
* Get child routes (routes that have this entity as parent)
|
|
354
|
+
* @param {string} entityName - Entity name to find children for
|
|
355
|
+
* @returns {Array} Routes with this entity as parent
|
|
356
|
+
*/
|
|
357
|
+
export function getChildRoutes(entityName) {
|
|
358
|
+
return routes.filter(route => {
|
|
359
|
+
const parent = route.meta?.parent
|
|
360
|
+
return parent?.entity === entityName
|
|
361
|
+
})
|
|
362
|
+
}
|
|
363
|
+
|
|
344
364
|
/**
|
|
345
365
|
* Check if a route belongs to a family
|
|
346
366
|
*/
|