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

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