@conduction/nextcloud-vue 0.1.0-beta.1 → 0.1.0-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (197) hide show
  1. package/README.md +226 -0
  2. package/css/index.css +5 -0
  3. package/dist/nextcloud-vue.cjs +67614 -0
  4. package/dist/nextcloud-vue.cjs.js +76311 -5905
  5. package/dist/nextcloud-vue.cjs.js.map +1 -1
  6. package/dist/nextcloud-vue.cjs.map +1 -0
  7. package/dist/nextcloud-vue.css +3279 -203
  8. package/dist/nextcloud-vue.esm.js +76240 -5882
  9. package/dist/nextcloud-vue.esm.js.map +1 -1
  10. package/package.json +89 -63
  11. package/src/components/CnActionsBar/CnActionsBar.vue +254 -0
  12. package/src/components/CnActionsBar/index.js +1 -0
  13. package/src/components/CnAdvancedFormDialog/CnAdvancedFormDialog.vue +569 -0
  14. package/src/components/CnAdvancedFormDialog/CnDataTab.vue +217 -0
  15. package/src/components/CnAdvancedFormDialog/CnMetadataTab.vue +121 -0
  16. package/src/components/CnAdvancedFormDialog/CnPropertiesTab.vue +422 -0
  17. package/src/components/CnAdvancedFormDialog/CnPropertyValueCell.vue +247 -0
  18. package/src/components/CnAdvancedFormDialog/index.js +1 -0
  19. package/src/components/CnCard/CnCard.vue +415 -0
  20. package/src/components/CnCard/index.js +1 -0
  21. package/src/components/CnCardGrid/CnCardGrid.vue +23 -20
  22. package/src/components/CnCardGrid/index.js +1 -1
  23. package/src/components/CnCellRenderer/index.js +1 -1
  24. package/src/components/CnChartWidget/CnChartWidget.vue +318 -0
  25. package/src/components/CnChartWidget/index.js +1 -0
  26. package/src/components/CnConfigurationCard/index.js +1 -1
  27. package/src/components/CnContextMenu/CnContextMenu.vue +142 -0
  28. package/src/components/CnContextMenu/index.js +1 -0
  29. package/src/components/CnCopyDialog/CnCopyDialog.vue +257 -0
  30. package/src/components/CnCopyDialog/index.js +1 -0
  31. package/src/components/CnDashboardGrid/CnDashboardGrid.vue +229 -0
  32. package/src/components/CnDashboardGrid/index.js +1 -0
  33. package/src/components/CnDashboardPage/CnDashboardPage.vue +396 -0
  34. package/src/components/CnDashboardPage/index.js +1 -0
  35. package/src/components/CnDataTable/CnDataTable.vue +24 -16
  36. package/src/components/CnDataTable/index.js +1 -1
  37. package/src/components/CnDeleteDialog/CnDeleteDialog.vue +177 -0
  38. package/src/components/CnDeleteDialog/index.js +1 -0
  39. package/src/components/CnDetailCard/CnDetailCard.vue +225 -0
  40. package/src/components/CnDetailCard/index.js +1 -0
  41. package/src/components/CnDetailGrid/CnDetailGrid.vue +254 -0
  42. package/src/components/CnDetailGrid/index.js +1 -0
  43. package/src/components/CnDetailPage/CnDetailPage.vue +431 -0
  44. package/src/components/CnDetailPage/index.js +1 -0
  45. package/src/components/CnFacetSidebar/CnFacetSidebar.vue +12 -2
  46. package/src/components/CnFacetSidebar/index.js +1 -1
  47. package/src/components/CnFilterBar/index.js +1 -1
  48. package/src/components/CnFormDialog/CnFormDialog.vue +934 -0
  49. package/src/components/CnFormDialog/index.js +1 -0
  50. package/src/components/CnIcon/CnIcon.vue +89 -0
  51. package/src/components/CnIcon/index.js +1 -0
  52. package/src/components/CnIndexPage/CnIndexPage.vue +589 -291
  53. package/src/components/CnIndexPage/index.js +1 -1
  54. package/src/components/CnIndexSidebar/CnIndexSidebar.vue +535 -0
  55. package/src/components/CnIndexSidebar/index.js +1 -0
  56. package/src/components/CnInfoWidget/CnInfoWidget.vue +219 -0
  57. package/src/components/CnInfoWidget/index.js +1 -0
  58. package/src/components/CnItemCard/CnItemCard.vue +134 -0
  59. package/src/components/CnItemCard/index.js +1 -0
  60. package/src/components/CnJsonViewer/CnJsonViewer.vue +283 -0
  61. package/src/components/CnJsonViewer/index.js +1 -0
  62. package/src/components/CnKpiGrid/CnKpiGrid.vue +5 -1
  63. package/src/components/CnKpiGrid/index.js +1 -1
  64. package/src/components/CnMassActionBar/CnMassActionBar.vue +6 -5
  65. package/src/components/CnMassActionBar/index.js +1 -1
  66. package/src/components/CnMassCopyDialog/CnMassCopyDialog.vue +16 -9
  67. package/src/components/CnMassCopyDialog/index.js +1 -1
  68. package/src/components/CnMassDeleteDialog/CnMassDeleteDialog.vue +16 -9
  69. package/src/components/CnMassDeleteDialog/index.js +1 -1
  70. package/src/components/CnMassExportDialog/CnMassExportDialog.vue +8 -7
  71. package/src/components/CnMassExportDialog/index.js +1 -1
  72. package/src/components/CnMassImportDialog/CnMassImportDialog.vue +20 -17
  73. package/src/components/CnMassImportDialog/index.js +1 -1
  74. package/src/components/CnNoteCard/CnNoteCard.vue +149 -0
  75. package/src/components/CnNoteCard/index.js +1 -0
  76. package/src/components/CnNotesCard/CnNotesCard.vue +415 -0
  77. package/src/components/CnNotesCard/index.js +1 -0
  78. package/src/components/CnObjectCard/CnObjectCard.vue +3 -1
  79. package/src/components/CnObjectCard/index.js +1 -1
  80. package/src/components/CnObjectDataWidget/CnObjectDataWidget.vue +853 -0
  81. package/src/components/CnObjectDataWidget/index.js +1 -0
  82. package/src/components/CnObjectMetadataWidget/CnObjectMetadataWidget.vue +288 -0
  83. package/src/components/CnObjectMetadataWidget/index.js +1 -0
  84. package/src/components/CnObjectSidebar/CnAuditTrailTab.vue +368 -0
  85. package/src/components/CnObjectSidebar/CnFilesTab.vue +286 -0
  86. package/src/components/CnObjectSidebar/CnNotesTab.vue +249 -0
  87. package/src/components/CnObjectSidebar/CnObjectSidebar.vue +254 -0
  88. package/src/components/CnObjectSidebar/CnTagsTab.vue +258 -0
  89. package/src/components/CnObjectSidebar/CnTasksTab.vue +482 -0
  90. package/src/components/CnObjectSidebar/index.js +6 -0
  91. package/src/components/CnPageHeader/CnPageHeader.vue +61 -0
  92. package/src/components/CnPageHeader/index.js +1 -0
  93. package/src/components/CnPagination/CnPagination.vue +7 -6
  94. package/src/components/CnPagination/index.js +1 -1
  95. package/src/components/CnProgressBar/CnProgressBar.vue +262 -0
  96. package/src/components/CnProgressBar/index.js +1 -0
  97. package/src/components/CnRegisterMapping/CnRegisterMapping.vue +792 -0
  98. package/src/components/CnRegisterMapping/index.js +1 -0
  99. package/src/components/CnRowActions/CnRowActions.vue +25 -3
  100. package/src/components/CnRowActions/index.js +1 -1
  101. package/src/components/CnSchemaFormDialog/CnSchemaConfigurationTab.vue +226 -0
  102. package/src/components/CnSchemaFormDialog/CnSchemaFormDialog.vue +787 -0
  103. package/src/components/CnSchemaFormDialog/CnSchemaPropertiesTab.vue +305 -0
  104. package/src/components/CnSchemaFormDialog/CnSchemaPropertyActions.vue +1398 -0
  105. package/src/components/CnSchemaFormDialog/CnSchemaSecurityTab.vue +236 -0
  106. package/src/components/CnSchemaFormDialog/index.js +1 -0
  107. package/src/components/CnSettingsCard/index.js +1 -1
  108. package/src/components/CnSettingsSection/index.js +1 -1
  109. package/src/components/CnStatsBlock/CnStatsBlock.vue +89 -19
  110. package/src/components/CnStatsBlock/index.js +1 -1
  111. package/src/components/CnStatsPanel/CnStatsPanel.vue +320 -0
  112. package/src/components/CnStatsPanel/index.js +1 -0
  113. package/src/components/CnStatusBadge/CnStatusBadge.vue +15 -2
  114. package/src/components/CnStatusBadge/index.js +1 -1
  115. package/src/components/CnTabbedFormDialog/CnTabbedFormDialog.vue +544 -0
  116. package/src/components/CnTabbedFormDialog/index.js +1 -0
  117. package/src/components/CnTableWidget/CnTableWidget.vue +332 -0
  118. package/src/components/CnTableWidget/index.js +1 -0
  119. package/src/components/CnTasksCard/CnTasksCard.vue +373 -0
  120. package/src/components/CnTasksCard/index.js +1 -0
  121. package/src/components/CnTileWidget/CnTileWidget.vue +159 -0
  122. package/src/components/CnTileWidget/index.js +1 -0
  123. package/src/components/CnTimelineStages/CnTimelineStages.vue +292 -0
  124. package/src/components/CnTimelineStages/index.js +1 -0
  125. package/src/components/CnUserActionMenu/CnUserActionMenu.vue +435 -0
  126. package/src/components/CnUserActionMenu/index.js +1 -0
  127. package/src/components/CnVersionInfoCard/index.js +1 -1
  128. package/src/components/CnWidgetRenderer/CnWidgetRenderer.vue +180 -0
  129. package/src/components/CnWidgetRenderer/index.js +1 -0
  130. package/src/components/CnWidgetWrapper/CnWidgetWrapper.vue +246 -0
  131. package/src/components/CnWidgetWrapper/index.js +1 -0
  132. package/src/components/index.js +57 -25
  133. package/src/composables/index.js +5 -3
  134. package/src/composables/useContextMenu.js +126 -0
  135. package/src/composables/useDashboardView.js +286 -0
  136. package/src/composables/useDetailView.js +290 -132
  137. package/src/composables/useListView.js +364 -153
  138. package/src/composables/useSubResource.js +142 -142
  139. package/src/constants/metadata.js +30 -0
  140. package/src/css/CnSchemaFormDialog.css +546 -0
  141. package/src/css/__sample_nextcloud_tokens.css +110 -0
  142. package/src/css/actions-bar.css +54 -0
  143. package/src/css/badge.css +83 -51
  144. package/src/css/card.css +129 -128
  145. package/src/css/context-menu.css +20 -0
  146. package/src/css/dashboard.css +70 -0
  147. package/src/css/detail-page.css +235 -0
  148. package/src/css/detail.css +68 -68
  149. package/src/css/index-page.css +44 -0
  150. package/src/css/index-sidebar.css +193 -0
  151. package/src/css/index.css +17 -8
  152. package/src/css/layout.css +90 -90
  153. package/src/css/page-header.css +35 -0
  154. package/src/css/pagination.css +72 -72
  155. package/src/css/table.css +142 -143
  156. package/src/css/timeline-stages.css +220 -0
  157. package/src/css/utilities.css +46 -46
  158. package/src/index.js +91 -50
  159. package/src/mixins/gridLayout.js +118 -0
  160. package/src/store/createCrudStore.js +360 -0
  161. package/src/store/createSubResourcePlugin.js +125 -135
  162. package/src/store/index.js +4 -3
  163. package/src/store/plugins/auditTrails.js +357 -17
  164. package/src/store/plugins/files.js +250 -186
  165. package/src/store/plugins/index.js +7 -4
  166. package/src/store/plugins/lifecycle.js +180 -180
  167. package/src/store/plugins/registerMapping.js +195 -0
  168. package/src/store/plugins/relations.js +68 -68
  169. package/src/store/plugins/search.js +385 -0
  170. package/src/store/plugins/selection.js +104 -0
  171. package/src/store/useObjectStore.js +823 -625
  172. package/src/types/auditTrail.d.ts +32 -32
  173. package/src/types/file.d.ts +23 -23
  174. package/src/types/index.d.ts +35 -35
  175. package/src/types/notification.d.ts +36 -36
  176. package/src/types/object.d.ts +40 -40
  177. package/src/types/organisation.d.ts +41 -41
  178. package/src/types/register.d.ts +25 -25
  179. package/src/types/schema.d.ts +39 -39
  180. package/src/types/shared.d.ts +79 -79
  181. package/src/types/source.d.ts +14 -14
  182. package/src/types/task.d.ts +31 -31
  183. package/src/utils/errors.js +96 -96
  184. package/src/utils/getTheme.js +9 -0
  185. package/src/utils/headers.js +80 -44
  186. package/src/utils/id.js +13 -0
  187. package/src/utils/index.js +4 -3
  188. package/src/utils/schema.js +422 -287
  189. package/src/utils/widgetVisibility.js +162 -0
  190. package/src/components/CnDetailViewLayout/CnDetailViewLayout.vue +0 -88
  191. package/src/components/CnDetailViewLayout/index.js +0 -1
  192. package/src/components/CnEmptyState/CnEmptyState.vue +0 -78
  193. package/src/components/CnEmptyState/index.js +0 -1
  194. package/src/components/CnListViewLayout/CnListViewLayout.vue +0 -80
  195. package/src/components/CnListViewLayout/index.js +0 -1
  196. package/src/components/CnViewModeToggle/CnViewModeToggle.vue +0 -77
  197. package/src/components/CnViewModeToggle/index.js +0 -1
@@ -0,0 +1,544 @@
1
+ <template>
2
+ <NcDialog
3
+ :name="resolvedTitle"
4
+ :size="size"
5
+ :can-close="!loading"
6
+ @closing="$emit('close')">
7
+ <!-- Result phase (standard mode, not create-another) -->
8
+ <div v-if="result !== null && !createAnother" class="cn-tabbed-form-dialog__result">
9
+ <NcNoteCard v-if="result.success" type="success">
10
+ {{ resolvedSuccessText }}
11
+ </NcNoteCard>
12
+ <NcNoteCard v-if="result.error" type="error">
13
+ {{ result.error }}
14
+ </NcNoteCard>
15
+ </div>
16
+
17
+ <!-- Form phase (or create-another mode where form stays visible) -->
18
+ <div v-if="createAnother || result === null" class="cn-tabbed-form-dialog__form">
19
+ <!-- Inline notifications for create-another mode -->
20
+ <NcNoteCard v-if="createAnother && result && result.success" type="success">
21
+ {{ resolvedSuccessText }}
22
+ </NcNoteCard>
23
+ <NcNoteCard v-if="result && result.error" type="error">
24
+ {{ result.error }}
25
+ </NcNoteCard>
26
+
27
+ <!-- Optional content above tabs (e.g. metadata grid, detail cards) -->
28
+ <slot name="above-tabs" :loading="loading" />
29
+
30
+ <!-- Tabs -->
31
+ <div class="cn-tabbed-form-dialog__tabs tabContainer">
32
+ <BTabs
33
+ v-model="activeTab"
34
+ content-class="mt-3"
35
+ justified
36
+ @input="$emit('update:activeTab', $event)">
37
+ <BTab
38
+ v-for="tab in tabs"
39
+ :key="tab.id"
40
+ :disabled="tab.disabled">
41
+ <template #title>
42
+ <component :is="tab.icon" v-if="tab.icon" :size="16" />
43
+ <span>{{ tab.title }}</span>
44
+ </template>
45
+ <div class="cn-tabbed-form-dialog__tab-content form-editor">
46
+ <slot :name="'tab-' + tab.id" :loading="loading" />
47
+ </div>
48
+ </BTab>
49
+ </BTabs>
50
+ </div>
51
+
52
+ <!-- Optional content below tabs (e.g. shared settings across all tabs) -->
53
+ <slot name="below-tabs" :loading="loading" />
54
+ </div>
55
+
56
+ <template #actions>
57
+ <!-- Create another checkbox (only in create mode) -->
58
+ <NcCheckboxRadioSwitch
59
+ v-if="showCreateAnother && isCreateMode"
60
+ class="cn-tabbed-form-dialog__create-another"
61
+ :disabled="loading"
62
+ :checked.sync="createAnother">
63
+ {{ createAnotherLabel }}
64
+ </NcCheckboxRadioSwitch>
65
+
66
+ <!-- Extra actions before Cancel -->
67
+ <slot name="actions-left"
68
+ :loading="loading"
69
+ :is-create-mode="isCreateMode"
70
+ :result="result" />
71
+
72
+ <!-- Cancel / Close button -->
73
+ <NcButton @click="handleClose">
74
+ <template #icon>
75
+ <Cancel :size="20" />
76
+ </template>
77
+ {{ result !== null && !createAnother ? closeLabel : cancelLabel }}
78
+ </NcButton>
79
+
80
+ <!-- Extra actions after primary -->
81
+ <slot name="actions-right"
82
+ :loading="loading"
83
+ :is-create-mode="isCreateMode"
84
+ :result="result" />
85
+
86
+ <!-- Primary action button (Save / Create) -->
87
+ <NcButton
88
+ v-if="createAnother || result === null"
89
+ type="primary"
90
+ :disabled="loading || disableSave"
91
+ @click="executeConfirm">
92
+ <template #icon>
93
+ <NcLoadingIcon v-if="loading" :size="20" />
94
+ <slot v-else-if="$slots['confirm-icon']" name="confirm-icon" />
95
+ <Plus v-else-if="isCreateMode" :size="20" />
96
+ <ContentSaveOutline v-else :size="20" />
97
+ </template>
98
+ {{ resolvedConfirmLabel }}
99
+ </NcButton>
100
+ </template>
101
+ </NcDialog>
102
+ </template>
103
+
104
+ <script>
105
+ import {
106
+ NcButton,
107
+ NcDialog,
108
+ NcLoadingIcon,
109
+ NcNoteCard,
110
+ NcCheckboxRadioSwitch,
111
+ } from '@nextcloud/vue'
112
+ import { BTabs, BTab } from 'bootstrap-vue'
113
+
114
+ import Cancel from 'vue-material-design-icons/Cancel.vue'
115
+ import ContentSaveOutline from 'vue-material-design-icons/ContentSaveOutline.vue'
116
+ import Plus from 'vue-material-design-icons/Plus.vue'
117
+
118
+ export default {
119
+ name: 'CnTabbedFormDialog',
120
+ components: {
121
+ NcDialog,
122
+ NcButton,
123
+ NcLoadingIcon,
124
+ NcNoteCard,
125
+ NcCheckboxRadioSwitch,
126
+ BTabs,
127
+ BTab,
128
+ Cancel,
129
+ ContentSaveOutline,
130
+ Plus,
131
+ },
132
+ props: {
133
+ /**
134
+ * Array of tab definitions. Each tab must have at least an `id` and `title`.
135
+ * The optional `icon` field should be a Vue component reference (e.g. an imported MDI icon).
136
+ * The optional `disabled` field prevents tab selection.
137
+ *
138
+ * @type {Array<{ id: string, title: string, icon?: object, disabled?: boolean }>}
139
+ */
140
+ tabs: {
141
+ type: Array,
142
+ required: true,
143
+ validator: (tabs) => tabs.length > 0 && tabs.every(t => t.id && t.title),
144
+ },
145
+ /**
146
+ * Existing item for edit mode. Pass null or undefined for create mode.
147
+ * The component only checks for truthiness to determine create vs edit mode.
148
+ *
149
+ * @type {object|null}
150
+ */
151
+ item: {
152
+ type: Object,
153
+ default: null,
154
+ },
155
+ /**
156
+ * Custom dialog title. When provided, overrides the auto-generated
157
+ * "Create {entityName}" / "Edit {entityName}" title.
158
+ *
159
+ * @type {string}
160
+ */
161
+ dialogTitle: {
162
+ type: String,
163
+ default: '',
164
+ },
165
+ /**
166
+ * Entity name used in auto-generated titles and success messages.
167
+ * For example, "Organisation" produces "Create Organisation" and
168
+ * "Organisation saved successfully".
169
+ *
170
+ * @type {string}
171
+ */
172
+ entityName: {
173
+ type: String,
174
+ default: 'Item',
175
+ },
176
+ /**
177
+ * NcDialog size. One of 'small', 'normal', 'large', 'full'.
178
+ *
179
+ * @type {string}
180
+ */
181
+ size: {
182
+ type: String,
183
+ default: 'large',
184
+ },
185
+ /**
186
+ * Whether to show the "Create Another" checkbox in create mode.
187
+ * When checked and a save succeeds, the form stays open and a reset
188
+ * event is emitted so the parent can clear form data.
189
+ *
190
+ * @type {boolean}
191
+ */
192
+ showCreateAnother: {
193
+ type: Boolean,
194
+ default: false,
195
+ },
196
+ /**
197
+ * Whether the primary save/create button is disabled.
198
+ * The parent controls validation externally.
199
+ *
200
+ * @type {boolean}
201
+ */
202
+ disableSave: {
203
+ type: Boolean,
204
+ default: false,
205
+ },
206
+ /**
207
+ * Custom success message shown in the result NcNoteCard.
208
+ * Defaults to "{entityName} saved successfully".
209
+ *
210
+ * @type {string}
211
+ */
212
+ successText: {
213
+ type: String,
214
+ default: '',
215
+ },
216
+ /**
217
+ * Cancel button label.
218
+ *
219
+ * @type {string}
220
+ */
221
+ cancelLabel: {
222
+ type: String,
223
+ default: 'Cancel',
224
+ },
225
+ /**
226
+ * Close button label shown in the result phase.
227
+ *
228
+ * @type {string}
229
+ */
230
+ closeLabel: {
231
+ type: String,
232
+ default: 'Close',
233
+ },
234
+ /**
235
+ * Primary confirm button label. Defaults to "Create" in create mode
236
+ * or "Save" in edit mode.
237
+ *
238
+ * @type {string}
239
+ */
240
+ confirmLabel: {
241
+ type: String,
242
+ default: '',
243
+ },
244
+ /**
245
+ * Label for the "Create Another" checkbox.
246
+ *
247
+ * @type {string}
248
+ */
249
+ createAnotherLabel: {
250
+ type: String,
251
+ default: 'Create another',
252
+ },
253
+ },
254
+ data() {
255
+ return {
256
+ /** @type {number} Current active tab index */
257
+ activeTab: 0,
258
+ /** @type {boolean} Whether the "create another" checkbox is checked */
259
+ createAnother: false,
260
+ /** @type {boolean} Whether an API operation is in progress */
261
+ loading: false,
262
+ /**
263
+ * Result of the last operation.
264
+ * null = form phase, { success: true } = success, { error: 'msg' } = error
265
+ *
266
+ * @type {{ success?: boolean, error?: string }|null}
267
+ */
268
+ result: null,
269
+ /** @type {number|null} Timeout ID for auto-close after success */
270
+ closeTimeout: null,
271
+ /** @type {number|null} Timeout ID for clearing success in create-another mode */
272
+ successClearTimeout: null,
273
+ }
274
+ },
275
+ computed: {
276
+ /**
277
+ * Whether the dialog is in create mode (no existing item).
278
+ *
279
+ * @return {boolean}
280
+ */
281
+ isCreateMode() {
282
+ return !this.item
283
+ },
284
+ /**
285
+ * Resolved dialog title. Uses dialogTitle prop if provided,
286
+ * otherwise auto-generates from entityName and mode.
287
+ *
288
+ * @return {string}
289
+ */
290
+ resolvedTitle() {
291
+ if (this.dialogTitle) {
292
+ return this.dialogTitle
293
+ }
294
+ return this.isCreateMode
295
+ ? `Create ${this.entityName}`
296
+ : `Edit ${this.entityName}`
297
+ },
298
+ /**
299
+ * Resolved success text for NcNoteCard.
300
+ *
301
+ * @return {string}
302
+ */
303
+ resolvedSuccessText() {
304
+ if (this.successText) {
305
+ return this.successText
306
+ }
307
+ return `${this.entityName} saved successfully`
308
+ },
309
+ /**
310
+ * Resolved primary button label.
311
+ *
312
+ * @return {string}
313
+ */
314
+ resolvedConfirmLabel() {
315
+ if (this.confirmLabel) {
316
+ return this.confirmLabel
317
+ }
318
+ return this.isCreateMode ? 'Create' : 'Save'
319
+ },
320
+ },
321
+ beforeDestroy() {
322
+ clearTimeout(this.closeTimeout)
323
+ clearTimeout(this.successClearTimeout)
324
+ },
325
+ methods: {
326
+ /**
327
+ * Set the result of the save operation. Call this from the parent
328
+ * after the API call completes.
329
+ *
330
+ * When success is true and create-another is not checked, the dialog
331
+ * auto-closes after 2 seconds. When create-another is checked,
332
+ * the success message shows inline for 2 seconds, then clears and
333
+ * emits the `reset` event.
334
+ *
335
+ * @param {{ success?: boolean, error?: string }} resultData - Result data to pass to the dialog
336
+ * @public
337
+ */
338
+ setResult(resultData) {
339
+ this.loading = false
340
+ this.result = resultData
341
+
342
+ if (resultData.success) {
343
+ if (this.createAnother) {
344
+ // Create-another mode: show success briefly, then reset
345
+ this.successClearTimeout = setTimeout(() => {
346
+ this.result = null
347
+ this.activeTab = 0
348
+ /**
349
+ * Emitted after a successful save in create-another mode.
350
+ * The parent should clear its form data.
351
+ *
352
+ * @event reset
353
+ */
354
+ this.$emit('reset')
355
+ }, 2000)
356
+ } else {
357
+ // Standard mode: auto-close after 2 seconds
358
+ this.closeTimeout = setTimeout(() => {
359
+ /**
360
+ * Emitted when the dialog should be closed.
361
+ *
362
+ * @event close
363
+ */
364
+ this.$emit('close')
365
+ }, 2000)
366
+ }
367
+ }
368
+ },
369
+
370
+ /**
371
+ * Reset the dialog to its initial form state.
372
+ * Clears any result, resets loading, and returns to the first tab.
373
+ *
374
+ * @public
375
+ */
376
+ resetDialog() {
377
+ clearTimeout(this.closeTimeout)
378
+ clearTimeout(this.successClearTimeout)
379
+ this.result = null
380
+ this.loading = false
381
+ this.activeTab = 0
382
+ },
383
+
384
+ /**
385
+ * Handle the primary action button click.
386
+ * Sets loading state and emits the confirm event.
387
+ *
388
+ * @private
389
+ */
390
+ executeConfirm() {
391
+ this.loading = true
392
+ this.result = null
393
+ /**
394
+ * Emitted when the user clicks Save/Create.
395
+ * The parent should perform the API call and then call setResult().
396
+ *
397
+ * @event confirm
398
+ */
399
+ this.$emit('confirm')
400
+ },
401
+
402
+ /**
403
+ * Handle close button click. Clears timeouts and emits close.
404
+ *
405
+ * @private
406
+ */
407
+ handleClose() {
408
+ clearTimeout(this.closeTimeout)
409
+ clearTimeout(this.successClearTimeout)
410
+ this.result = null
411
+ this.loading = false
412
+ this.createAnother = false
413
+ this.activeTab = 0
414
+ this.$emit('close')
415
+ },
416
+ },
417
+ }
418
+ </script>
419
+
420
+ <style scoped>
421
+ /* Result phase container */
422
+ .cn-tabbed-form-dialog__result {
423
+ padding: 16px 0;
424
+ }
425
+
426
+ /* Form phase container */
427
+ .cn-tabbed-form-dialog__form {
428
+ display: flex;
429
+ flex-direction: column;
430
+ gap: 8px;
431
+ }
432
+
433
+ /* Tabs wrapper */
434
+ .cn-tabbed-form-dialog__tabs {
435
+ display: flex;
436
+ flex-direction: column;
437
+ gap: 12px;
438
+ }
439
+
440
+ /* Tab content area — also uses .form-editor for compatibility */
441
+ .cn-tabbed-form-dialog__tab-content {
442
+ display: flex;
443
+ flex-direction: column;
444
+ gap: 16px;
445
+ padding: 16px 0;
446
+ }
447
+
448
+ /* Create another checkbox — push to the left in actions area */
449
+ .cn-tabbed-form-dialog__create-another {
450
+ margin-right: auto;
451
+ }
452
+
453
+ /* Bootstrap-Vue tab container styling */
454
+ .tabContainer > * ul > li {
455
+ display: flex;
456
+ flex: 1;
457
+ }
458
+
459
+ .tabContainer > * ul > li:hover {
460
+ background-color: var(--color-background-hover);
461
+ }
462
+
463
+ .tabContainer > * ul > li > a {
464
+ flex: 1;
465
+ text-align: center;
466
+ }
467
+
468
+ .tabContainer > * ul > li > .active {
469
+ background: transparent !important;
470
+ color: var(--color-main-text) !important;
471
+ border-bottom: var(--default-grid-baseline) solid var(--color-primary-element) !important;
472
+ }
473
+
474
+ .tabContainer > * ul[role="tablist"] {
475
+ display: flex;
476
+ margin: 10px 8px 0 8px;
477
+ justify-content: space-between;
478
+ border-bottom: 1px solid var(--color-border);
479
+ }
480
+
481
+ .tabContainer > * ul[role="tablist"] > * a[role="tab"] {
482
+ padding-inline-start: 10px;
483
+ padding-inline-end: 10px;
484
+ padding-block-start: 10px;
485
+ padding-block-end: 10px;
486
+ }
487
+
488
+ .tabContainer > * div[role="tabpanel"] {
489
+ margin-block-start: var(--OR-margin-10);
490
+ }
491
+
492
+ :deep(.nav-tabs) {
493
+ border-bottom: 1px solid var(--color-border);
494
+ margin-bottom: 15px;
495
+ display: flex;
496
+ }
497
+
498
+ :deep(.nav-tabs .nav-item) {
499
+ display: flex;
500
+ flex: 1;
501
+ }
502
+
503
+ :deep(.nav-tabs .nav-link) {
504
+ flex: 1;
505
+ text-align: center;
506
+ border: none;
507
+ border-bottom: 2px solid transparent;
508
+ color: var(--color-text-maxcontrast);
509
+ padding: 8px 16px;
510
+ display: flex;
511
+ align-items: center;
512
+ gap: 8px;
513
+ justify-content: center;
514
+ }
515
+
516
+ :deep(.nav-tabs .nav-link.active) {
517
+ color: var(--color-main-text);
518
+ border-bottom: 2px solid var(--color-primary);
519
+ background-color: transparent;
520
+ }
521
+
522
+ :deep(.nav-tabs .nav-link:hover) {
523
+ border-bottom: 2px solid var(--color-border);
524
+ }
525
+
526
+ :deep(.nav-tabs .nav-link.disabled) {
527
+ cursor: not-allowed;
528
+ opacity: 0.5;
529
+ color: var(--color-text-maxcontrast);
530
+ pointer-events: auto;
531
+ }
532
+ :deep(.nav-tabs .nav-link.disabled *) {
533
+ cursor: not-allowed;
534
+ }
535
+
536
+ :deep(.nav-tabs .nav-link.disabled:hover) {
537
+ border-bottom: 2px solid transparent;
538
+ }
539
+
540
+ :deep(.tab-content) {
541
+ padding: 16px;
542
+ background-color: var(--color-main-background);
543
+ }
544
+ </style>
@@ -0,0 +1 @@
1
+ export { default as CnTabbedFormDialog } from './CnTabbedFormDialog.vue'