@conduction/nextcloud-vue 0.1.0-beta.2 → 0.1.0-beta.4
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 +226 -226
- package/css/index.css +5 -0
- package/dist/nextcloud-vue.cjs.js +60455 -8755
- package/dist/nextcloud-vue.cjs.js.map +1 -1
- package/dist/nextcloud-vue.css +2062 -528
- package/dist/nextcloud-vue.esm.js +60411 -8731
- package/dist/nextcloud-vue.esm.js.map +1 -1
- package/package.json +75 -61
- package/src/components/CnActionsBar/CnActionsBar.vue +235 -225
- package/src/components/CnActionsBar/index.js +1 -1
- package/src/components/CnAdvancedFormDialog/CnAdvancedFormDialog.vue +579 -0
- package/src/components/CnAdvancedFormDialog/CnDataTab.vue +217 -0
- package/src/components/CnAdvancedFormDialog/CnMetadataTab.vue +121 -0
- package/src/components/CnAdvancedFormDialog/CnPropertiesTab.vue +418 -0
- package/src/components/CnAdvancedFormDialog/CnPropertyValueCell.vue +247 -0
- package/src/components/CnAdvancedFormDialog/index.js +1 -0
- package/src/components/CnCardGrid/CnCardGrid.vue +152 -152
- package/src/components/CnCardGrid/index.js +1 -1
- package/src/components/CnCellRenderer/CnCellRenderer.vue +132 -132
- package/src/components/CnCellRenderer/index.js +1 -1
- package/src/components/CnChartWidget/CnChartWidget.vue +320 -0
- package/src/components/CnChartWidget/index.js +1 -0
- package/src/components/CnConfigurationCard/CnConfigurationCard.vue +77 -77
- package/src/components/CnConfigurationCard/index.js +1 -1
- package/src/components/CnDashboardGrid/CnDashboardGrid.vue +225 -0
- package/src/components/CnDashboardGrid/index.js +1 -0
- package/src/components/CnDashboardPage/CnDashboardPage.vue +390 -0
- package/src/components/CnDashboardPage/index.js +1 -0
- package/src/components/CnDataTable/CnDataTable.vue +349 -349
- package/src/components/CnDataTable/index.js +1 -1
- package/src/components/CnDetailCard/CnDetailCard.vue +214 -0
- package/src/components/CnDetailCard/index.js +1 -0
- package/src/components/CnDetailPage/CnDetailPage.vue +281 -0
- package/src/components/CnDetailPage/index.js +1 -0
- package/src/components/CnFacetSidebar/CnFacetSidebar.vue +231 -223
- package/src/components/CnFacetSidebar/index.js +1 -1
- package/src/components/CnFilterBar/CnFilterBar.vue +152 -152
- package/src/components/CnFilterBar/index.js +1 -1
- package/src/components/CnIcon/CnIcon.vue +89 -89
- package/src/components/CnIcon/index.js +1 -1
- package/src/components/CnIndexPage/CnIndexPage.vue +874 -816
- package/src/components/CnIndexPage/index.js +1 -1
- package/src/components/CnIndexSidebar/CnIndexSidebar.vue +503 -484
- package/src/components/CnIndexSidebar/index.js +1 -1
- package/src/components/CnItemCard/CnItemCard.vue +132 -0
- package/src/components/CnItemCard/index.js +1 -0
- package/src/components/CnKpiGrid/CnKpiGrid.vue +89 -89
- package/src/components/CnKpiGrid/index.js +1 -1
- package/src/components/CnMassActionBar/CnMassActionBar.vue +160 -160
- package/src/components/CnMassActionBar/index.js +1 -1
- package/src/components/CnMassCopyDialog/CnMassCopyDialog.vue +320 -320
- package/src/components/CnMassCopyDialog/index.js +1 -1
- package/src/components/CnMassDeleteDialog/CnMassDeleteDialog.vue +238 -238
- package/src/components/CnMassDeleteDialog/index.js +1 -1
- package/src/components/CnMassExportDialog/CnMassExportDialog.vue +190 -190
- package/src/components/CnMassExportDialog/index.js +1 -1
- package/src/components/CnMassImportDialog/CnMassImportDialog.vue +491 -491
- package/src/components/CnMassImportDialog/index.js +1 -1
- package/src/components/CnNoteCard/CnNoteCard.vue +149 -0
- package/src/components/CnNoteCard/index.js +1 -0
- package/src/components/CnNotesCard/CnNotesCard.vue +413 -0
- package/src/components/CnNotesCard/index.js +1 -0
- package/src/components/CnObjectCard/CnObjectCard.vue +292 -292
- package/src/components/CnObjectCard/index.js +1 -1
- package/src/components/CnObjectSidebar/CnObjectSidebar.vue +876 -0
- package/src/components/CnObjectSidebar/index.js +1 -0
- package/src/components/CnPageHeader/CnPageHeader.vue +57 -57
- package/src/components/CnPageHeader/index.js +1 -1
- package/src/components/CnPagination/CnPagination.vue +252 -252
- package/src/components/CnPagination/index.js +1 -1
- package/src/components/CnRowActions/CnRowActions.vue +73 -73
- package/src/components/CnRowActions/index.js +1 -1
- package/src/components/CnSchemaFormDialog/CnSchemaConfigurationTab.vue +226 -0
- package/src/components/CnSchemaFormDialog/CnSchemaFormDialog.vue +787 -0
- package/src/components/CnSchemaFormDialog/CnSchemaPropertiesTab.vue +305 -0
- package/src/components/CnSchemaFormDialog/CnSchemaPropertyActions.vue +1398 -0
- package/src/components/CnSchemaFormDialog/CnSchemaSecurityTab.vue +236 -0
- package/src/components/CnSchemaFormDialog/index.js +1 -0
- package/src/components/CnSettingsCard/CnSettingsCard.vue +92 -92
- package/src/components/CnSettingsCard/index.js +1 -1
- package/src/components/CnSettingsSection/CnSettingsSection.vue +266 -266
- package/src/components/CnSettingsSection/index.js +1 -1
- package/src/components/CnStatsBlock/CnStatsBlock.vue +420 -366
- package/src/components/CnStatsBlock/index.js +1 -1
- package/src/components/CnStatusBadge/CnStatusBadge.vue +77 -77
- package/src/components/CnStatusBadge/index.js +1 -1
- package/src/components/CnTabbedFormDialog/CnTabbedFormDialog.vue +540 -0
- package/src/components/CnTabbedFormDialog/index.js +1 -0
- package/src/components/CnTasksCard/CnTasksCard.vue +373 -0
- package/src/components/CnTasksCard/index.js +1 -0
- package/src/components/CnTileWidget/CnTileWidget.vue +159 -0
- package/src/components/CnTileWidget/index.js +1 -0
- package/src/components/CnTimelineStages/CnTimelineStages.vue +292 -0
- package/src/components/CnTimelineStages/index.js +1 -0
- package/src/components/CnUserActionMenu/CnUserActionMenu.vue +435 -0
- package/src/components/CnUserActionMenu/index.js +1 -0
- package/src/components/CnVersionInfoCard/CnVersionInfoCard.vue +312 -312
- package/src/components/CnVersionInfoCard/index.js +1 -1
- package/src/components/CnWidgetRenderer/CnWidgetRenderer.vue +180 -0
- package/src/components/CnWidgetRenderer/index.js +1 -0
- package/src/components/CnWidgetWrapper/CnWidgetWrapper.vue +211 -0
- package/src/components/CnWidgetWrapper/index.js +1 -0
- package/src/components/index.js +43 -29
- package/src/composables/index.js +4 -3
- package/src/composables/useDashboardView.js +240 -0
- package/src/composables/useDetailView.js +289 -132
- package/src/composables/useListView.js +363 -153
- package/src/composables/useSubResource.js +142 -142
- package/src/constants/metadata.js +30 -30
- package/src/css/CnSchemaFormDialog.css +546 -0
- package/src/css/__sample_nextcloud_tokens.css +110 -0
- package/src/css/actions-bar.css +48 -48
- package/src/css/badge.css +51 -51
- package/src/css/card.css +128 -128
- package/src/css/dashboard.css +70 -0
- package/src/css/detail-page.css +168 -0
- package/src/css/detail.css +68 -68
- package/src/css/index-page.css +44 -32
- package/src/css/index-sidebar.css +193 -187
- package/src/css/index.css +16 -12
- package/src/css/layout.css +90 -90
- package/src/css/page-header.css +33 -33
- package/src/css/pagination.css +72 -72
- package/src/css/table.css +142 -142
- package/src/css/timeline-stages.css +218 -0
- package/src/css/utilities.css +46 -46
- package/src/index.js +72 -53
- package/src/store/createSubResourcePlugin.js +135 -135
- package/src/store/index.js +3 -3
- package/src/store/plugins/auditTrails.js +17 -17
- package/src/store/plugins/files.js +250 -186
- package/src/store/plugins/index.js +7 -5
- package/src/store/plugins/lifecycle.js +180 -180
- package/src/store/plugins/relations.js +68 -68
- package/src/store/plugins/search.js +372 -0
- package/src/store/plugins/selection.js +104 -0
- package/src/store/useObjectStore.js +829 -686
- package/src/types/auditTrail.d.ts +32 -32
- package/src/types/file.d.ts +23 -23
- package/src/types/index.d.ts +35 -35
- package/src/types/notification.d.ts +36 -36
- package/src/types/object.d.ts +40 -40
- package/src/types/organisation.d.ts +41 -41
- package/src/types/register.d.ts +25 -25
- package/src/types/schema.d.ts +39 -39
- package/src/types/shared.d.ts +79 -79
- package/src/types/source.d.ts +14 -14
- package/src/types/task.d.ts +31 -31
- package/src/utils/errors.js +96 -96
- package/src/utils/headers.js +68 -50
- package/src/utils/id.js +13 -0
- package/src/utils/index.js +3 -3
- package/src/utils/schema.js +422 -419
|
@@ -1,816 +1,874 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div class="cn-index-page">
|
|
3
|
-
<!-- Header (hidden by default — shown in sidebar instead) -->
|
|
4
|
-
<CnPageHeader
|
|
5
|
-
v-if="showTitle"
|
|
6
|
-
:title="title"
|
|
7
|
-
:description="description"
|
|
8
|
-
:icon="resolvedIcon" />
|
|
9
|
-
|
|
10
|
-
<!--
|
|
11
|
-
<
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
:
|
|
18
|
-
:
|
|
19
|
-
:
|
|
20
|
-
:
|
|
21
|
-
:
|
|
22
|
-
:
|
|
23
|
-
:
|
|
24
|
-
:show-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
@
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
<template v-if="$scopedSlots['
|
|
39
|
-
<slot name="
|
|
40
|
-
</template>
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
<!--
|
|
153
|
-
<
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
</
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
import {
|
|
247
|
-
import
|
|
248
|
-
import
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
*
|
|
270
|
-
*
|
|
271
|
-
*
|
|
272
|
-
*
|
|
273
|
-
*
|
|
274
|
-
*
|
|
275
|
-
*
|
|
276
|
-
*
|
|
277
|
-
*
|
|
278
|
-
*
|
|
279
|
-
*
|
|
280
|
-
*
|
|
281
|
-
*
|
|
282
|
-
*
|
|
283
|
-
*
|
|
284
|
-
*
|
|
285
|
-
*
|
|
286
|
-
*
|
|
287
|
-
*
|
|
288
|
-
*
|
|
289
|
-
*
|
|
290
|
-
*
|
|
291
|
-
*
|
|
292
|
-
*
|
|
293
|
-
*
|
|
294
|
-
*
|
|
295
|
-
*
|
|
296
|
-
*
|
|
297
|
-
* @
|
|
298
|
-
*
|
|
299
|
-
*
|
|
300
|
-
*
|
|
301
|
-
*
|
|
302
|
-
*
|
|
303
|
-
*
|
|
304
|
-
* @
|
|
305
|
-
* @
|
|
306
|
-
* @
|
|
307
|
-
* @
|
|
308
|
-
* @
|
|
309
|
-
* @
|
|
310
|
-
* @
|
|
311
|
-
* @
|
|
312
|
-
* @
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
},
|
|
402
|
-
/**
|
|
403
|
-
|
|
404
|
-
type:
|
|
405
|
-
default:
|
|
406
|
-
},
|
|
407
|
-
/**
|
|
408
|
-
|
|
409
|
-
type:
|
|
410
|
-
default:
|
|
411
|
-
},
|
|
412
|
-
/**
|
|
413
|
-
|
|
414
|
-
type:
|
|
415
|
-
default:
|
|
416
|
-
},
|
|
417
|
-
/**
|
|
418
|
-
|
|
419
|
-
type:
|
|
420
|
-
default:
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
if (this.
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
this.
|
|
690
|
-
this
|
|
691
|
-
},
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
this
|
|
697
|
-
},
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
this.$
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
},
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
1
|
+
<template>
|
|
2
|
+
<div class="cn-index-page">
|
|
3
|
+
<!-- Header (hidden by default — shown in sidebar instead) -->
|
|
4
|
+
<CnPageHeader
|
|
5
|
+
v-if="showTitle"
|
|
6
|
+
:title="title"
|
|
7
|
+
:description="description"
|
|
8
|
+
:icon="resolvedIcon" />
|
|
9
|
+
|
|
10
|
+
<!-- Optional content below header, above actions bar -->
|
|
11
|
+
<div v-if="$scopedSlots['below-header']" class="cn-index-page__below-header">
|
|
12
|
+
<slot name="below-header" />
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
<!-- Actions bar -->
|
|
16
|
+
<CnActionsBar
|
|
17
|
+
:pagination="pagination"
|
|
18
|
+
:object-count="objects.length"
|
|
19
|
+
:selectable="selectable"
|
|
20
|
+
:selected-ids="internalSelectedIds"
|
|
21
|
+
:add-label="resolvedAddLabel"
|
|
22
|
+
:add-icon="resolvedIcon"
|
|
23
|
+
:inline-action-count="inlineActionCount"
|
|
24
|
+
:show-mass-import="showMassImport"
|
|
25
|
+
:show-mass-export="showMassExport"
|
|
26
|
+
:show-mass-copy="showMassCopy"
|
|
27
|
+
:show-mass-delete="showMassDelete"
|
|
28
|
+
:view-mode="currentViewMode"
|
|
29
|
+
:show-view-toggle="showViewToggle"
|
|
30
|
+
:refreshing="refreshing"
|
|
31
|
+
@add="onAddClick"
|
|
32
|
+
@refresh="$emit('refresh')"
|
|
33
|
+
@show-import="showImportDialog = true"
|
|
34
|
+
@show-export="showExportDialog = true"
|
|
35
|
+
@show-copy="showMassCopyDialog = true"
|
|
36
|
+
@show-delete="showMassDeleteDialog = true"
|
|
37
|
+
@view-mode-change="onViewModeChange">
|
|
38
|
+
<template v-if="$scopedSlots['mass-actions']" #mass-actions="{ count, selectedIds: ids }">
|
|
39
|
+
<slot name="mass-actions" :count="count" :selected-ids="ids" />
|
|
40
|
+
</template>
|
|
41
|
+
<template v-if="$scopedSlots['action-items']" #action-items>
|
|
42
|
+
<slot name="action-items" />
|
|
43
|
+
</template>
|
|
44
|
+
<template v-if="$scopedSlots['header-actions']" #header-actions>
|
|
45
|
+
<slot name="header-actions" />
|
|
46
|
+
</template>
|
|
47
|
+
</CnActionsBar>
|
|
48
|
+
|
|
49
|
+
<!-- Mass delete dialog -->
|
|
50
|
+
<CnMassDeleteDialog
|
|
51
|
+
v-if="showMassDeleteDialog"
|
|
52
|
+
ref="massDeleteDialog"
|
|
53
|
+
:items="selectedObjects"
|
|
54
|
+
:name-field="massActionNameField"
|
|
55
|
+
@confirm="onMassDeleteConfirm"
|
|
56
|
+
@close="showMassDeleteDialog = false" />
|
|
57
|
+
|
|
58
|
+
<!-- Mass copy dialog -->
|
|
59
|
+
<CnMassCopyDialog
|
|
60
|
+
v-if="showMassCopyDialog"
|
|
61
|
+
ref="massCopyDialog"
|
|
62
|
+
:items="selectedObjects"
|
|
63
|
+
:name-field="massActionNameField"
|
|
64
|
+
@confirm="onMassCopyConfirm"
|
|
65
|
+
@close="showMassCopyDialog = false" />
|
|
66
|
+
|
|
67
|
+
<!-- Mass export dialog -->
|
|
68
|
+
<CnMassExportDialog
|
|
69
|
+
v-if="showExportDialog"
|
|
70
|
+
ref="exportDialog"
|
|
71
|
+
:formats="exportFormats"
|
|
72
|
+
@confirm="onMassExportConfirm"
|
|
73
|
+
@close="showExportDialog = false" />
|
|
74
|
+
|
|
75
|
+
<!-- Mass import dialog -->
|
|
76
|
+
<CnMassImportDialog
|
|
77
|
+
v-if="showImportDialog"
|
|
78
|
+
ref="importDialog"
|
|
79
|
+
:options="importOptions"
|
|
80
|
+
@confirm="onMassImportConfirm"
|
|
81
|
+
@close="showImportDialog = false">
|
|
82
|
+
<template v-if="$scopedSlots['import-fields']" #fields="{ file }">
|
|
83
|
+
<slot name="import-fields" :file="file" />
|
|
84
|
+
</template>
|
|
85
|
+
</CnMassImportDialog>
|
|
86
|
+
|
|
87
|
+
<!-- Single delete dialog (overridable via slot) -->
|
|
88
|
+
<slot
|
|
89
|
+
name="delete-dialog"
|
|
90
|
+
:item="actionTargetItem"
|
|
91
|
+
:close="closeSingleDelete">
|
|
92
|
+
<CnDeleteDialog
|
|
93
|
+
v-if="showSingleDeleteDialog && actionTargetItem"
|
|
94
|
+
ref="singleDeleteDialog"
|
|
95
|
+
:item="actionTargetItem"
|
|
96
|
+
:name-field="massActionNameField"
|
|
97
|
+
@confirm="onSingleDeleteConfirm"
|
|
98
|
+
@close="closeSingleDelete" />
|
|
99
|
+
</slot>
|
|
100
|
+
|
|
101
|
+
<!-- Single copy dialog (overridable via slot) -->
|
|
102
|
+
<slot
|
|
103
|
+
name="copy-dialog"
|
|
104
|
+
:item="actionTargetItem"
|
|
105
|
+
:close="closeSingleCopy">
|
|
106
|
+
<CnCopyDialog
|
|
107
|
+
v-if="showSingleCopyDialog && actionTargetItem"
|
|
108
|
+
ref="singleCopyDialog"
|
|
109
|
+
:item="actionTargetItem"
|
|
110
|
+
:name-field="massActionNameField"
|
|
111
|
+
@confirm="onSingleCopyConfirm"
|
|
112
|
+
@close="closeSingleCopy" />
|
|
113
|
+
</slot>
|
|
114
|
+
|
|
115
|
+
<!-- Form dialog for create/edit (overridable via slot) -->
|
|
116
|
+
<slot
|
|
117
|
+
name="form-dialog"
|
|
118
|
+
:item="editItem"
|
|
119
|
+
:schema="schema"
|
|
120
|
+
:close="closeFormDialog">
|
|
121
|
+
<CnFormDialog
|
|
122
|
+
v-if="showFormDialogVisible && !useAdvancedFormDialog"
|
|
123
|
+
ref="formDialog"
|
|
124
|
+
:schema="schema"
|
|
125
|
+
:item="editItem"
|
|
126
|
+
:exclude-fields="excludeFields"
|
|
127
|
+
:include-fields="includeFields"
|
|
128
|
+
:field-overrides="fieldOverrides"
|
|
129
|
+
:name-field="massActionNameField"
|
|
130
|
+
@confirm="onFormConfirm"
|
|
131
|
+
@close="closeFormDialog">
|
|
132
|
+
<template v-if="$scopedSlots['form-fields']" #form="scope">
|
|
133
|
+
<slot name="form-fields" v-bind="scope" />
|
|
134
|
+
</template>
|
|
135
|
+
</CnFormDialog>
|
|
136
|
+
<CnAdvancedFormDialog
|
|
137
|
+
v-if="showFormDialogVisible && useAdvancedFormDialog"
|
|
138
|
+
ref="formDialog"
|
|
139
|
+
:schema="schema"
|
|
140
|
+
:item="editItem"
|
|
141
|
+
:exclude-fields="excludeFields"
|
|
142
|
+
:include-fields="includeFields"
|
|
143
|
+
:field-overrides="fieldOverrides"
|
|
144
|
+
:name-field="massActionNameField"
|
|
145
|
+
@confirm="onFormConfirm"
|
|
146
|
+
@close="closeFormDialog" />
|
|
147
|
+
</slot>
|
|
148
|
+
|
|
149
|
+
<!-- Body -->
|
|
150
|
+
<div class="cn-index-page__body">
|
|
151
|
+
<div class="cn-index-page__main">
|
|
152
|
+
<!-- Loading state -->
|
|
153
|
+
<div v-if="loading" class="cn-index-page__loading">
|
|
154
|
+
<NcLoadingIcon :size="32" />
|
|
155
|
+
</div>
|
|
156
|
+
|
|
157
|
+
<!-- Empty state -->
|
|
158
|
+
<div v-else-if="objects.length === 0" class="cn-index-page__empty">
|
|
159
|
+
<slot name="empty">
|
|
160
|
+
<NcEmptyContent :name="emptyText">
|
|
161
|
+
<template #icon>
|
|
162
|
+
<CnIcon v-if="resolvedIcon" :name="resolvedIcon" :size="64" />
|
|
163
|
+
<DatabaseSearch v-else :size="64" />
|
|
164
|
+
</template>
|
|
165
|
+
</NcEmptyContent>
|
|
166
|
+
</slot>
|
|
167
|
+
</div>
|
|
168
|
+
|
|
169
|
+
<!-- Table view -->
|
|
170
|
+
<CnDataTable
|
|
171
|
+
v-else-if="currentViewMode === 'table'"
|
|
172
|
+
:schema="schema"
|
|
173
|
+
:columns="columns"
|
|
174
|
+
:rows="objects"
|
|
175
|
+
:sort-key="sortKey"
|
|
176
|
+
:sort-order="sortOrder"
|
|
177
|
+
:selectable="selectable"
|
|
178
|
+
:selected-ids="internalSelectedIds"
|
|
179
|
+
:row-key="rowKey"
|
|
180
|
+
:empty-text="emptyText"
|
|
181
|
+
:exclude-columns="excludeColumns"
|
|
182
|
+
:include-columns="includeColumns"
|
|
183
|
+
:column-overrides="columnOverrides"
|
|
184
|
+
:row-class="rowClass"
|
|
185
|
+
@sort="$emit('sort', $event)"
|
|
186
|
+
@select="onSelect"
|
|
187
|
+
@row-click="$emit('row-click', $event)">
|
|
188
|
+
<!-- Pass through column slots -->
|
|
189
|
+
<template
|
|
190
|
+
v-for="col in slotColumns"
|
|
191
|
+
#[`column-${col}`]="{ row, value }">
|
|
192
|
+
<slot :name="'column-' + col" :row="row" :value="value" />
|
|
193
|
+
</template>
|
|
194
|
+
|
|
195
|
+
<!-- Row actions -->
|
|
196
|
+
<template v-if="hasRowActions" #row-actions="{ row }">
|
|
197
|
+
<slot name="row-actions" :row="row">
|
|
198
|
+
<CnRowActions
|
|
199
|
+
:actions="mergedActions"
|
|
200
|
+
:row="row"
|
|
201
|
+
@action="$emit('action', $event)" />
|
|
202
|
+
</slot>
|
|
203
|
+
</template>
|
|
204
|
+
</CnDataTable>
|
|
205
|
+
|
|
206
|
+
<!-- Card view -->
|
|
207
|
+
<CnCardGrid
|
|
208
|
+
v-else
|
|
209
|
+
:objects="objects"
|
|
210
|
+
:schema="schema"
|
|
211
|
+
:selectable="selectable"
|
|
212
|
+
:selected-ids="internalSelectedIds"
|
|
213
|
+
:row-key="rowKey"
|
|
214
|
+
:empty-text="emptyText"
|
|
215
|
+
@click="$emit('row-click', $event)"
|
|
216
|
+
@select="onSelect">
|
|
217
|
+
<template v-if="$scopedSlots.card" #card="{ object, selected }">
|
|
218
|
+
<slot name="card" :object="object" :selected="selected" />
|
|
219
|
+
</template>
|
|
220
|
+
<template v-if="hasRowActions" #card-actions="{ object }">
|
|
221
|
+
<slot name="row-actions" :row="object">
|
|
222
|
+
<CnRowActions
|
|
223
|
+
:actions="mergedActions"
|
|
224
|
+
:row="object"
|
|
225
|
+
@action="$emit('action', $event)" />
|
|
226
|
+
</slot>
|
|
227
|
+
</template>
|
|
228
|
+
</CnCardGrid>
|
|
229
|
+
|
|
230
|
+
<!-- Pagination -->
|
|
231
|
+
<CnPagination
|
|
232
|
+
v-if="pagination && pagination.pages > 1"
|
|
233
|
+
:current-page="pagination.page || 1"
|
|
234
|
+
:total-pages="pagination.pages || 1"
|
|
235
|
+
:total-items="pagination.total || 0"
|
|
236
|
+
:current-page-size="pagination.limit || 20"
|
|
237
|
+
class="cn-index-page__pagination"
|
|
238
|
+
@page-changed="$emit('page-changed', $event)"
|
|
239
|
+
@page-size-changed="$emit('page-size-changed', $event)" />
|
|
240
|
+
</div>
|
|
241
|
+
</div>
|
|
242
|
+
</div>
|
|
243
|
+
</template>
|
|
244
|
+
|
|
245
|
+
<script>
|
|
246
|
+
import { NcLoadingIcon, NcEmptyContent } from '@nextcloud/vue'
|
|
247
|
+
import DatabaseSearch from 'vue-material-design-icons/DatabaseSearch.vue'
|
|
248
|
+
import Eye from 'vue-material-design-icons/Eye.vue'
|
|
249
|
+
import Pencil from 'vue-material-design-icons/Pencil.vue'
|
|
250
|
+
import ContentCopy from 'vue-material-design-icons/ContentCopy.vue'
|
|
251
|
+
import TrashCanOutline from 'vue-material-design-icons/TrashCanOutline.vue'
|
|
252
|
+
import { CnPageHeader } from '../CnPageHeader/index.js'
|
|
253
|
+
import { CnActionsBar } from '../CnActionsBar/index.js'
|
|
254
|
+
import { CnIcon, ICON_MAP } from '../CnIcon/index.js'
|
|
255
|
+
import { CnDataTable } from '../CnDataTable/index.js'
|
|
256
|
+
import { CnCardGrid } from '../CnCardGrid/index.js'
|
|
257
|
+
import { CnPagination } from '../CnPagination/index.js'
|
|
258
|
+
import { CnRowActions } from '../CnRowActions/index.js'
|
|
259
|
+
import { CnMassDeleteDialog } from '../CnMassDeleteDialog/index.js'
|
|
260
|
+
import { CnMassCopyDialog } from '../CnMassCopyDialog/index.js'
|
|
261
|
+
import { CnMassExportDialog } from '../CnMassExportDialog/index.js'
|
|
262
|
+
import { CnMassImportDialog } from '../CnMassImportDialog/index.js'
|
|
263
|
+
import { CnDeleteDialog } from '../CnDeleteDialog/index.js'
|
|
264
|
+
import { CnCopyDialog } from '../CnCopyDialog/index.js'
|
|
265
|
+
import { CnFormDialog } from '../CnFormDialog/index.js'
|
|
266
|
+
import { CnAdvancedFormDialog } from '../CnAdvancedFormDialog/index.js'
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* CnIndexPage — Top-level schema-driven index page component.
|
|
270
|
+
*
|
|
271
|
+
* Assembles sub-components (CnPageHeader, CnActionsBar, table, cards,
|
|
272
|
+
* pagination, mass actions, single-object dialogs) into a single
|
|
273
|
+
* zero-config page.
|
|
274
|
+
*
|
|
275
|
+
* Dialogs are overridable via named slots:
|
|
276
|
+
* - `#form-dialog` — Replace the create/edit dialog entirely
|
|
277
|
+
* - `#delete-dialog` — Replace the single-item delete dialog
|
|
278
|
+
* - `#copy-dialog` — Replace the single-item copy dialog
|
|
279
|
+
* - `#form-fields` — Replace only the form content inside the built-in form dialog (CnFormDialog only)
|
|
280
|
+
*
|
|
281
|
+
* Use the `useAdvancedFormDialog` prop to use CnAdvancedFormDialog for create/edit (properties table, JSON tab, optional metadata).
|
|
282
|
+
*
|
|
283
|
+
* @example Minimal usage (auto-generated dialogs from schema)
|
|
284
|
+
* <CnIndexPage
|
|
285
|
+
* title="Clients"
|
|
286
|
+
* :schema="schema"
|
|
287
|
+
* :objects="clients"
|
|
288
|
+
* :pagination="pagination"
|
|
289
|
+
* :loading="loading"
|
|
290
|
+
* @create="onCreate"
|
|
291
|
+
* @edit="onEdit"
|
|
292
|
+
* @delete="onDelete"
|
|
293
|
+
* @refresh="fetchClients"
|
|
294
|
+
* @row-click="openClient"
|
|
295
|
+
* @page-changed="onPage" />
|
|
296
|
+
*
|
|
297
|
+
* @example With custom form dialog
|
|
298
|
+
* <CnIndexPage ...>
|
|
299
|
+
* <template #form-dialog="{ item, schema, close }">
|
|
300
|
+
* <MyCustomFormDialog :item="item" @close="close" />
|
|
301
|
+
* </template>
|
|
302
|
+
* </CnIndexPage>
|
|
303
|
+
*
|
|
304
|
+
* @event {void} add — Add button clicked (backward compat, only if listener attached)
|
|
305
|
+
* @event {object} create — Form dialog create confirmed. Payload: formData object
|
|
306
|
+
* @event {object} edit — Form dialog edit confirmed. Payload: formData object (includes id)
|
|
307
|
+
* @event {string} delete — Single delete confirmed. Payload: item ID
|
|
308
|
+
* @event {{ id: string, newName: string }} copy — Single copy confirmed
|
|
309
|
+
* @event {string[]} mass-delete — Mass delete confirmed. Payload: array of IDs
|
|
310
|
+
* @event {object} mass-copy — Mass copy confirmed. Payload: { ids, pattern }
|
|
311
|
+
* @event {object} mass-export — Mass export confirmed. Payload: { ids, format }
|
|
312
|
+
* @event {object} mass-import — Mass import confirmed. Payload: import data
|
|
313
|
+
* @event {void} refresh — Refresh button clicked
|
|
314
|
+
* @event {object} row-click — Table row or card clicked. Payload: row object
|
|
315
|
+
* @event {{ key: string, order: string }} sort — Column sort changed
|
|
316
|
+
* @event {number} page-changed — Pagination page changed
|
|
317
|
+
* @event {number} page-size-changed — Pagination page size changed
|
|
318
|
+
* @event {string[]} select — Selection changed. Payload: array of selected IDs
|
|
319
|
+
* @event {object} action — Row action triggered. Payload: { action, row }
|
|
320
|
+
*
|
|
321
|
+
* @slot mass-actions — Extra mass action buttons (shown when items are selected)
|
|
322
|
+
* @slot action-items — Extra action bar buttons
|
|
323
|
+
* @slot header-actions — Extra buttons in the page header
|
|
324
|
+
* @slot delete-dialog — Replace the single-item delete dialog. Scope: `{ item, close }`
|
|
325
|
+
* @slot copy-dialog — Replace the single-item copy dialog. Scope: `{ item, close }`
|
|
326
|
+
* @slot form-dialog — Replace the create/edit form dialog. Scope: `{ item, schema, close }`
|
|
327
|
+
* @slot form-fields — Replace form content inside the built-in CnFormDialog. Scope: `{ fields, formData, errors, updateField }`
|
|
328
|
+
* @slot import-fields — Extra fields in the import dialog
|
|
329
|
+
* @slot empty — Custom empty state content
|
|
330
|
+
* @slot card — Custom card template for card view. Scope: `{ row }`
|
|
331
|
+
* @slot row-actions — Custom row actions. Scope: `{ row }`
|
|
332
|
+
* @slot column-{key} — Custom cell renderer for a specific column. Scope: `{ row, value }`
|
|
333
|
+
*/
|
|
334
|
+
export default {
|
|
335
|
+
name: 'CnIndexPage',
|
|
336
|
+
|
|
337
|
+
components: {
|
|
338
|
+
NcLoadingIcon,
|
|
339
|
+
NcEmptyContent,
|
|
340
|
+
DatabaseSearch,
|
|
341
|
+
CnPageHeader,
|
|
342
|
+
CnActionsBar,
|
|
343
|
+
CnIcon,
|
|
344
|
+
CnDataTable,
|
|
345
|
+
CnCardGrid,
|
|
346
|
+
CnPagination,
|
|
347
|
+
CnRowActions,
|
|
348
|
+
CnMassDeleteDialog,
|
|
349
|
+
CnMassCopyDialog,
|
|
350
|
+
CnMassExportDialog,
|
|
351
|
+
CnMassImportDialog,
|
|
352
|
+
CnDeleteDialog,
|
|
353
|
+
CnCopyDialog,
|
|
354
|
+
CnFormDialog,
|
|
355
|
+
CnAdvancedFormDialog,
|
|
356
|
+
},
|
|
357
|
+
|
|
358
|
+
props: {
|
|
359
|
+
/** Page title */
|
|
360
|
+
title: {
|
|
361
|
+
type: String,
|
|
362
|
+
required: true,
|
|
363
|
+
},
|
|
364
|
+
/** Optional description shown below the title */
|
|
365
|
+
description: {
|
|
366
|
+
type: String,
|
|
367
|
+
default: '',
|
|
368
|
+
},
|
|
369
|
+
/**
|
|
370
|
+
* Whether to show the page header (icon, title, description) inline.
|
|
371
|
+
* When false (default), the title is shown in the sidebar header instead.
|
|
372
|
+
*/
|
|
373
|
+
showTitle: {
|
|
374
|
+
type: Boolean,
|
|
375
|
+
default: false,
|
|
376
|
+
},
|
|
377
|
+
/** Optional MDI icon name. Defaults to schema.icon when a schema is provided. */
|
|
378
|
+
icon: {
|
|
379
|
+
type: String,
|
|
380
|
+
default: '',
|
|
381
|
+
},
|
|
382
|
+
/** Schema definition */
|
|
383
|
+
schema: {
|
|
384
|
+
type: Object,
|
|
385
|
+
default: null,
|
|
386
|
+
},
|
|
387
|
+
/** Manual column definitions (used instead of schema when provided) */
|
|
388
|
+
columns: {
|
|
389
|
+
type: Array,
|
|
390
|
+
default: () => [],
|
|
391
|
+
},
|
|
392
|
+
/** Object/row data array */
|
|
393
|
+
objects: {
|
|
394
|
+
type: Array,
|
|
395
|
+
default: () => [],
|
|
396
|
+
},
|
|
397
|
+
/** Pagination state: { page, pages, total, limit } */
|
|
398
|
+
pagination: {
|
|
399
|
+
type: Object,
|
|
400
|
+
default: null,
|
|
401
|
+
},
|
|
402
|
+
/** Whether data is loading */
|
|
403
|
+
loading: {
|
|
404
|
+
type: Boolean,
|
|
405
|
+
default: false,
|
|
406
|
+
},
|
|
407
|
+
/** Whether rows/cards can be selected */
|
|
408
|
+
selectable: {
|
|
409
|
+
type: Boolean,
|
|
410
|
+
default: true,
|
|
411
|
+
},
|
|
412
|
+
/** Currently selected IDs */
|
|
413
|
+
selectedIds: {
|
|
414
|
+
type: Array,
|
|
415
|
+
default: () => [],
|
|
416
|
+
},
|
|
417
|
+
/** View mode: 'table' or 'cards' */
|
|
418
|
+
viewMode: {
|
|
419
|
+
type: String,
|
|
420
|
+
default: 'table',
|
|
421
|
+
validator: (v) => ['table', 'cards'].includes(v),
|
|
422
|
+
},
|
|
423
|
+
/** Current sort key */
|
|
424
|
+
sortKey: {
|
|
425
|
+
type: String,
|
|
426
|
+
default: null,
|
|
427
|
+
},
|
|
428
|
+
/** Current sort order */
|
|
429
|
+
sortOrder: {
|
|
430
|
+
type: String,
|
|
431
|
+
default: 'asc',
|
|
432
|
+
},
|
|
433
|
+
/** Unique row identifier property */
|
|
434
|
+
rowKey: {
|
|
435
|
+
type: String,
|
|
436
|
+
default: 'id',
|
|
437
|
+
},
|
|
438
|
+
/** Columns to exclude in schema mode */
|
|
439
|
+
excludeColumns: {
|
|
440
|
+
type: Array,
|
|
441
|
+
default: () => [],
|
|
442
|
+
},
|
|
443
|
+
/** Columns to include in schema mode (whitelist) */
|
|
444
|
+
includeColumns: {
|
|
445
|
+
type: Array,
|
|
446
|
+
default: null,
|
|
447
|
+
},
|
|
448
|
+
/** Per-column overrides in schema mode */
|
|
449
|
+
columnOverrides: {
|
|
450
|
+
type: Object,
|
|
451
|
+
default: () => ({}),
|
|
452
|
+
},
|
|
453
|
+
/** Row action definitions (app-provided, merged with built-in actions) */
|
|
454
|
+
actions: {
|
|
455
|
+
type: Array,
|
|
456
|
+
default: () => [],
|
|
457
|
+
},
|
|
458
|
+
/** Text shown when no items found */
|
|
459
|
+
emptyText: {
|
|
460
|
+
type: String,
|
|
461
|
+
default: 'No items found',
|
|
462
|
+
},
|
|
463
|
+
/** Function returning CSS class(es) for a row */
|
|
464
|
+
rowClass: {
|
|
465
|
+
type: Function,
|
|
466
|
+
default: null,
|
|
467
|
+
},
|
|
468
|
+
/** Override label for the Add button. Defaults to "Add {schema.title}" */
|
|
469
|
+
addLabel: {
|
|
470
|
+
type: String,
|
|
471
|
+
default: '',
|
|
472
|
+
},
|
|
473
|
+
/** How many action buttons to show inline (rest go in overflow dropdown) */
|
|
474
|
+
inlineActionCount: {
|
|
475
|
+
type: Number,
|
|
476
|
+
default: 2,
|
|
477
|
+
},
|
|
478
|
+
/** Whether to show the built-in mass Import action */
|
|
479
|
+
showMassImport: {
|
|
480
|
+
type: Boolean,
|
|
481
|
+
default: true,
|
|
482
|
+
},
|
|
483
|
+
/** Whether to show the built-in mass Export action */
|
|
484
|
+
showMassExport: {
|
|
485
|
+
type: Boolean,
|
|
486
|
+
default: true,
|
|
487
|
+
},
|
|
488
|
+
/** Whether to show the built-in mass Copy button */
|
|
489
|
+
showMassCopy: {
|
|
490
|
+
type: Boolean,
|
|
491
|
+
default: true,
|
|
492
|
+
},
|
|
493
|
+
/** Whether to show the built-in mass Delete button */
|
|
494
|
+
showMassDelete: {
|
|
495
|
+
type: Boolean,
|
|
496
|
+
default: true,
|
|
497
|
+
},
|
|
498
|
+
/** Property name used to display item names in dialogs */
|
|
499
|
+
massActionNameField: {
|
|
500
|
+
type: String,
|
|
501
|
+
default: 'title',
|
|
502
|
+
},
|
|
503
|
+
/** Available export formats for the export dialog */
|
|
504
|
+
exportFormats: {
|
|
505
|
+
type: Array,
|
|
506
|
+
default: () => [
|
|
507
|
+
{ id: 'excel', label: 'Excel (.xlsx)' },
|
|
508
|
+
{ id: 'csv', label: 'CSV (.csv)' },
|
|
509
|
+
],
|
|
510
|
+
},
|
|
511
|
+
/** Import option definitions for the import dialog */
|
|
512
|
+
importOptions: {
|
|
513
|
+
type: Array,
|
|
514
|
+
default: () => [],
|
|
515
|
+
},
|
|
516
|
+
/** Whether to show the built-in form dialog for Add/Edit */
|
|
517
|
+
showFormDialog: {
|
|
518
|
+
type: Boolean,
|
|
519
|
+
default: true,
|
|
520
|
+
},
|
|
521
|
+
/** Use CnAdvancedFormDialog (properties table, JSON tab, optional metadata) instead of CnFormDialog for Add/Edit */
|
|
522
|
+
useAdvancedFormDialog: {
|
|
523
|
+
type: Boolean,
|
|
524
|
+
default: false,
|
|
525
|
+
},
|
|
526
|
+
/** Whether to add an Edit action to row actions */
|
|
527
|
+
showEditAction: {
|
|
528
|
+
type: Boolean,
|
|
529
|
+
default: true,
|
|
530
|
+
},
|
|
531
|
+
/** Whether to add a Copy action to row actions */
|
|
532
|
+
showCopyAction: {
|
|
533
|
+
type: Boolean,
|
|
534
|
+
default: true,
|
|
535
|
+
},
|
|
536
|
+
/** Whether to add a Delete action to row actions */
|
|
537
|
+
showDeleteAction: {
|
|
538
|
+
type: Boolean,
|
|
539
|
+
default: true,
|
|
540
|
+
},
|
|
541
|
+
/** Field keys to exclude from the form dialog */
|
|
542
|
+
excludeFields: {
|
|
543
|
+
type: Array,
|
|
544
|
+
default: () => [],
|
|
545
|
+
},
|
|
546
|
+
/** Field keys to include in the form dialog (whitelist mode) */
|
|
547
|
+
includeFields: {
|
|
548
|
+
type: Array,
|
|
549
|
+
default: null,
|
|
550
|
+
},
|
|
551
|
+
/** Per-field overrides passed to CnFormDialog */
|
|
552
|
+
fieldOverrides: {
|
|
553
|
+
type: Object,
|
|
554
|
+
default: () => ({}),
|
|
555
|
+
},
|
|
556
|
+
/** Whether to show the Cards/Table view toggle in the actions bar */
|
|
557
|
+
showViewToggle: {
|
|
558
|
+
type: Boolean,
|
|
559
|
+
default: true,
|
|
560
|
+
},
|
|
561
|
+
/** Whether the refresh action is currently in progress */
|
|
562
|
+
refreshing: {
|
|
563
|
+
type: Boolean,
|
|
564
|
+
default: false,
|
|
565
|
+
},
|
|
566
|
+
/**
|
|
567
|
+
* Store instance for automatic save integration. When provided alongside
|
|
568
|
+
* objectType, the form dialog saves directly to the store instead of
|
|
569
|
+
* emitting create/edit events. The object type must already be registered
|
|
570
|
+
* in the store via registerObjectType() before passing the store here.
|
|
571
|
+
*/
|
|
572
|
+
store: { type: Object, default: null },
|
|
573
|
+
/**
|
|
574
|
+
* Object type slug for store integration (e.g. `${registerId}-${schemaId}`).
|
|
575
|
+
* Required when store is set — a console warning is emitted if missing.
|
|
576
|
+
*/
|
|
577
|
+
objectType: { type: String, default: '' },
|
|
578
|
+
},
|
|
579
|
+
|
|
580
|
+
data() {
|
|
581
|
+
return {
|
|
582
|
+
currentViewMode: this.viewMode,
|
|
583
|
+
internalSelectedIds: [...this.selectedIds],
|
|
584
|
+
// Mass action dialogs
|
|
585
|
+
showMassDeleteDialog: false,
|
|
586
|
+
showMassCopyDialog: false,
|
|
587
|
+
showExportDialog: false,
|
|
588
|
+
showImportDialog: false,
|
|
589
|
+
// Single-object dialogs
|
|
590
|
+
showSingleDeleteDialog: false,
|
|
591
|
+
showSingleCopyDialog: false,
|
|
592
|
+
showFormDialogVisible: false,
|
|
593
|
+
// Dialog targets
|
|
594
|
+
actionTargetItem: null,
|
|
595
|
+
editItem: null,
|
|
596
|
+
}
|
|
597
|
+
},
|
|
598
|
+
|
|
599
|
+
computed: {
|
|
600
|
+
/** Resolved icon — explicit prop overrides schema.icon */
|
|
601
|
+
resolvedIcon() {
|
|
602
|
+
if (this.icon) return this.icon
|
|
603
|
+
return this.schema?.icon || ''
|
|
604
|
+
},
|
|
605
|
+
|
|
606
|
+
/** Resolved schema icon component for View action */
|
|
607
|
+
schemaIconComponent() {
|
|
608
|
+
if (this.resolvedIcon && ICON_MAP[this.resolvedIcon]) {
|
|
609
|
+
return ICON_MAP[this.resolvedIcon]
|
|
610
|
+
}
|
|
611
|
+
return Eye
|
|
612
|
+
},
|
|
613
|
+
|
|
614
|
+
/** Built-in row actions based on show*Action props */
|
|
615
|
+
defaultActions() {
|
|
616
|
+
const builtIn = []
|
|
617
|
+
if (this.$listeners && this.$listeners['row-click']) {
|
|
618
|
+
builtIn.push({
|
|
619
|
+
label: 'View',
|
|
620
|
+
icon: this.schemaIconComponent,
|
|
621
|
+
handler: (row) => {
|
|
622
|
+
this.$emit('row-click', row)
|
|
623
|
+
},
|
|
624
|
+
})
|
|
625
|
+
}
|
|
626
|
+
if (this.showEditAction) {
|
|
627
|
+
builtIn.push({
|
|
628
|
+
label: 'Edit',
|
|
629
|
+
icon: Pencil,
|
|
630
|
+
handler: (row) => {
|
|
631
|
+
this.editItem = row
|
|
632
|
+
this.showFormDialogVisible = true
|
|
633
|
+
},
|
|
634
|
+
})
|
|
635
|
+
}
|
|
636
|
+
if (this.showCopyAction) {
|
|
637
|
+
builtIn.push({
|
|
638
|
+
label: 'Copy',
|
|
639
|
+
icon: ContentCopy,
|
|
640
|
+
handler: (row) => {
|
|
641
|
+
this.actionTargetItem = row
|
|
642
|
+
this.showSingleCopyDialog = true
|
|
643
|
+
},
|
|
644
|
+
})
|
|
645
|
+
}
|
|
646
|
+
if (this.showDeleteAction) {
|
|
647
|
+
builtIn.push({
|
|
648
|
+
label: 'Delete',
|
|
649
|
+
icon: TrashCanOutline,
|
|
650
|
+
destructive: true,
|
|
651
|
+
handler: (row) => {
|
|
652
|
+
this.actionTargetItem = row
|
|
653
|
+
this.showSingleDeleteDialog = true
|
|
654
|
+
},
|
|
655
|
+
})
|
|
656
|
+
}
|
|
657
|
+
return builtIn
|
|
658
|
+
},
|
|
659
|
+
|
|
660
|
+
/** Merged actions: app-provided first, then built-in defaults */
|
|
661
|
+
mergedActions() {
|
|
662
|
+
return [...this.actions, ...this.defaultActions]
|
|
663
|
+
},
|
|
664
|
+
|
|
665
|
+
hasRowActions() {
|
|
666
|
+
return this.$scopedSlots['row-actions'] || this.mergedActions.length > 0
|
|
667
|
+
},
|
|
668
|
+
|
|
669
|
+
/** Whether all visible items are selected */
|
|
670
|
+
allSelected() {
|
|
671
|
+
if (this.objects.length === 0 || this.internalSelectedIds.length === 0) return false
|
|
672
|
+
return this.objects.every((o) => this.internalSelectedIds.includes(o[this.rowKey]))
|
|
673
|
+
},
|
|
674
|
+
|
|
675
|
+
/** Full objects for the selected IDs (used by mass action dialogs) */
|
|
676
|
+
selectedObjects() {
|
|
677
|
+
return this.objects.filter((o) => this.internalSelectedIds.includes(o[this.rowKey]))
|
|
678
|
+
},
|
|
679
|
+
|
|
680
|
+
/** Column slot names that the parent has provided (for pass-through) */
|
|
681
|
+
slotColumns() {
|
|
682
|
+
return Object.keys(this.$scopedSlots)
|
|
683
|
+
.filter((name) => name.startsWith('column-'))
|
|
684
|
+
.map((name) => name.replace('column-', ''))
|
|
685
|
+
},
|
|
686
|
+
|
|
687
|
+
/** Add button label — derived from schema.title if not explicitly set */
|
|
688
|
+
resolvedAddLabel() {
|
|
689
|
+
if (this.addLabel) return this.addLabel
|
|
690
|
+
return 'Add ' + (this.schema?.title || 'Item')
|
|
691
|
+
},
|
|
692
|
+
},
|
|
693
|
+
|
|
694
|
+
watch: {
|
|
695
|
+
viewMode(val) {
|
|
696
|
+
this.currentViewMode = val
|
|
697
|
+
},
|
|
698
|
+
selectedIds(val) {
|
|
699
|
+
this.internalSelectedIds = [...val]
|
|
700
|
+
},
|
|
701
|
+
},
|
|
702
|
+
|
|
703
|
+
methods: {
|
|
704
|
+
/**
|
|
705
|
+
* Handle the Add button click. If the consumer listens to @add,
|
|
706
|
+
* emit the event (backward compatible). Otherwise open the form dialog.
|
|
707
|
+
*/
|
|
708
|
+
onAddClick() {
|
|
709
|
+
if (this.$listeners && this.$listeners.add) {
|
|
710
|
+
this.$emit('add')
|
|
711
|
+
} else if (this.showFormDialog) {
|
|
712
|
+
this.editItem = null
|
|
713
|
+
this.showFormDialogVisible = true
|
|
714
|
+
}
|
|
715
|
+
},
|
|
716
|
+
|
|
717
|
+
/**
|
|
718
|
+
* Handle view mode toggle.
|
|
719
|
+
* @param {string} mode 'table' or 'cards'
|
|
720
|
+
*/
|
|
721
|
+
onViewModeChange(mode) {
|
|
722
|
+
this.currentViewMode = mode
|
|
723
|
+
this.$emit('view-mode-change', mode)
|
|
724
|
+
},
|
|
725
|
+
|
|
726
|
+
/**
|
|
727
|
+
* Handle selection changes from CnDataTable/CnCardGrid.
|
|
728
|
+
* Updates internal state and re-emits for parent.
|
|
729
|
+
* @param {Array} ids Array of selected row IDs
|
|
730
|
+
*/
|
|
731
|
+
onSelect(ids) {
|
|
732
|
+
this.internalSelectedIds = ids
|
|
733
|
+
this.$emit('select', ids)
|
|
734
|
+
},
|
|
735
|
+
|
|
736
|
+
// --- Mass action handlers ---
|
|
737
|
+
|
|
738
|
+
onMassDeleteConfirm(ids) {
|
|
739
|
+
this.$emit('mass-delete', ids)
|
|
740
|
+
},
|
|
741
|
+
|
|
742
|
+
onMassCopyConfirm(payload) {
|
|
743
|
+
this.$emit('mass-copy', payload)
|
|
744
|
+
},
|
|
745
|
+
|
|
746
|
+
onMassExportConfirm(payload) {
|
|
747
|
+
this.$emit('mass-export', payload)
|
|
748
|
+
},
|
|
749
|
+
|
|
750
|
+
onMassImportConfirm(payload) {
|
|
751
|
+
this.$emit('mass-import', payload)
|
|
752
|
+
},
|
|
753
|
+
|
|
754
|
+
/** @public Forward result to mass delete dialog */
|
|
755
|
+
setMassDeleteResult(resultData) {
|
|
756
|
+
if (this.$refs.massDeleteDialog) {
|
|
757
|
+
this.$refs.massDeleteDialog.setResult(resultData)
|
|
758
|
+
}
|
|
759
|
+
},
|
|
760
|
+
|
|
761
|
+
/** @public Forward result to mass copy dialog */
|
|
762
|
+
setMassCopyResult(resultData) {
|
|
763
|
+
if (this.$refs.massCopyDialog) {
|
|
764
|
+
this.$refs.massCopyDialog.setResult(resultData)
|
|
765
|
+
}
|
|
766
|
+
},
|
|
767
|
+
|
|
768
|
+
/** @public Forward result to export dialog */
|
|
769
|
+
setExportResult(resultData) {
|
|
770
|
+
if (this.$refs.exportDialog) {
|
|
771
|
+
this.$refs.exportDialog.setResult(resultData)
|
|
772
|
+
}
|
|
773
|
+
},
|
|
774
|
+
|
|
775
|
+
/** @public Forward result to import dialog */
|
|
776
|
+
setImportResult(resultData) {
|
|
777
|
+
if (this.$refs.importDialog) {
|
|
778
|
+
this.$refs.importDialog.setResult(resultData)
|
|
779
|
+
}
|
|
780
|
+
},
|
|
781
|
+
|
|
782
|
+
// --- Backward-compatible aliases ---
|
|
783
|
+
/** @public @deprecated Use setMassDeleteResult instead */
|
|
784
|
+
setDeleteResult(resultData) {
|
|
785
|
+
this.setMassDeleteResult(resultData)
|
|
786
|
+
},
|
|
787
|
+
/** @public @deprecated Use setMassCopyResult instead */
|
|
788
|
+
setCopyResult(resultData) {
|
|
789
|
+
this.setMassCopyResult(resultData)
|
|
790
|
+
},
|
|
791
|
+
|
|
792
|
+
// --- Single-object dialog handlers ---
|
|
793
|
+
|
|
794
|
+
onSingleDeleteConfirm(id) {
|
|
795
|
+
this.$emit('delete', id)
|
|
796
|
+
},
|
|
797
|
+
|
|
798
|
+
onSingleCopyConfirm(payload) {
|
|
799
|
+
this.$emit('copy', payload)
|
|
800
|
+
},
|
|
801
|
+
|
|
802
|
+
async onFormConfirm(formData) {
|
|
803
|
+
if (this.store) {
|
|
804
|
+
if (!this.objectType) {
|
|
805
|
+
console.warn('[CnIndexPage] store prop is set but objectType is missing. Cannot save to store.')
|
|
806
|
+
return
|
|
807
|
+
}
|
|
808
|
+
const saved = await this.store.saveObject(this.objectType, formData)
|
|
809
|
+
if (saved) {
|
|
810
|
+
this.setFormResult({ success: true })
|
|
811
|
+
this.$emit(this.editItem ? 'edit' : 'create', saved)
|
|
812
|
+
} else {
|
|
813
|
+
const err = this.store.getError?.(this.objectType)
|
|
814
|
+
this.setFormResult({ error: (err && err.message) || 'Save failed' })
|
|
815
|
+
}
|
|
816
|
+
return
|
|
817
|
+
}
|
|
818
|
+
if (this.editItem) {
|
|
819
|
+
this.$emit('edit', formData)
|
|
820
|
+
} else {
|
|
821
|
+
this.$emit('create', formData)
|
|
822
|
+
}
|
|
823
|
+
},
|
|
824
|
+
|
|
825
|
+
closeSingleDelete() {
|
|
826
|
+
this.showSingleDeleteDialog = false
|
|
827
|
+
this.actionTargetItem = null
|
|
828
|
+
},
|
|
829
|
+
|
|
830
|
+
closeSingleCopy() {
|
|
831
|
+
this.showSingleCopyDialog = false
|
|
832
|
+
this.actionTargetItem = null
|
|
833
|
+
},
|
|
834
|
+
|
|
835
|
+
closeFormDialog() {
|
|
836
|
+
this.showFormDialogVisible = false
|
|
837
|
+
this.editItem = null
|
|
838
|
+
},
|
|
839
|
+
|
|
840
|
+
/** @public Forward result to single delete dialog */
|
|
841
|
+
setSingleDeleteResult(resultData) {
|
|
842
|
+
if (this.$refs.singleDeleteDialog) {
|
|
843
|
+
this.$refs.singleDeleteDialog.setResult(resultData)
|
|
844
|
+
}
|
|
845
|
+
},
|
|
846
|
+
|
|
847
|
+
/** @public Forward result to single copy dialog */
|
|
848
|
+
setSingleCopyResult(resultData) {
|
|
849
|
+
if (this.$refs.singleCopyDialog) {
|
|
850
|
+
this.$refs.singleCopyDialog.setResult(resultData)
|
|
851
|
+
}
|
|
852
|
+
},
|
|
853
|
+
|
|
854
|
+
/** @public Forward result to form dialog */
|
|
855
|
+
setFormResult(resultData) {
|
|
856
|
+
if (this.$refs.formDialog) {
|
|
857
|
+
this.$refs.formDialog.setResult(resultData)
|
|
858
|
+
}
|
|
859
|
+
},
|
|
860
|
+
|
|
861
|
+
/**
|
|
862
|
+
* Programmatically open the form dialog.
|
|
863
|
+
* @param {object|null} item Pass null for create mode, or an object for edit mode
|
|
864
|
+
* @public
|
|
865
|
+
*/
|
|
866
|
+
openFormDialog(item = null) {
|
|
867
|
+
this.editItem = item
|
|
868
|
+
this.showFormDialogVisible = true
|
|
869
|
+
},
|
|
870
|
+
},
|
|
871
|
+
}
|
|
872
|
+
</script>
|
|
873
|
+
|
|
874
|
+
<!-- Styles in css/index-page.css -->
|