@jskit-ai/users-web 0.1.80 → 0.1.82
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.descriptor.mjs +137 -21
- package/package.json +21 -10
- package/src/client/bulkActions.js +47 -0
- package/src/client/components/AccountSettingsClientElement.vue +69 -24
- package/src/client/components/CrudAddEditScreen.vue +186 -0
- package/src/client/components/CrudListBulkActionSurface.vue +126 -0
- package/src/client/components/CrudListFilterSurface.vue +377 -0
- package/src/client/components/CrudListScreen.vue +434 -0
- package/src/client/components/CrudViewScreen.vue +186 -0
- package/src/client/components/ProfileClientElement.vue +19 -12
- package/src/client/components/UsersHomeToolsWidget.vue +0 -1
- package/src/client/composables/records/useAddEdit.js +23 -2
- package/src/client/composables/records/useCrudList.js +5 -1
- package/src/client/composables/records/useView.js +1 -0
- package/src/client/composables/runtime/operationUiHelpers.js +7 -3
- package/src/client/composables/runtime/useEndpointResource.js +12 -2
- package/src/client/composables/runtime/useUiFeedback.js +4 -2
- package/src/client/composables/support/resourceLoadStateHelpers.js +33 -1
- package/src/client/composables/useAccountSettingsRuntime.js +10 -1
- package/src/client/composables/useCrudAddEditScreen.js +88 -0
- package/src/client/composables/useCrudListBulkActions.js +147 -0
- package/src/client/composables/useCrudListScreen.js +107 -0
- package/src/client/composables/useCrudViewScreen.js +67 -0
- package/src/client/composables/usePagedCollection.js +6 -1
- package/src/client/filters.js +15 -0
- package/src/client/index.js +5 -0
- package/src/shared/toolsOutletContracts.js +0 -4
- package/templates/src/components/account/settings/AccountSettingsNotificationsSection.vue +34 -8
- package/templates/src/components/account/settings/AccountSettingsPreferencesSection.vue +34 -8
- package/templates/src/components/account/settings/AccountSettingsProfileSection.vue +34 -8
- package/test/crudListBulkActionSurface.test.js +27 -0
- package/test/crudListFilterSurface.test.js +45 -0
- package/test/crudScreenComponents.test.js +62 -0
- package/test/errorIntentContract.test.js +31 -0
- package/test/exportsContract.test.js +11 -0
- package/test/resourceLoadStateHelpers.test.js +35 -1
- package/test/settingsPlacementContract.test.js +146 -14
- package/test/useCrudListBulkActions.test.js +65 -0
package/package.descriptor.mjs
CHANGED
|
@@ -3,7 +3,7 @@ import { HOME_COG_OUTLET } from "./src/shared/toolsOutletContracts.js";
|
|
|
3
3
|
export default Object.freeze({
|
|
4
4
|
packageVersion: 1,
|
|
5
5
|
packageId: "@jskit-ai/users-web",
|
|
6
|
-
version: "0.1.
|
|
6
|
+
version: "0.1.82",
|
|
7
7
|
kind: "runtime",
|
|
8
8
|
description: "Users web module: account/profile UI plus shared users web widgets.",
|
|
9
9
|
dependsOn: [
|
|
@@ -50,6 +50,34 @@ export default Object.freeze({
|
|
|
50
50
|
subpath: "./client/components/AccountSettingsClientElement",
|
|
51
51
|
summary: "Exports the package-owned account settings host that renders placement-backed account sections."
|
|
52
52
|
},
|
|
53
|
+
{
|
|
54
|
+
subpath: "./client/components/CrudAddEditScreen",
|
|
55
|
+
summary: "Exports the package-owned CRUD add/edit screen shell used by generated form pages."
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
subpath: "./client/components/CrudListBulkActionSurface",
|
|
59
|
+
summary: "Exports the adaptive CRUD list bulk-action surface for generated list pages."
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
subpath: "./client/components/CrudListFilterSurface",
|
|
63
|
+
summary: "Exports the adaptive CRUD list filter surface for generated list pages."
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
subpath: "./client/components/CrudListScreen",
|
|
67
|
+
summary: "Exports the package-owned CRUD list screen shell used by generated list pages."
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
subpath: "./client/components/CrudViewScreen",
|
|
71
|
+
summary: "Exports the package-owned CRUD view screen shell used by generated detail pages."
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
subpath: "./client/bulkActions",
|
|
75
|
+
summary: "Exports client-side CRUD list bulk-action definition helpers."
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
subpath: "./client/filters",
|
|
79
|
+
summary: "Exports client-side CRUD list filter definition helpers."
|
|
80
|
+
},
|
|
53
81
|
{
|
|
54
82
|
subpath: "./client/components/ProfileClientElement",
|
|
55
83
|
summary: "Exports profile settings client element scaffold component."
|
|
@@ -78,10 +106,26 @@ export default Object.freeze({
|
|
|
78
106
|
subpath: "./client/composables/useCrudListFilterLookups",
|
|
79
107
|
summary: "Exports lookup-backed CRUD list filter helper for remote autocomplete filters."
|
|
80
108
|
},
|
|
109
|
+
{
|
|
110
|
+
subpath: "./client/composables/useCrudAddEditScreen",
|
|
111
|
+
summary: "Exports the package-owned add/edit screen runtime for generated form pages."
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
subpath: "./client/composables/useCrudListBulkActions",
|
|
115
|
+
summary: "Exports selected-record state and execution runtime for generated CRUD list bulk actions."
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
subpath: "./client/composables/useCrudListScreen",
|
|
119
|
+
summary: "Exports the package-owned list screen runtime for generated list pages."
|
|
120
|
+
},
|
|
81
121
|
{
|
|
82
122
|
subpath: "./client/composables/useView",
|
|
83
123
|
summary: "Exports read/view operation composable."
|
|
84
124
|
},
|
|
125
|
+
{
|
|
126
|
+
subpath: "./client/composables/useCrudViewScreen",
|
|
127
|
+
summary: "Exports the package-owned view screen runtime for generated detail pages."
|
|
128
|
+
},
|
|
85
129
|
{
|
|
86
130
|
subpath: "./client/composables/usePagedCollection",
|
|
87
131
|
summary: "Exports paged collection query composable."
|
|
@@ -112,7 +156,6 @@ export default Object.freeze({
|
|
|
112
156
|
outlets: [
|
|
113
157
|
{
|
|
114
158
|
target: HOME_COG_OUTLET.target,
|
|
115
|
-
defaultLinkComponentToken: HOME_COG_OUTLET.defaultLinkComponentToken,
|
|
116
159
|
surfaces: ["home"],
|
|
117
160
|
source: "src/client/components/UsersHomeToolsWidget.vue"
|
|
118
161
|
},
|
|
@@ -122,19 +165,66 @@ export default Object.freeze({
|
|
|
122
165
|
source: "src/client/components/AccountSettingsClientElement.vue"
|
|
123
166
|
}
|
|
124
167
|
],
|
|
168
|
+
topology: {
|
|
169
|
+
placements: [
|
|
170
|
+
{
|
|
171
|
+
id: "home.tools-menu",
|
|
172
|
+
description: "Home surface tools menu actions.",
|
|
173
|
+
surfaces: ["home"],
|
|
174
|
+
variants: {
|
|
175
|
+
compact: {
|
|
176
|
+
outlet: HOME_COG_OUTLET.target,
|
|
177
|
+
renderers: {
|
|
178
|
+
link: "local.main.ui.surface-aware-menu-link-item"
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
medium: {
|
|
182
|
+
outlet: HOME_COG_OUTLET.target,
|
|
183
|
+
renderers: {
|
|
184
|
+
link: "local.main.ui.surface-aware-menu-link-item"
|
|
185
|
+
}
|
|
186
|
+
},
|
|
187
|
+
expanded: {
|
|
188
|
+
outlet: HOME_COG_OUTLET.target,
|
|
189
|
+
renderers: {
|
|
190
|
+
link: "local.main.ui.surface-aware-menu-link-item"
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
id: "settings.sections",
|
|
197
|
+
owner: "account-settings",
|
|
198
|
+
description: "Account settings content sections.",
|
|
199
|
+
surfaces: ["account"],
|
|
200
|
+
variants: {
|
|
201
|
+
compact: {
|
|
202
|
+
outlet: "account-settings:sections"
|
|
203
|
+
},
|
|
204
|
+
medium: {
|
|
205
|
+
outlet: "account-settings:sections"
|
|
206
|
+
},
|
|
207
|
+
expanded: {
|
|
208
|
+
outlet: "account-settings:sections"
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
]
|
|
213
|
+
},
|
|
125
214
|
contributions: [
|
|
126
215
|
{
|
|
127
216
|
id: "users.profile.menu.settings",
|
|
128
|
-
target: "auth
|
|
217
|
+
target: "auth.profile-menu",
|
|
218
|
+
kind: "link",
|
|
129
219
|
surfaces: ["*"],
|
|
130
220
|
order: 500,
|
|
131
|
-
componentToken: "auth.web.profile.menu.link-item",
|
|
132
221
|
when: "auth.authenticated === true",
|
|
133
222
|
source: "mutations.text#users-web-profile-settings-placement"
|
|
134
223
|
},
|
|
135
224
|
{
|
|
136
225
|
id: "users.home.tools.widget",
|
|
137
|
-
target: "shell
|
|
226
|
+
target: "shell.status",
|
|
227
|
+
kind: "component",
|
|
138
228
|
surfaces: ["home"],
|
|
139
229
|
order: 900,
|
|
140
230
|
componentToken: "users.web.home.tools.widget",
|
|
@@ -143,16 +233,18 @@ export default Object.freeze({
|
|
|
143
233
|
},
|
|
144
234
|
{
|
|
145
235
|
id: "users.home.menu.settings",
|
|
146
|
-
target: "home-
|
|
236
|
+
target: "home.tools-menu",
|
|
237
|
+
kind: "link",
|
|
147
238
|
surfaces: ["home"],
|
|
148
239
|
order: 100,
|
|
149
|
-
componentToken: "local.main.ui.surface-aware-menu-link-item",
|
|
150
240
|
when: "auth.authenticated === true",
|
|
151
241
|
source: "mutations.text#users-web-home-tools-placement"
|
|
152
242
|
},
|
|
153
243
|
{
|
|
154
244
|
id: "users.account.settings.profile",
|
|
155
|
-
target: "
|
|
245
|
+
target: "settings.sections",
|
|
246
|
+
owner: "account-settings",
|
|
247
|
+
kind: "component",
|
|
156
248
|
surfaces: ["account"],
|
|
157
249
|
order: 100,
|
|
158
250
|
componentToken: "local.main.account-settings.section.profile",
|
|
@@ -160,7 +252,9 @@ export default Object.freeze({
|
|
|
160
252
|
},
|
|
161
253
|
{
|
|
162
254
|
id: "users.account.settings.preferences",
|
|
163
|
-
target: "
|
|
255
|
+
target: "settings.sections",
|
|
256
|
+
owner: "account-settings",
|
|
257
|
+
kind: "component",
|
|
164
258
|
surfaces: ["account"],
|
|
165
259
|
order: 200,
|
|
166
260
|
componentToken: "local.main.account-settings.section.preferences",
|
|
@@ -168,7 +262,9 @@ export default Object.freeze({
|
|
|
168
262
|
},
|
|
169
263
|
{
|
|
170
264
|
id: "users.account.settings.notifications",
|
|
171
|
-
target: "
|
|
265
|
+
target: "settings.sections",
|
|
266
|
+
owner: "account-settings",
|
|
267
|
+
kind: "component",
|
|
172
268
|
surfaces: ["account"],
|
|
173
269
|
order: 300,
|
|
174
270
|
componentToken: "local.main.account-settings.section.notifications",
|
|
@@ -181,15 +277,13 @@ export default Object.freeze({
|
|
|
181
277
|
mutations: {
|
|
182
278
|
dependencies: {
|
|
183
279
|
runtime: {
|
|
184
|
-
"@tanstack/vue-query": "5.92.12",
|
|
185
280
|
"@mdi/js": "^7.4.47",
|
|
186
|
-
"@jskit-ai/http-runtime": "0.1.
|
|
187
|
-
"@jskit-ai/realtime": "0.1.
|
|
188
|
-
"@jskit-ai/kernel": "0.1.
|
|
189
|
-
"@jskit-ai/shell-web": "0.1.
|
|
190
|
-
"@jskit-ai/uploads-image-web": "0.1.
|
|
191
|
-
"@jskit-ai/users-core": "0.1.
|
|
192
|
-
vuetify: "^4.0.0"
|
|
281
|
+
"@jskit-ai/http-runtime": "0.1.66",
|
|
282
|
+
"@jskit-ai/realtime": "0.1.66",
|
|
283
|
+
"@jskit-ai/kernel": "0.1.67",
|
|
284
|
+
"@jskit-ai/shell-web": "0.1.66",
|
|
285
|
+
"@jskit-ai/uploads-image-web": "0.1.45",
|
|
286
|
+
"@jskit-ai/users-core": "0.1.77"
|
|
193
287
|
},
|
|
194
288
|
dev: {}
|
|
195
289
|
},
|
|
@@ -249,7 +343,7 @@ export default Object.freeze({
|
|
|
249
343
|
position: "bottom",
|
|
250
344
|
skipIfContains: "id: \"users.profile.menu.settings\"",
|
|
251
345
|
value:
|
|
252
|
-
"\naddPlacement({\n id: \"users.profile.menu.settings\",\n target: \"auth
|
|
346
|
+
"\naddPlacement({\n id: \"users.profile.menu.settings\",\n target: \"auth.profile-menu\",\n kind: \"link\",\n surfaces: [\"*\"],\n order: 500,\n props: {\n label: \"Settings\",\n to: \"/account\"\n },\n when: ({ auth }) => auth?.authenticated === true\n});\n",
|
|
253
347
|
reason: "Append users-web profile settings menu placement into app-owned placement registry.",
|
|
254
348
|
category: "users-web",
|
|
255
349
|
id: "users-web-profile-settings-placement"
|
|
@@ -260,22 +354,44 @@ export default Object.freeze({
|
|
|
260
354
|
position: "bottom",
|
|
261
355
|
skipIfContains: "id: \"users.home.tools.widget\"",
|
|
262
356
|
value:
|
|
263
|
-
"\naddPlacement({\n id: \"users.home.tools.widget\",\n target: \"shell
|
|
357
|
+
"\naddPlacement({\n id: \"users.home.tools.widget\",\n target: \"shell.status\",\n kind: \"component\",\n surfaces: [\"home\"],\n order: 900,\n componentToken: \"users.web.home.tools.widget\",\n when: ({ auth }) => auth?.authenticated === true\n});\n\naddPlacement({\n id: \"users.home.menu.settings\",\n target: \"home.tools-menu\",\n kind: \"link\",\n surfaces: [\"home\"],\n order: 100,\n props: {\n label: \"Settings\",\n surface: \"home\",\n scopedSuffix: \"/settings\",\n unscopedSuffix: \"/settings\"\n },\n when: ({ auth }) => auth?.authenticated === true\n});\n",
|
|
264
358
|
reason: "Append users-web home tools widget and settings menu placements into app-owned placement registry.",
|
|
265
359
|
category: "users-web",
|
|
266
360
|
id: "users-web-home-tools-placement"
|
|
267
361
|
},
|
|
362
|
+
{
|
|
363
|
+
op: "append-text",
|
|
364
|
+
file: "src/placementTopology.js",
|
|
365
|
+
position: "bottom",
|
|
366
|
+
skipIfContains: "id: \"home.tools-menu\"",
|
|
367
|
+
value:
|
|
368
|
+
"\naddPlacementTopology({\n id: \"home.tools-menu\",\n description: \"Home surface tools menu actions.\",\n surfaces: [\"home\"],\n variants: {\n compact: {\n outlet: \"home-cog:primary-menu\",\n renderers: {\n link: \"local.main.ui.surface-aware-menu-link-item\"\n }\n },\n medium: {\n outlet: \"home-cog:primary-menu\",\n renderers: {\n link: \"local.main.ui.surface-aware-menu-link-item\"\n }\n },\n expanded: {\n outlet: \"home-cog:primary-menu\",\n renderers: {\n link: \"local.main.ui.surface-aware-menu-link-item\"\n }\n }\n }\n});\n",
|
|
369
|
+
reason: "Append users-web home tools semantic topology into app-owned placement topology.",
|
|
370
|
+
category: "users-web",
|
|
371
|
+
id: "users-web-home-tools-topology"
|
|
372
|
+
},
|
|
268
373
|
{
|
|
269
374
|
op: "append-text",
|
|
270
375
|
file: "src/placement.js",
|
|
271
376
|
position: "bottom",
|
|
272
377
|
skipIfContains: "id: \"users.account.settings.profile\"",
|
|
273
378
|
value:
|
|
274
|
-
"\naddPlacement({\n id: \"users.account.settings.profile\",\n target: \"account-settings:
|
|
379
|
+
"\naddPlacement({\n id: \"users.account.settings.profile\",\n target: \"settings.sections\",\n owner: \"account-settings\",\n kind: \"component\",\n surfaces: [\"account\"],\n order: 100,\n componentToken: \"local.main.account-settings.section.profile\",\n props: {\n title: \"Profile\",\n value: \"profile\",\n usesSharedRuntime: true\n }\n});\n\naddPlacement({\n id: \"users.account.settings.preferences\",\n target: \"settings.sections\",\n owner: \"account-settings\",\n kind: \"component\",\n surfaces: [\"account\"],\n order: 200,\n componentToken: \"local.main.account-settings.section.preferences\",\n props: {\n title: \"Preferences\",\n value: \"preferences\",\n usesSharedRuntime: true\n }\n});\n\naddPlacement({\n id: \"users.account.settings.notifications\",\n target: \"settings.sections\",\n owner: \"account-settings\",\n kind: \"component\",\n surfaces: [\"account\"],\n order: 300,\n componentToken: \"local.main.account-settings.section.notifications\",\n props: {\n title: \"Notifications\",\n value: \"notifications\",\n usesSharedRuntime: true\n }\n});\n",
|
|
275
380
|
reason: "Append users-web account settings section placements into the app-owned placement registry.",
|
|
276
381
|
category: "users-web",
|
|
277
382
|
id: "users-web-account-settings-sections-placement"
|
|
278
383
|
},
|
|
384
|
+
{
|
|
385
|
+
op: "append-text",
|
|
386
|
+
file: "src/placementTopology.js",
|
|
387
|
+
position: "bottom",
|
|
388
|
+
skipIfContains: "id: \"settings.sections\"",
|
|
389
|
+
value:
|
|
390
|
+
"\naddPlacementTopology({\n id: \"settings.sections\",\n owner: \"account-settings\",\n description: \"Account settings content sections.\",\n surfaces: [\"account\"],\n variants: {\n compact: {\n outlet: \"account-settings:sections\"\n },\n medium: {\n outlet: \"account-settings:sections\"\n },\n expanded: {\n outlet: \"account-settings:sections\"\n }\n }\n});\n",
|
|
391
|
+
reason: "Append users-web account settings semantic topology into app-owned placement topology.",
|
|
392
|
+
category: "users-web",
|
|
393
|
+
id: "users-web-account-settings-topology"
|
|
394
|
+
},
|
|
279
395
|
{
|
|
280
396
|
op: "append-text",
|
|
281
397
|
file: "packages/main/src/client/providers/MainClientProvider.js",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jskit-ai/users-web",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.82",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "node --test"
|
|
@@ -8,22 +8,33 @@
|
|
|
8
8
|
"exports": {
|
|
9
9
|
"./client": "./src/client/index.js",
|
|
10
10
|
"./client/components/AccountSettingsClientElement": "./src/client/components/AccountSettingsClientElement.vue",
|
|
11
|
+
"./client/components/CrudAddEditScreen": "./src/client/components/CrudAddEditScreen.vue",
|
|
12
|
+
"./client/components/CrudListBulkActionSurface": "./src/client/components/CrudListBulkActionSurface.vue",
|
|
13
|
+
"./client/components/CrudListFilterSurface": "./src/client/components/CrudListFilterSurface.vue",
|
|
14
|
+
"./client/components/CrudListScreen": "./src/client/components/CrudListScreen.vue",
|
|
15
|
+
"./client/components/CrudViewScreen": "./src/client/components/CrudViewScreen.vue",
|
|
11
16
|
"./client/account-settings/sections": "./src/client/account-settings/sections.js",
|
|
17
|
+
"./client/bulkActions": "./src/client/bulkActions.js",
|
|
18
|
+
"./client/filters": "./src/client/filters.js",
|
|
12
19
|
"./client/composables/useAddEdit": "./src/client/composables/records/useAddEdit.js",
|
|
13
20
|
"./client/composables/useAccess": "./src/client/composables/useAccess.js",
|
|
14
21
|
"./client/composables/useCommand": "./src/client/composables/useCommand.js",
|
|
15
22
|
"./client/composables/useCrudAddEdit": "./src/client/composables/records/useCrudAddEdit.js",
|
|
23
|
+
"./client/composables/useCrudAddEditScreen": "./src/client/composables/useCrudAddEditScreen.js",
|
|
24
|
+
"./client/composables/useCrudListBulkActions": "./src/client/composables/useCrudListBulkActions.js",
|
|
16
25
|
"./client/composables/crudLookupFieldRuntime": "./src/client/composables/crud/crudLookupFieldRuntime.js",
|
|
17
26
|
"./client/composables/useCrudListFilterLookups": "./src/client/composables/useCrudListFilterLookups.js",
|
|
18
27
|
"./client/composables/useCrudListFilters": "./src/client/composables/useCrudListFilters.js",
|
|
19
28
|
"./client/composables/useEndpointResource": "./src/client/composables/runtime/useEndpointResource.js",
|
|
20
29
|
"./client/composables/useList": "./src/client/composables/records/useList.js",
|
|
21
30
|
"./client/composables/useCrudList": "./src/client/composables/records/useCrudList.js",
|
|
31
|
+
"./client/composables/useCrudListScreen": "./src/client/composables/useCrudListScreen.js",
|
|
22
32
|
"./client/composables/useCrudListParentTitle": "./src/client/composables/useCrudListParentTitle.js",
|
|
23
33
|
"./client/composables/useRealtimeQueryInvalidation": "./src/client/composables/useRealtimeQueryInvalidation.js",
|
|
24
34
|
"./client/composables/useSurfaceRouteContext": "./src/client/composables/useSurfaceRouteContext.js",
|
|
25
35
|
"./client/composables/useView": "./src/client/composables/records/useView.js",
|
|
26
36
|
"./client/composables/useCrudView": "./src/client/composables/records/useCrudView.js",
|
|
37
|
+
"./client/composables/useCrudViewScreen": "./src/client/composables/useCrudViewScreen.js",
|
|
27
38
|
"./client/composables/usePagedCollection": "./src/client/composables/usePagedCollection.js",
|
|
28
39
|
"./client/composables/usePaths": "./src/client/composables/usePaths.js",
|
|
29
40
|
"./client/composables/runtime/useUiFeedback": "./src/client/composables/runtime/useUiFeedback.js",
|
|
@@ -32,18 +43,18 @@
|
|
|
32
43
|
"./client/support/contractGuards": "./src/client/support/contractGuards.js"
|
|
33
44
|
},
|
|
34
45
|
"dependencies": {
|
|
35
|
-
"@tanstack/vue-query": "5.92.12",
|
|
36
46
|
"@mdi/js": "^7.4.47",
|
|
37
|
-
"@jskit-ai/http-runtime": "0.1.
|
|
38
|
-
"@jskit-ai/kernel": "0.1.
|
|
39
|
-
"@jskit-ai/realtime": "0.1.
|
|
40
|
-
"@jskit-ai/shell-web": "0.1.
|
|
41
|
-
"@jskit-ai/uploads-image-web": "0.1.
|
|
42
|
-
"@jskit-ai/users-core": "0.1.
|
|
43
|
-
"vuetify": "^4.0.0"
|
|
47
|
+
"@jskit-ai/http-runtime": "0.1.66",
|
|
48
|
+
"@jskit-ai/kernel": "0.1.67",
|
|
49
|
+
"@jskit-ai/realtime": "0.1.66",
|
|
50
|
+
"@jskit-ai/shell-web": "0.1.66",
|
|
51
|
+
"@jskit-ai/uploads-image-web": "0.1.45",
|
|
52
|
+
"@jskit-ai/users-core": "0.1.77"
|
|
44
53
|
},
|
|
45
54
|
"peerDependencies": {
|
|
55
|
+
"@tanstack/vue-query": "^5.90.5",
|
|
46
56
|
"vue": "^3.5.13",
|
|
47
|
-
"vue-router": "^5.0.4"
|
|
57
|
+
"vue-router": "^5.0.4",
|
|
58
|
+
"vuetify": "^4.0.0"
|
|
48
59
|
}
|
|
49
60
|
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { normalizeText } from "@jskit-ai/kernel/shared/support/normalize";
|
|
2
|
+
|
|
3
|
+
function normalizeCrudListBulkAction(rawAction = {}, index = 0) {
|
|
4
|
+
if (!rawAction || typeof rawAction !== "object" || Array.isArray(rawAction)) {
|
|
5
|
+
return null;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const key = normalizeText(rawAction.key || rawAction.id || `action-${index + 1}`);
|
|
9
|
+
const label = normalizeText(rawAction.label || rawAction.title);
|
|
10
|
+
if (!key || !label) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return Object.freeze({
|
|
15
|
+
key,
|
|
16
|
+
label,
|
|
17
|
+
icon: normalizeText(rawAction.icon),
|
|
18
|
+
color: normalizeText(rawAction.color, { fallback: "primary" }),
|
|
19
|
+
variant: normalizeText(rawAction.variant, { fallback: "tonal" }),
|
|
20
|
+
confirmLabel: normalizeText(rawAction.confirmLabel),
|
|
21
|
+
run: typeof rawAction.run === "function" ? rawAction.run : null,
|
|
22
|
+
disabled: rawAction.disabled
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function defineCrudListBulkActions(actions = []) {
|
|
27
|
+
if (!Array.isArray(actions)) {
|
|
28
|
+
throw new TypeError("defineCrudListBulkActions requires an array.");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const normalizedActions = [];
|
|
32
|
+
const seenKeys = new Set();
|
|
33
|
+
|
|
34
|
+
actions.forEach((rawAction, index) => {
|
|
35
|
+
const action = normalizeCrudListBulkAction(rawAction, index);
|
|
36
|
+
if (!action || seenKeys.has(action.key)) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
seenKeys.add(action.key);
|
|
41
|
+
normalizedActions.push(action);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
return Object.freeze(normalizedActions);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export { defineCrudListBulkActions };
|
|
@@ -56,28 +56,41 @@ const activeTab = computed({
|
|
|
56
56
|
|
|
57
57
|
<template>
|
|
58
58
|
<section class="settings-view py-2 py-md-4">
|
|
59
|
-
<v-
|
|
60
|
-
<
|
|
61
|
-
<
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
59
|
+
<v-sheet class="settings-panel" rounded="lg" border>
|
|
60
|
+
<header class="settings-panel__header">
|
|
61
|
+
<div>
|
|
62
|
+
<h1 class="settings-panel__title">Account settings</h1>
|
|
63
|
+
<p class="text-body-2 text-medium-emphasis mb-0">
|
|
64
|
+
Global profile, preferences, notifications, and account controls.
|
|
65
|
+
</p>
|
|
66
|
+
</div>
|
|
67
|
+
<v-btn
|
|
68
|
+
variant="text"
|
|
69
|
+
color="secondary"
|
|
70
|
+
:to="runtime.backNavigationTarget.value.sameOrigin ? runtime.backNavigationTarget.value.href : undefined"
|
|
71
|
+
:href="runtime.backNavigationTarget.value.sameOrigin ? undefined : runtime.backNavigationTarget.value.href"
|
|
72
|
+
>
|
|
73
|
+
Back
|
|
74
|
+
</v-btn>
|
|
75
|
+
</header>
|
|
75
76
|
|
|
76
|
-
<
|
|
77
|
+
<div class="settings-panel__body">
|
|
77
78
|
<template v-if="runtime.loadingSettings.value">
|
|
78
79
|
<v-skeleton-loader type="text@2, list-item-two-line@4" class="mb-4" />
|
|
79
80
|
<v-skeleton-loader type="text@2, paragraph, button" />
|
|
80
81
|
</template>
|
|
82
|
+
<div v-else-if="runtime.settingsLoadError.value" class="settings-panel__state">
|
|
83
|
+
<h2 class="text-h6 mb-2">Unable to load account settings</h2>
|
|
84
|
+
<p class="text-body-2 text-medium-emphasis mb-4">{{ runtime.settingsLoadError.value }}</p>
|
|
85
|
+
<v-btn
|
|
86
|
+
color="primary"
|
|
87
|
+
variant="tonal"
|
|
88
|
+
:loading="runtime.refreshingSettings.value"
|
|
89
|
+
@click="runtime.refreshSettings"
|
|
90
|
+
>
|
|
91
|
+
Retry
|
|
92
|
+
</v-btn>
|
|
93
|
+
</div>
|
|
81
94
|
<template v-else-if="sections.length < 1">
|
|
82
95
|
<p class="text-body-2 text-medium-emphasis mb-0">No account settings sections are registered.</p>
|
|
83
96
|
</template>
|
|
@@ -109,20 +122,42 @@ const activeTab = computed({
|
|
|
109
122
|
</v-col>
|
|
110
123
|
</v-row>
|
|
111
124
|
</template>
|
|
112
|
-
</
|
|
113
|
-
</v-
|
|
125
|
+
</div>
|
|
126
|
+
</v-sheet>
|
|
114
127
|
</section>
|
|
115
128
|
</template>
|
|
116
129
|
|
|
117
130
|
<style scoped>
|
|
118
|
-
.panel
|
|
131
|
+
.settings-panel {
|
|
119
132
|
background-color: rgb(var(--v-theme-surface));
|
|
133
|
+
overflow: hidden;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.settings-panel__header {
|
|
137
|
+
align-items: flex-start;
|
|
138
|
+
display: flex;
|
|
139
|
+
gap: 1rem;
|
|
140
|
+
justify-content: space-between;
|
|
141
|
+
padding: 1rem 1rem 0;
|
|
120
142
|
}
|
|
121
143
|
|
|
122
|
-
.
|
|
123
|
-
font-size:
|
|
124
|
-
font-weight:
|
|
125
|
-
letter-spacing: 0.
|
|
144
|
+
.settings-panel__title {
|
|
145
|
+
font-size: clamp(1.35rem, 2vw, 1.85rem);
|
|
146
|
+
font-weight: 650;
|
|
147
|
+
letter-spacing: -0.02em;
|
|
148
|
+
line-height: 1.15;
|
|
149
|
+
margin: 0 0 0.35rem;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.settings-panel__body {
|
|
153
|
+
padding: 1rem;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.settings-panel__state {
|
|
157
|
+
margin-inline: auto;
|
|
158
|
+
max-width: 30rem;
|
|
159
|
+
padding: 2rem 1rem;
|
|
160
|
+
text-align: center;
|
|
126
161
|
}
|
|
127
162
|
|
|
128
163
|
.settings-section-list {
|
|
@@ -139,4 +174,14 @@ const activeTab = computed({
|
|
|
139
174
|
:deep(.settings-sections-window .v-window-x-reverse-transition-leave-active) {
|
|
140
175
|
transition: none !important;
|
|
141
176
|
}
|
|
177
|
+
|
|
178
|
+
@media (max-width: 960px) {
|
|
179
|
+
.settings-panel__header {
|
|
180
|
+
flex-direction: column;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.settings-panel__header :deep(.v-btn) {
|
|
184
|
+
min-height: 48px;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
142
187
|
</style>
|