@conduction/nextcloud-vue 0.1.0-beta.3 → 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/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 -62
- 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 -362
- 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
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="cn-schema-form__security-section">
|
|
3
|
+
<CnNoteCard type="info">
|
|
4
|
+
<p><strong>Role-Based Access Control (RBAC)</strong></p>
|
|
5
|
+
<p>Configure which Nextcloud user groups can perform CRUD operations on objects of this schema.</p>
|
|
6
|
+
<ul>
|
|
7
|
+
<li>If no groups are specified for an operation, all users can perform it</li>
|
|
8
|
+
<li>The 'admin' group always has full access (cannot be changed)</li>
|
|
9
|
+
<li>The object owner always has full access</li>
|
|
10
|
+
<li>'public' represents unauthenticated access</li>
|
|
11
|
+
</ul>
|
|
12
|
+
</CnNoteCard>
|
|
13
|
+
|
|
14
|
+
<div v-if="loadingGroups" class="cn-schema-form__loading-groups">
|
|
15
|
+
<NcLoadingIcon :size="20" />
|
|
16
|
+
<span>Loading user groups...</span>
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
<div v-else class="cn-schema-form__rbac-table-container">
|
|
20
|
+
<h3>Group Permissions</h3>
|
|
21
|
+
<table class="cn-schema-form__rbac-table">
|
|
22
|
+
<thead>
|
|
23
|
+
<tr>
|
|
24
|
+
<th>Group</th>
|
|
25
|
+
<th>Create</th>
|
|
26
|
+
<th>Read</th>
|
|
27
|
+
<th>Update</th>
|
|
28
|
+
<th>Delete</th>
|
|
29
|
+
</tr>
|
|
30
|
+
</thead>
|
|
31
|
+
<tbody>
|
|
32
|
+
<!-- Public group at top -->
|
|
33
|
+
<tr class="cn-schema-form__public-row">
|
|
34
|
+
<td class="cn-schema-form__group-name">
|
|
35
|
+
<span class="cn-schema-form__group-badge cn-schema-form__public">public</span>
|
|
36
|
+
<small>Unauthenticated users</small>
|
|
37
|
+
</td>
|
|
38
|
+
<td>
|
|
39
|
+
<NcCheckboxRadioSwitch
|
|
40
|
+
:checked="hasGroupPermission('public', 'create')"
|
|
41
|
+
@update:checked="updateGroupPermission('public', 'create', $event)" />
|
|
42
|
+
</td>
|
|
43
|
+
<td>
|
|
44
|
+
<NcCheckboxRadioSwitch
|
|
45
|
+
:checked="hasGroupPermission('public', 'read')"
|
|
46
|
+
@update:checked="updateGroupPermission('public', 'read', $event)" />
|
|
47
|
+
</td>
|
|
48
|
+
<td>
|
|
49
|
+
<NcCheckboxRadioSwitch
|
|
50
|
+
:checked="hasGroupPermission('public', 'update')"
|
|
51
|
+
@update:checked="updateGroupPermission('public', 'update', $event)" />
|
|
52
|
+
</td>
|
|
53
|
+
<td>
|
|
54
|
+
<NcCheckboxRadioSwitch
|
|
55
|
+
:checked="hasGroupPermission('public', 'delete')"
|
|
56
|
+
@update:checked="updateGroupPermission('public', 'delete', $event)" />
|
|
57
|
+
</td>
|
|
58
|
+
</tr>
|
|
59
|
+
|
|
60
|
+
<!-- User group (authenticated users) -->
|
|
61
|
+
<tr class="cn-schema-form__user-row">
|
|
62
|
+
<td class="cn-schema-form__group-name">
|
|
63
|
+
<span class="cn-schema-form__group-badge cn-schema-form__user">user</span>
|
|
64
|
+
<small>Authenticated users</small>
|
|
65
|
+
</td>
|
|
66
|
+
<td>
|
|
67
|
+
<NcCheckboxRadioSwitch
|
|
68
|
+
:checked="hasGroupPermission('user', 'create')"
|
|
69
|
+
@update:checked="updateGroupPermission('user', 'create', $event)" />
|
|
70
|
+
</td>
|
|
71
|
+
<td>
|
|
72
|
+
<NcCheckboxRadioSwitch
|
|
73
|
+
:checked="hasGroupPermission('user', 'read')"
|
|
74
|
+
@update:checked="updateGroupPermission('user', 'read', $event)" />
|
|
75
|
+
</td>
|
|
76
|
+
<td>
|
|
77
|
+
<NcCheckboxRadioSwitch
|
|
78
|
+
:checked="hasGroupPermission('user', 'update')"
|
|
79
|
+
@update:checked="updateGroupPermission('user', 'update', $event)" />
|
|
80
|
+
</td>
|
|
81
|
+
<td>
|
|
82
|
+
<NcCheckboxRadioSwitch
|
|
83
|
+
:checked="hasGroupPermission('user', 'delete')"
|
|
84
|
+
@update:checked="updateGroupPermission('user', 'delete', $event)" />
|
|
85
|
+
</td>
|
|
86
|
+
</tr>
|
|
87
|
+
|
|
88
|
+
<!-- Regular user groups -->
|
|
89
|
+
<tr v-for="group in sortedUserGroups" :key="group.id">
|
|
90
|
+
<td class="cn-schema-form__group-name">
|
|
91
|
+
<span class="cn-schema-form__group-badge">{{ group.displayname || group.id }}</span>
|
|
92
|
+
<small v-if="group.displayname && group.displayname !== group.id">{{ group.id }}</small>
|
|
93
|
+
</td>
|
|
94
|
+
<td>
|
|
95
|
+
<NcCheckboxRadioSwitch
|
|
96
|
+
:checked="hasGroupPermission(group.id, 'create')"
|
|
97
|
+
@update:checked="updateGroupPermission(group.id, 'create', $event)" />
|
|
98
|
+
</td>
|
|
99
|
+
<td>
|
|
100
|
+
<NcCheckboxRadioSwitch
|
|
101
|
+
:checked="hasGroupPermission(group.id, 'read')"
|
|
102
|
+
@update:checked="updateGroupPermission(group.id, 'read', $event)" />
|
|
103
|
+
</td>
|
|
104
|
+
<td>
|
|
105
|
+
<NcCheckboxRadioSwitch
|
|
106
|
+
:checked="hasGroupPermission(group.id, 'update')"
|
|
107
|
+
@update:checked="updateGroupPermission(group.id, 'update', $event)" />
|
|
108
|
+
</td>
|
|
109
|
+
<td>
|
|
110
|
+
<NcCheckboxRadioSwitch
|
|
111
|
+
:checked="hasGroupPermission(group.id, 'delete')"
|
|
112
|
+
@update:checked="updateGroupPermission(group.id, 'delete', $event)" />
|
|
113
|
+
</td>
|
|
114
|
+
</tr>
|
|
115
|
+
|
|
116
|
+
<!-- Admin group at bottom (disabled) -->
|
|
117
|
+
<tr class="cn-schema-form__admin-row">
|
|
118
|
+
<td class="cn-schema-form__group-name">
|
|
119
|
+
<span class="cn-schema-form__group-badge cn-schema-form__admin">admin</span>
|
|
120
|
+
<small>Always has full access</small>
|
|
121
|
+
</td>
|
|
122
|
+
<td>
|
|
123
|
+
<NcCheckboxRadioSwitch
|
|
124
|
+
:checked="true"
|
|
125
|
+
:disabled="true" />
|
|
126
|
+
</td>
|
|
127
|
+
<td>
|
|
128
|
+
<NcCheckboxRadioSwitch
|
|
129
|
+
:checked="true"
|
|
130
|
+
:disabled="true" />
|
|
131
|
+
</td>
|
|
132
|
+
<td>
|
|
133
|
+
<NcCheckboxRadioSwitch
|
|
134
|
+
:checked="true"
|
|
135
|
+
:disabled="true" />
|
|
136
|
+
</td>
|
|
137
|
+
<td>
|
|
138
|
+
<NcCheckboxRadioSwitch
|
|
139
|
+
:checked="true"
|
|
140
|
+
:disabled="true" />
|
|
141
|
+
</td>
|
|
142
|
+
</tr>
|
|
143
|
+
</tbody>
|
|
144
|
+
</table>
|
|
145
|
+
|
|
146
|
+
<div class="cn-schema-form__rbac-summary">
|
|
147
|
+
<CnNoteCard v-if="!hasAnyPermissions" type="success">
|
|
148
|
+
<p><strong>Open Access:</strong> No specific permissions set - all users can perform all operations.</p>
|
|
149
|
+
</CnNoteCard>
|
|
150
|
+
<CnNoteCard v-else-if="isRestrictiveSchema" type="warning">
|
|
151
|
+
<p><strong>Restrictive Schema:</strong> Access is limited to specified groups only.</p>
|
|
152
|
+
</CnNoteCard>
|
|
153
|
+
</div>
|
|
154
|
+
</div>
|
|
155
|
+
</div>
|
|
156
|
+
</template>
|
|
157
|
+
|
|
158
|
+
<script>
|
|
159
|
+
import {
|
|
160
|
+
// NcNoteCard,
|
|
161
|
+
NcCheckboxRadioSwitch,
|
|
162
|
+
NcLoadingIcon,
|
|
163
|
+
} from '@nextcloud/vue'
|
|
164
|
+
import CnNoteCard from '../CnNoteCard/CnNoteCard.vue'
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* CnSchemaSecurityTab — RBAC permissions table tab for CnSchemaFormDialog.
|
|
168
|
+
*
|
|
169
|
+
* Renders the schema-level authorization configuration. Mutates
|
|
170
|
+
* schemaItem.authorization directly.
|
|
171
|
+
*/
|
|
172
|
+
export default {
|
|
173
|
+
name: 'CnSchemaSecurityTab',
|
|
174
|
+
components: {
|
|
175
|
+
CnNoteCard,
|
|
176
|
+
NcCheckboxRadioSwitch,
|
|
177
|
+
NcLoadingIcon,
|
|
178
|
+
},
|
|
179
|
+
props: {
|
|
180
|
+
/** The full schema item — mutates authorization directly */
|
|
181
|
+
schemaItem: { type: Object, required: true },
|
|
182
|
+
/** Full user groups array */
|
|
183
|
+
userGroups: { type: Array, default: () => [] },
|
|
184
|
+
/** Filtered/sorted user groups (excludes admin/public) */
|
|
185
|
+
sortedUserGroups: { type: Array, default: () => [] },
|
|
186
|
+
/** Whether groups are loading */
|
|
187
|
+
loadingGroups: { type: Boolean, default: false },
|
|
188
|
+
/** Whether schema has any permissions set */
|
|
189
|
+
hasAnyPermissions: { type: Boolean, default: false },
|
|
190
|
+
/** Whether schema has restrictive permissions */
|
|
191
|
+
isRestrictiveSchema: { type: Boolean, default: false },
|
|
192
|
+
},
|
|
193
|
+
computed: {
|
|
194
|
+
/** Local alias to avoid vue/no-mutating-props on template bindings */
|
|
195
|
+
schema() {
|
|
196
|
+
return this.schemaItem
|
|
197
|
+
},
|
|
198
|
+
},
|
|
199
|
+
methods: {
|
|
200
|
+
hasGroupPermission(groupId, action) {
|
|
201
|
+
const auth = this.schema.authorization || {}
|
|
202
|
+
if (!auth[action] || !Array.isArray(auth[action])) {
|
|
203
|
+
return false
|
|
204
|
+
}
|
|
205
|
+
return auth[action].includes(groupId)
|
|
206
|
+
},
|
|
207
|
+
|
|
208
|
+
updateGroupPermission(groupId, action, hasPermission) {
|
|
209
|
+
if (!this.schema.authorization) {
|
|
210
|
+
this.$set(this.schema, 'authorization', {})
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (!this.schema.authorization[action]) {
|
|
214
|
+
this.$set(this.schema.authorization, action, [])
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const currentPermissions = this.schema.authorization[action]
|
|
218
|
+
const groupIndex = currentPermissions.indexOf(groupId)
|
|
219
|
+
|
|
220
|
+
if (hasPermission && groupIndex === -1) {
|
|
221
|
+
currentPermissions.push(groupId)
|
|
222
|
+
} else if (!hasPermission && groupIndex !== -1) {
|
|
223
|
+
currentPermissions.splice(groupIndex, 1)
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
if (currentPermissions.length === 0) {
|
|
227
|
+
this.$delete(this.schema.authorization, action)
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
if (Object.keys(this.schema.authorization).length === 0) {
|
|
231
|
+
this.$set(this.schema, 'authorization', {})
|
|
232
|
+
}
|
|
233
|
+
},
|
|
234
|
+
},
|
|
235
|
+
}
|
|
236
|
+
</script>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as CnSchemaFormDialog } from './CnSchemaFormDialog.vue'
|
|
@@ -1,92 +1,92 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div class="cn-settings-card" :class="{ 'cn-settings-card--collapsible': collapsible }">
|
|
3
|
-
<h4
|
|
4
|
-
v-if="title"
|
|
5
|
-
:class="{ 'cn-settings-card__header--clickable': collapsible }"
|
|
6
|
-
@click="collapsible ? toggleCollapsed() : null">
|
|
7
|
-
<span>{{ icon }} {{ title }}</span>
|
|
8
|
-
<ChevronDown
|
|
9
|
-
v-if="collapsible && !isCollapsed"
|
|
10
|
-
:size="20"
|
|
11
|
-
class="cn-settings-card__chevron" />
|
|
12
|
-
<ChevronUp
|
|
13
|
-
v-if="collapsible && isCollapsed"
|
|
14
|
-
:size="20"
|
|
15
|
-
class="cn-settings-card__chevron" />
|
|
16
|
-
</h4>
|
|
17
|
-
|
|
18
|
-
<transition v-if="collapsible" name="cn-slide-fade">
|
|
19
|
-
<div v-show="!isCollapsed" class="cn-settings-card__content">
|
|
20
|
-
<slot />
|
|
21
|
-
</div>
|
|
22
|
-
</transition>
|
|
23
|
-
|
|
24
|
-
<div v-else>
|
|
25
|
-
<slot />
|
|
26
|
-
</div>
|
|
27
|
-
</div>
|
|
28
|
-
</template>
|
|
29
|
-
|
|
30
|
-
<script>
|
|
31
|
-
import ChevronDown from 'vue-material-design-icons/ChevronDown.vue'
|
|
32
|
-
import ChevronUp from 'vue-material-design-icons/ChevronUp.vue'
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* CnSettingsCard — Collapsible card for settings and configuration sections.
|
|
36
|
-
*
|
|
37
|
-
* Extracted from OpenRegister's SettingsCard. Provides a titled card with
|
|
38
|
-
* optional collapse/expand animation.
|
|
39
|
-
*
|
|
40
|
-
* @example
|
|
41
|
-
* <CnSettingsCard title="Database Settings" icon="🗄️" collapsible>
|
|
42
|
-
* <p>Content here</p>
|
|
43
|
-
* </CnSettingsCard>
|
|
44
|
-
*/
|
|
45
|
-
export default {
|
|
46
|
-
name: 'CnSettingsCard',
|
|
47
|
-
|
|
48
|
-
components: {
|
|
49
|
-
ChevronDown,
|
|
50
|
-
ChevronUp,
|
|
51
|
-
},
|
|
52
|
-
|
|
53
|
-
props: {
|
|
54
|
-
/** Card title text */
|
|
55
|
-
title: {
|
|
56
|
-
type: String,
|
|
57
|
-
default: '',
|
|
58
|
-
},
|
|
59
|
-
/** Icon emoji or text displayed before the title */
|
|
60
|
-
icon: {
|
|
61
|
-
type: String,
|
|
62
|
-
default: '',
|
|
63
|
-
},
|
|
64
|
-
/** Whether the card can be collapsed */
|
|
65
|
-
collapsible: {
|
|
66
|
-
type: Boolean,
|
|
67
|
-
default: false,
|
|
68
|
-
},
|
|
69
|
-
/** Whether the card starts collapsed (only applies when collapsible) */
|
|
70
|
-
defaultCollapsed: {
|
|
71
|
-
type: Boolean,
|
|
72
|
-
default: false,
|
|
73
|
-
},
|
|
74
|
-
},
|
|
75
|
-
|
|
76
|
-
data() {
|
|
77
|
-
return {
|
|
78
|
-
isCollapsed: this.defaultCollapsed,
|
|
79
|
-
}
|
|
80
|
-
},
|
|
81
|
-
|
|
82
|
-
methods: {
|
|
83
|
-
toggleCollapsed() {
|
|
84
|
-
if (this.collapsible) {
|
|
85
|
-
this.isCollapsed = !this.isCollapsed
|
|
86
|
-
/** @event toggle Emitted when collapse state changes. Payload: isCollapsed boolean. */
|
|
87
|
-
this.$emit('toggle', this.isCollapsed)
|
|
88
|
-
}
|
|
89
|
-
},
|
|
90
|
-
},
|
|
91
|
-
}
|
|
92
|
-
</script>
|
|
1
|
+
<template>
|
|
2
|
+
<div class="cn-settings-card" :class="{ 'cn-settings-card--collapsible': collapsible }">
|
|
3
|
+
<h4
|
|
4
|
+
v-if="title"
|
|
5
|
+
:class="{ 'cn-settings-card__header--clickable': collapsible }"
|
|
6
|
+
@click="collapsible ? toggleCollapsed() : null">
|
|
7
|
+
<span>{{ icon }} {{ title }}</span>
|
|
8
|
+
<ChevronDown
|
|
9
|
+
v-if="collapsible && !isCollapsed"
|
|
10
|
+
:size="20"
|
|
11
|
+
class="cn-settings-card__chevron" />
|
|
12
|
+
<ChevronUp
|
|
13
|
+
v-if="collapsible && isCollapsed"
|
|
14
|
+
:size="20"
|
|
15
|
+
class="cn-settings-card__chevron" />
|
|
16
|
+
</h4>
|
|
17
|
+
|
|
18
|
+
<transition v-if="collapsible" name="cn-slide-fade">
|
|
19
|
+
<div v-show="!isCollapsed" class="cn-settings-card__content">
|
|
20
|
+
<slot />
|
|
21
|
+
</div>
|
|
22
|
+
</transition>
|
|
23
|
+
|
|
24
|
+
<div v-else>
|
|
25
|
+
<slot />
|
|
26
|
+
</div>
|
|
27
|
+
</div>
|
|
28
|
+
</template>
|
|
29
|
+
|
|
30
|
+
<script>
|
|
31
|
+
import ChevronDown from 'vue-material-design-icons/ChevronDown.vue'
|
|
32
|
+
import ChevronUp from 'vue-material-design-icons/ChevronUp.vue'
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* CnSettingsCard — Collapsible card for settings and configuration sections.
|
|
36
|
+
*
|
|
37
|
+
* Extracted from OpenRegister's SettingsCard. Provides a titled card with
|
|
38
|
+
* optional collapse/expand animation.
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* <CnSettingsCard title="Database Settings" icon="🗄️" collapsible>
|
|
42
|
+
* <p>Content here</p>
|
|
43
|
+
* </CnSettingsCard>
|
|
44
|
+
*/
|
|
45
|
+
export default {
|
|
46
|
+
name: 'CnSettingsCard',
|
|
47
|
+
|
|
48
|
+
components: {
|
|
49
|
+
ChevronDown,
|
|
50
|
+
ChevronUp,
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
props: {
|
|
54
|
+
/** Card title text */
|
|
55
|
+
title: {
|
|
56
|
+
type: String,
|
|
57
|
+
default: '',
|
|
58
|
+
},
|
|
59
|
+
/** Icon emoji or text displayed before the title */
|
|
60
|
+
icon: {
|
|
61
|
+
type: String,
|
|
62
|
+
default: '',
|
|
63
|
+
},
|
|
64
|
+
/** Whether the card can be collapsed */
|
|
65
|
+
collapsible: {
|
|
66
|
+
type: Boolean,
|
|
67
|
+
default: false,
|
|
68
|
+
},
|
|
69
|
+
/** Whether the card starts collapsed (only applies when collapsible) */
|
|
70
|
+
defaultCollapsed: {
|
|
71
|
+
type: Boolean,
|
|
72
|
+
default: false,
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
|
|
76
|
+
data() {
|
|
77
|
+
return {
|
|
78
|
+
isCollapsed: this.defaultCollapsed,
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
|
|
82
|
+
methods: {
|
|
83
|
+
toggleCollapsed() {
|
|
84
|
+
if (this.collapsible) {
|
|
85
|
+
this.isCollapsed = !this.isCollapsed
|
|
86
|
+
/** @event toggle Emitted when collapse state changes. Payload: isCollapsed boolean. */
|
|
87
|
+
this.$emit('toggle', this.isCollapsed)
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
}
|
|
92
|
+
</script>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { default as CnSettingsCard } from './CnSettingsCard.vue'
|
|
1
|
+
export { default as CnSettingsCard } from './CnSettingsCard.vue'
|