qdadm 0.13.0 → 0.14.2
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/README.md +26 -117
- package/package.json +1 -2
- package/src/components/SeverityTag.vue +71 -0
- package/src/components/editors/ScopeEditor.vue +26 -17
- package/src/components/index.js +1 -0
- package/src/components/layout/AppLayout.vue +29 -1
- package/src/components/layout/PageHeader.vue +71 -5
- package/src/components/layout/PageLayout.vue +4 -3
- package/src/composables/index.js +1 -0
- package/src/composables/useBareForm.js +76 -4
- package/src/composables/useBreadcrumb.js +23 -14
- package/src/composables/useForm.js +48 -2
- package/src/composables/useListPageBuilder.js +51 -74
- package/src/composables/useManager.js +20 -0
- package/src/entity/EntityManager.js +391 -9
- package/src/entity/storage/ApiStorage.js +5 -0
- package/src/entity/storage/LocalStorage.js +5 -0
- package/src/kernel/Kernel.js +25 -8
- package/src/plugin.js +3 -1
- package/src/styles/main.css +44 -0
- package/src/styles/theme/index.css +1 -1
- package/CHANGELOG.md +0 -270
package/CHANGELOG.md
DELETED
|
@@ -1,270 +0,0 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
All notable changes to qdadm will be documented in this file.
|
|
4
|
-
|
|
5
|
-
The format is based on [Keep a Changelog](https://keepachangelog.com/),
|
|
6
|
-
and this project adheres to [Semantic Versioning](https://semver.org/).
|
|
7
|
-
|
|
8
|
-
## [0.13.0] - 2025-12-21
|
|
9
|
-
|
|
10
|
-
### Added
|
|
11
|
-
- `EntityManager.getMany(ids)`: Batch fetch multiple entities by IDs
|
|
12
|
-
- Delegates to `storage.getMany(ids)` if available
|
|
13
|
-
- Falls back to parallel `get()` calls
|
|
14
|
-
- `EntityManager.canCreate()`: Permission check for creating entities
|
|
15
|
-
- `EntityManager.canUpdate(entity?)`: Permission check for updating entities
|
|
16
|
-
- `EntityManager.children`: Config for parent-child entity relationships
|
|
17
|
-
- `BoolCell` component: Standardized tristate boolean display
|
|
18
|
-
- `true` → green check (`--p-green-500`)
|
|
19
|
-
- `false` → red cross (`--p-red-500`)
|
|
20
|
-
- `null/undefined` → empty
|
|
21
|
-
- `LocalStorage.getMany(ids)`: Optimized batch fetch for localStorage adapter
|
|
22
|
-
|
|
23
|
-
### Changed
|
|
24
|
-
- **BREAKING**: Removed `canWrite()` - use `canCreate()` / `canUpdate()` instead
|
|
25
|
-
- `addCreateAction()`: Uses `manager.canCreate()` for visibility
|
|
26
|
-
- `addEditAction()`: Uses `manager.canUpdate(row)` for visibility
|
|
27
|
-
|
|
28
|
-
### Demo
|
|
29
|
-
- `read` field moved from `books` to `loans` entity
|
|
30
|
-
- `BookForm`: Tabs in edit mode showing child entities (Loans)
|
|
31
|
-
- `LoanList`: Bulk actions "Mark Read" / "Mark Unread"
|
|
32
|
-
- `LoanForm`: Toggle for `read` field
|
|
33
|
-
- Permission examples updated to use `canCreate()` / `canUpdate()`
|
|
34
|
-
|
|
35
|
-
## [0.12.0] - 2025-12-21
|
|
36
|
-
|
|
37
|
-
### Added
|
|
38
|
-
- `useListPageBuilder.addFilter({ local_filter })`: Custom filter callback for local mode
|
|
39
|
-
- Specifies HOW to filter when in local mode (items < threshold)
|
|
40
|
-
- Example: `local_filter: (item, value) => value === 'active' ? !item.returned_at : true`
|
|
41
|
-
- Filters with `local_filter` are **not sent to manager** (virtual fields)
|
|
42
|
-
- `local_filter: false` = manager only, skip in local mode
|
|
43
|
-
- `useListPageBuilder.setSearch({ local_search })`: Custom search callback for local mode
|
|
44
|
-
- Specifies HOW to search when in local mode
|
|
45
|
-
- Example: `local_search: (item, query) => booksMap[item.book_id]?.title.includes(query)`
|
|
46
|
-
- `local_search: false` = manager only, skip in local mode
|
|
47
|
-
- `EntityManager.localFilterThreshold`: Per-entity threshold for auto local filtering
|
|
48
|
-
- Priority: config `autoFilterThreshold` > `manager.localFilterThreshold` > default (100)
|
|
49
|
-
|
|
50
|
-
### Changed
|
|
51
|
-
- **BREAKING**: Renamed `filterMode: 'api'` → `filterMode: 'manager'` (clearer intent)
|
|
52
|
-
- **Demo**: `LoanList` uses `local_filter` for virtual `status` filter
|
|
53
|
-
- **Demo**: `LoanList` uses `local_search` for book title lookup
|
|
54
|
-
|
|
55
|
-
### Documentation
|
|
56
|
-
- **The threshold decides everything**:
|
|
57
|
-
- `items >= threshold` → **manager mode**: delegate ALL filtering to EntityManager
|
|
58
|
-
- `items < threshold` → **local mode**: filter client-side
|
|
59
|
-
- **Modes**:
|
|
60
|
-
- `filterMode: 'manager'`: Always delegate to EntityManager
|
|
61
|
-
- `filterMode: 'local'`: Always filter client-side
|
|
62
|
-
- `filterMode: 'auto'` (default): Switch based on threshold
|
|
63
|
-
- **Behavior Matrix**:
|
|
64
|
-
| Type | Mode `manager` | Mode `local` |
|
|
65
|
-
|-----------------------------|-----------------|-----------------------------|
|
|
66
|
-
| Filter standard | Manager handles | `item[field] === value` |
|
|
67
|
-
| Filter + `local_filter` | Manager handles | `local_filter(item, value)` |
|
|
68
|
-
| Filter + `local_filter:false` | Manager handles | (skipped) |
|
|
69
|
-
| Search standard | Manager handles | `field.includes(query)` |
|
|
70
|
-
| Search + `local_search` | Manager handles | `local_search(item, query)` |
|
|
71
|
-
| Search + `local_search:false` | Manager handles | (skipped) |
|
|
72
|
-
- **Threshold Priority**: config > `manager.localFilterThreshold` > 100
|
|
73
|
-
|
|
74
|
-
## [0.11.0] - 2025-12-20
|
|
75
|
-
|
|
76
|
-
### Added
|
|
77
|
-
- **Demo**: Permission-aware form fields pattern
|
|
78
|
-
- `LoanForm`: Non-admin users get `user_id` auto-set and field locked
|
|
79
|
-
- `LoansManager.create()`: Enforces `user_id` server-side for non-admin
|
|
80
|
-
- **Demo**: Detailed comments on `useForm` return values (`loading`, `saving`, `dirty`, `isEdit`)
|
|
81
|
-
|
|
82
|
-
### Changed
|
|
83
|
-
- **Demo**: Simplified `onMounted` pattern replaces `watch` for form field initialization
|
|
84
|
-
|
|
85
|
-
## [0.10.0] - 2025-12-20
|
|
86
|
-
|
|
87
|
-
### Added
|
|
88
|
-
- **Demo**: Complete permission patterns with documented examples
|
|
89
|
-
- `UsersManager`: Admin-only access (canRead/canWrite)
|
|
90
|
-
- `BooksManager`: Everyone edits, admin-only delete (canDelete)
|
|
91
|
-
- `LoansManager`: Ownership-based filtering (list override + row-level permissions)
|
|
92
|
-
- **Demo**: Detailed JSDoc comments explaining all qdadm patterns
|
|
93
|
-
- **Demo**: Fixture seeding system with JSON files
|
|
94
|
-
|
|
95
|
-
### Changed
|
|
96
|
-
- **Demo**: Login page shows all available demo accounts with role explanations
|
|
97
|
-
|
|
98
|
-
## [0.9.0] - 2025-12-20
|
|
99
|
-
|
|
100
|
-
### Added
|
|
101
|
-
- `useListPageBuilder.props`: Computed object with all ListPage props - use with `v-bind="list.props.value"`
|
|
102
|
-
- `useListPageBuilder.events`: Event handlers object - use with `v-on="list.events"`
|
|
103
|
-
- `useListPageBuilder.hasBulkActions`: Auto-detects if bulk actions are available
|
|
104
|
-
- Auto-selectable: Checkboxes shown only when bulk actions exist (no manual `selectable` prop needed)
|
|
105
|
-
|
|
106
|
-
### Changed
|
|
107
|
-
- ListPage template simplified from ~20 props/events to just `v-bind` + `v-on`
|
|
108
|
-
|
|
109
|
-
## [0.8.0] - 2025-12-20
|
|
110
|
-
|
|
111
|
-
### Added
|
|
112
|
-
- `EntityManager.canDelete(entity?)`: Fine-grained delete permission check
|
|
113
|
-
- `useListPageBuilder`: Standard actions now respect permissions:
|
|
114
|
-
- `addCreateAction()`: Hidden if `manager.canCreate()` returns false
|
|
115
|
-
- `addEditAction()`: Hidden per row if `manager.canUpdate(row)` returns false
|
|
116
|
-
- `addDeleteAction()`: Hidden per row if `manager.canDelete(row)` returns false
|
|
117
|
-
- `addBulkDeleteAction()`: Hidden if `manager.canDelete()` returns false
|
|
118
|
-
|
|
119
|
-
## [0.7.0] - 2025-12-20
|
|
120
|
-
|
|
121
|
-
### Added
|
|
122
|
-
- `Kernel`: All-in-one bootstrap class - handles Vue app, Pinia, PrimeVue, router, auth guard, and qdadm
|
|
123
|
-
- Constructor is declarative (stores config only)
|
|
124
|
-
- `createApp()` does all initialization, returns Vue app for mount
|
|
125
|
-
- Allows tweaking `kernel.options` before `createApp()`, or adding plugins/directives before `mount()`
|
|
126
|
-
```js
|
|
127
|
-
const kernel = new Kernel({
|
|
128
|
-
root: App,
|
|
129
|
-
modules: import.meta.glob('./modules/*/init.js', { eager: true }),
|
|
130
|
-
managers, authAdapter,
|
|
131
|
-
pages: { login, layout },
|
|
132
|
-
homeRoute: 'book',
|
|
133
|
-
app: { name: 'My App' },
|
|
134
|
-
primevue: { plugin: PrimeVue, theme: Aura }
|
|
135
|
-
})
|
|
136
|
-
kernel.createApp().mount('#app')
|
|
137
|
-
```
|
|
138
|
-
- `kernel.getRouter()`, `kernel.getApp()`, `kernel.getOrchestrator()` - access internals
|
|
139
|
-
|
|
140
|
-
## [0.6.0] - 2025-12-20
|
|
141
|
-
|
|
142
|
-
### Added
|
|
143
|
-
- `registry.addRoutes(prefix, routes, { entity })`: Route-level entity binding for permission checks
|
|
144
|
-
- `registry.addNavItem({ entity })`: Nav item entity binding for permission checks
|
|
145
|
-
- **Auto Route Guard**: Plugin adds `beforeEach` guard that redirects to `/` if `manager.canRead()` returns false
|
|
146
|
-
- **Auto Nav Filtering**: `useNavigation` filters items and hides empty sections based on `manager.canRead()`
|
|
147
|
-
|
|
148
|
-
## [0.5.0] - 2025-12-20
|
|
149
|
-
|
|
150
|
-
### Added
|
|
151
|
-
- `useGuardStore`: Shared reactive store for automatic UnsavedChangesDialog rendering
|
|
152
|
-
- `AppLayout`: Automatically renders UnsavedChangesDialog when a form is active (no code needed in forms)
|
|
153
|
-
- `EntityManager.canRead(entity?)`: Permission check for reading (general or specific entity)
|
|
154
|
-
- `EntityManager.canWrite(entity?)`: Permission check for writing (general or specific entity)
|
|
155
|
-
|
|
156
|
-
### Changed
|
|
157
|
-
- `useBareForm`: Uses `registerGuardDialog`/`unregisterGuardDialog` from store instead of provide/inject
|
|
158
|
-
- `UnsavedChangesDialog`: Refactored to use `SimpleDialog` internally
|
|
159
|
-
- `PageLayout`: Removed `guardDialog` prop (dialog is now automatic via AppLayout)
|
|
160
|
-
|
|
161
|
-
### Removed
|
|
162
|
-
- `features.scopes`: Removed from plugin config - permission logic belongs in EntityManager
|
|
163
|
-
- `useAuth.hasScope()`: Replaced by `EntityManager.canRead()`/`canWrite()` pattern
|
|
164
|
-
|
|
165
|
-
### Fixed
|
|
166
|
-
- `useDirtyState`: Fixed timing issue where `takeSnapshot()` used `nextTick()` causing navigation to be blocked after save
|
|
167
|
-
|
|
168
|
-
## [0.4.0] - 2025-12-20
|
|
169
|
-
|
|
170
|
-
### Added
|
|
171
|
-
- `EntityManager.getEntityLabel(entity)`: Method to get display label, handles both string field and callback
|
|
172
|
-
- `EntityManager.labelField`: Can now be a string (field name) or callback function `(entity) => string`
|
|
173
|
-
- `PageLayout`: `manager` prop - derives labelField automatically from EntityManager
|
|
174
|
-
|
|
175
|
-
### Changed
|
|
176
|
-
- `PageLayout`: Uses `manager.getEntityLabel()` instead of manual field access
|
|
177
|
-
- `useBreadcrumb`: Shows entity label in breadcrumb (replaces ID segment), keeps action labels (Edit/Create/View)
|
|
178
|
-
|
|
179
|
-
## [0.3.1] - 2025-12-20
|
|
180
|
-
|
|
181
|
-
### Added
|
|
182
|
-
- `AppLayout`: "powered by qdadm" footer with version display
|
|
183
|
-
- `assets/logo.svg`: Hexagon logo with "QD" in two-tone blue
|
|
184
|
-
- `features.poweredBy`: Option to hide "powered by" footer (default: true)
|
|
185
|
-
|
|
186
|
-
### Fixed
|
|
187
|
-
- `AppLayout`: Vue Flow and full-height components now render correctly (flex layout)
|
|
188
|
-
- `AppLayout`: Use `<RouterView />` fallback when no slot content provided
|
|
189
|
-
|
|
190
|
-
### Changed
|
|
191
|
-
- `AppLayout`: Sidebar width uses CSS variable `var(--fad-sidebar-width, 15rem)` instead of hardcoded `250px`
|
|
192
|
-
- `tokens.css`: Layout tokens now use `rem` units (`--fad-sidebar-width`, `--fad-header-height`, `--fad-content-max-width`)
|
|
193
|
-
- `main.css`: Removed ~130 lines of duplicated styles (sidebar, nav, login, user-info) - now only in AppLayout scoped CSS
|
|
194
|
-
|
|
195
|
-
## [0.3.0] - 2025-12-20
|
|
196
|
-
|
|
197
|
-
### Added
|
|
198
|
-
- `AppLayout` component with auto-nav from module registry
|
|
199
|
-
- `useNavigation` composable for navigation state management
|
|
200
|
-
- `useStatus` composable for generic status/option loading
|
|
201
|
-
- `setSectionOrder()` to configure navigation section order
|
|
202
|
-
- `initModules()` accepts external module imports and core nav items
|
|
203
|
-
|
|
204
|
-
### Changed
|
|
205
|
-
- Module registry is now fully configurable (no hardcoded imports)
|
|
206
|
-
- Navigation auto-builds from module declarations (registry.addNavItem)
|
|
207
|
-
- Branding comes from bootstrap config (createQdadm app option)
|
|
208
|
-
- Dashboard now uses qdadm AppLayout instead of local implementation
|
|
209
|
-
|
|
210
|
-
### Removed
|
|
211
|
-
- Hardcoded import.meta.glob in moduleRegistry
|
|
212
|
-
- Hardcoded sectionOrder in moduleRegistry
|
|
213
|
-
|
|
214
|
-
## [0.2.0] - 2025-12-20
|
|
215
|
-
|
|
216
|
-
### Added
|
|
217
|
-
- README.md with quick start guide
|
|
218
|
-
- TODO.md for planned features
|
|
219
|
-
- docs/FRAMEWORK.md moved from dashboard
|
|
220
|
-
|
|
221
|
-
### Changed
|
|
222
|
-
- Successfully integrated with Faketual dashboard
|
|
223
|
-
- All 60+ dashboard modules migrated to use qdadm imports
|
|
224
|
-
- Validated build and runtime functionality
|
|
225
|
-
|
|
226
|
-
### Fixed
|
|
227
|
-
- Component import paths (PageHeader, CardsGrid, ListPage)
|
|
228
|
-
- useJsonSyntax import paths in editor components
|
|
229
|
-
- Theme CSS import path in styles/index.css
|
|
230
|
-
|
|
231
|
-
## [0.1.0] - 2025-12-20
|
|
232
|
-
|
|
233
|
-
### Added
|
|
234
|
-
- Initial extraction from Faketual dashboard
|
|
235
|
-
- `createQdadm` plugin for Vue 3 bootstrap
|
|
236
|
-
- **Adapters**:
|
|
237
|
-
- `ApiAdapter` interface for CRUD operations
|
|
238
|
-
- `AuthAdapter` interface for authentication (optional)
|
|
239
|
-
- **Composables**:
|
|
240
|
-
- `useForm` - Form state management with validation
|
|
241
|
-
- `useListPageBuilder` - Paginated list with filters and actions
|
|
242
|
-
- `useBareForm` - Minimal form without routing
|
|
243
|
-
- `useBreadcrumb` - Breadcrumb builder
|
|
244
|
-
- `useDirtyState` - Track unsaved changes
|
|
245
|
-
- `useEntityTitle` - Dynamic page titles
|
|
246
|
-
- `useJsonSyntax` - JSON validation helpers
|
|
247
|
-
- `usePageBuilder` - Generic page builder
|
|
248
|
-
- `useSubEditor` - Sub-component for complex forms
|
|
249
|
-
- `useTabSync` - Sync tabs with URL
|
|
250
|
-
- `useUnsavedChangesGuard` - Block navigation if dirty
|
|
251
|
-
- `useAuth` - Authentication access
|
|
252
|
-
- `useApp` - App branding access
|
|
253
|
-
- **Components**:
|
|
254
|
-
- Layout: `PageLayout`, `PageHeader`, `Breadcrumb`
|
|
255
|
-
- Forms: `FormField`, `FormActions`, `FormTabs`, `FormTab`
|
|
256
|
-
- Lists: `ListPage`, `ActionButtons`, `ActionColumn`, `FilterBar`
|
|
257
|
-
- Editors: `KeyValueEditor`, `LanguageEditor`, `ScopeEditor`, `VanillaJsonEditor`, `JsonEditorFoldable`, `JsonStructuredField`, `JsonViewer`
|
|
258
|
-
- Dialogs: `SimpleDialog`, `MultiStepDialog`, `BulkStatusDialog`, `UnsavedChangesDialog`
|
|
259
|
-
- Display: `CardsGrid`, `RichCardsGrid`, `CopyableId`, `EmptyState`, `IntensityBar`
|
|
260
|
-
- Auth: `LoginPage`, `AuthGuard`, `ScopeGuard`
|
|
261
|
-
- **Module System**:
|
|
262
|
-
- `moduleRegistry` for auto-discovery of modules
|
|
263
|
-
- Route registration with path prefix
|
|
264
|
-
- Navigation item registration
|
|
265
|
-
- Route family for active state detection
|
|
266
|
-
- **Configuration**:
|
|
267
|
-
- `app` config for branding (name, logo, version, theme)
|
|
268
|
-
- `features` toggles (auth, scopes)
|
|
269
|
-
- `builtinModules` for users/roles
|
|
270
|
-
- `endpoints` configuration
|