@conduction/nextcloud-vue 0.1.0-beta.3 → 0.1.0-beta.5

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 (142) hide show
  1. package/README.md +226 -226
  2. package/dist/nextcloud-vue.cjs +67614 -0
  3. package/dist/nextcloud-vue.cjs.js +58386 -6112
  4. package/dist/nextcloud-vue.cjs.js.map +1 -1
  5. package/dist/nextcloud-vue.cjs.map +1 -0
  6. package/dist/nextcloud-vue.css +1819 -285
  7. package/dist/nextcloud-vue.esm.js +58342 -6088
  8. package/dist/nextcloud-vue.esm.js.map +1 -1
  9. package/package.json +82 -62
  10. package/src/components/CnActionsBar/CnActionsBar.vue +17 -7
  11. package/src/components/CnActionsBar/index.js +1 -1
  12. package/src/components/CnAdvancedFormDialog/CnAdvancedFormDialog.vue +579 -0
  13. package/src/components/CnAdvancedFormDialog/CnDataTab.vue +217 -0
  14. package/src/components/CnAdvancedFormDialog/CnMetadataTab.vue +121 -0
  15. package/src/components/CnAdvancedFormDialog/CnPropertiesTab.vue +418 -0
  16. package/src/components/CnAdvancedFormDialog/CnPropertyValueCell.vue +247 -0
  17. package/src/components/CnAdvancedFormDialog/index.js +1 -0
  18. package/src/components/CnCardGrid/CnCardGrid.vue +1 -1
  19. package/src/components/CnCardGrid/index.js +1 -1
  20. package/src/components/CnCellRenderer/index.js +1 -1
  21. package/src/components/CnChartWidget/CnChartWidget.vue +320 -0
  22. package/src/components/CnChartWidget/index.js +1 -0
  23. package/src/components/CnConfigurationCard/index.js +1 -1
  24. package/src/components/CnCopyDialog/CnCopyDialog.vue +250 -250
  25. package/src/components/CnDashboardGrid/CnDashboardGrid.vue +225 -0
  26. package/src/components/CnDashboardGrid/index.js +1 -0
  27. package/src/components/CnDashboardPage/CnDashboardPage.vue +390 -0
  28. package/src/components/CnDashboardPage/index.js +1 -0
  29. package/src/components/CnDataTable/CnDataTable.vue +1 -1
  30. package/src/components/CnDataTable/index.js +1 -1
  31. package/src/components/CnDeleteDialog/CnDeleteDialog.vue +170 -170
  32. package/src/components/CnDetailCard/CnDetailCard.vue +214 -0
  33. package/src/components/CnDetailCard/index.js +1 -0
  34. package/src/components/CnDetailPage/CnDetailPage.vue +285 -0
  35. package/src/components/CnDetailPage/index.js +1 -0
  36. package/src/components/CnFacetSidebar/CnFacetSidebar.vue +9 -1
  37. package/src/components/CnFacetSidebar/index.js +1 -1
  38. package/src/components/CnFilterBar/index.js +1 -1
  39. package/src/components/CnFormDialog/CnFormDialog.vue +302 -11
  40. package/src/components/CnIcon/index.js +1 -1
  41. package/src/components/CnIndexPage/CnIndexPage.vue +71 -3
  42. package/src/components/CnIndexPage/index.js +1 -1
  43. package/src/components/CnIndexSidebar/CnIndexSidebar.vue +121 -102
  44. package/src/components/CnIndexSidebar/index.js +1 -1
  45. package/src/components/CnItemCard/CnItemCard.vue +132 -0
  46. package/src/components/CnItemCard/index.js +1 -0
  47. package/src/components/CnKpiGrid/index.js +1 -1
  48. package/src/components/CnMassActionBar/index.js +1 -1
  49. package/src/components/CnMassCopyDialog/index.js +1 -1
  50. package/src/components/CnMassDeleteDialog/index.js +1 -1
  51. package/src/components/CnMassExportDialog/index.js +1 -1
  52. package/src/components/CnMassImportDialog/index.js +1 -1
  53. package/src/components/CnNoteCard/CnNoteCard.vue +149 -0
  54. package/src/components/CnNoteCard/index.js +1 -0
  55. package/src/components/CnNotesCard/CnNotesCard.vue +413 -0
  56. package/src/components/CnNotesCard/index.js +1 -0
  57. package/src/components/CnObjectCard/CnObjectCard.vue +1 -1
  58. package/src/components/CnObjectCard/index.js +1 -1
  59. package/src/components/CnObjectSidebar/CnObjectSidebar.vue +876 -0
  60. package/src/components/CnObjectSidebar/index.js +1 -0
  61. package/src/components/CnPageHeader/index.js +1 -1
  62. package/src/components/CnPagination/index.js +1 -1
  63. package/src/components/CnRegisterMapping/CnRegisterMapping.vue +792 -792
  64. package/src/components/CnRowActions/CnRowActions.vue +25 -3
  65. package/src/components/CnRowActions/index.js +1 -1
  66. package/src/components/CnSchemaFormDialog/CnSchemaConfigurationTab.vue +226 -0
  67. package/src/components/CnSchemaFormDialog/CnSchemaFormDialog.vue +787 -0
  68. package/src/components/CnSchemaFormDialog/CnSchemaPropertiesTab.vue +305 -0
  69. package/src/components/CnSchemaFormDialog/CnSchemaPropertyActions.vue +1398 -0
  70. package/src/components/CnSchemaFormDialog/CnSchemaSecurityTab.vue +236 -0
  71. package/src/components/CnSchemaFormDialog/index.js +1 -0
  72. package/src/components/CnSettingsCard/index.js +1 -1
  73. package/src/components/CnSettingsSection/index.js +1 -1
  74. package/src/components/CnStatsBlock/CnStatsBlock.vue +62 -8
  75. package/src/components/CnStatsBlock/index.js +1 -1
  76. package/src/components/CnStatusBadge/index.js +1 -1
  77. package/src/components/CnTabbedFormDialog/CnTabbedFormDialog.vue +540 -0
  78. package/src/components/CnTabbedFormDialog/index.js +1 -0
  79. package/src/components/CnTasksCard/CnTasksCard.vue +373 -0
  80. package/src/components/CnTasksCard/index.js +1 -0
  81. package/src/components/CnTileWidget/CnTileWidget.vue +159 -0
  82. package/src/components/CnTileWidget/index.js +1 -0
  83. package/src/components/CnTimelineStages/CnTimelineStages.vue +292 -0
  84. package/src/components/CnTimelineStages/index.js +1 -0
  85. package/src/components/CnUserActionMenu/CnUserActionMenu.vue +435 -0
  86. package/src/components/CnUserActionMenu/index.js +1 -0
  87. package/src/components/CnVersionInfoCard/index.js +1 -1
  88. package/src/components/CnWidgetRenderer/CnWidgetRenderer.vue +180 -0
  89. package/src/components/CnWidgetRenderer/index.js +1 -0
  90. package/src/components/CnWidgetWrapper/CnWidgetWrapper.vue +211 -0
  91. package/src/components/CnWidgetWrapper/index.js +1 -0
  92. package/src/components/index.js +43 -29
  93. package/src/composables/index.js +4 -3
  94. package/src/composables/useDashboardView.js +240 -0
  95. package/src/composables/useDetailView.js +289 -132
  96. package/src/composables/useListView.js +363 -362
  97. package/src/composables/useSubResource.js +142 -142
  98. package/src/constants/metadata.js +30 -30
  99. package/src/css/CnSchemaFormDialog.css +546 -0
  100. package/src/css/__sample_nextcloud_tokens.css +110 -0
  101. package/src/css/actions-bar.css +48 -48
  102. package/src/css/badge.css +51 -51
  103. package/src/css/card.css +128 -128
  104. package/src/css/dashboard.css +70 -0
  105. package/src/css/detail-page.css +168 -0
  106. package/src/css/detail.css +68 -68
  107. package/src/css/index-page.css +44 -32
  108. package/src/css/index-sidebar.css +193 -187
  109. package/src/css/index.css +16 -12
  110. package/src/css/layout.css +90 -90
  111. package/src/css/page-header.css +33 -33
  112. package/src/css/pagination.css +72 -72
  113. package/src/css/table.css +142 -142
  114. package/src/css/timeline-stages.css +218 -0
  115. package/src/css/utilities.css +46 -46
  116. package/src/index.js +72 -53
  117. package/src/store/createSubResourcePlugin.js +135 -135
  118. package/src/store/index.js +3 -3
  119. package/src/store/plugins/auditTrails.js +17 -17
  120. package/src/store/plugins/files.js +250 -186
  121. package/src/store/plugins/index.js +7 -5
  122. package/src/store/plugins/lifecycle.js +180 -180
  123. package/src/store/plugins/relations.js +68 -68
  124. package/src/store/plugins/search.js +372 -0
  125. package/src/store/plugins/selection.js +104 -0
  126. package/src/store/useObjectStore.js +829 -686
  127. package/src/types/auditTrail.d.ts +32 -32
  128. package/src/types/file.d.ts +23 -23
  129. package/src/types/index.d.ts +35 -35
  130. package/src/types/notification.d.ts +36 -36
  131. package/src/types/object.d.ts +40 -40
  132. package/src/types/organisation.d.ts +41 -41
  133. package/src/types/register.d.ts +25 -25
  134. package/src/types/schema.d.ts +39 -39
  135. package/src/types/shared.d.ts +79 -79
  136. package/src/types/source.d.ts +14 -14
  137. package/src/types/task.d.ts +31 -31
  138. package/src/utils/errors.js +96 -96
  139. package/src/utils/headers.js +68 -50
  140. package/src/utils/id.js +13 -0
  141. package/src/utils/index.js +3 -3
  142. package/src/utils/schema.js +422 -419
@@ -0,0 +1,373 @@
1
+ <!--
2
+ CnTasksCard — Inline tasks card for detail pages.
3
+
4
+ Displays up to 5 tasks with status indicators, assignee, and due date.
5
+ Integrates CnUserActionMenu on assignee names. Highlights overdue tasks.
6
+ Wraps CnDetailCard for consistent styling.
7
+ -->
8
+ <template>
9
+ <CnDetailCard :title="titleLabel" :icon="CheckboxMarkedOutline" :collapsible="collapsible">
10
+ <div class="cn-tasks-card">
11
+ <!-- Loading state -->
12
+ <NcLoadingIcon v-if="loading" />
13
+
14
+ <!-- Empty state -->
15
+ <div v-else-if="allTasks.length === 0" class="cn-tasks-card__empty">
16
+ {{ noTasksLabel }}
17
+ </div>
18
+
19
+ <!-- Tasks list -->
20
+ <div v-else class="cn-tasks-card__list">
21
+ <div
22
+ v-for="task in displayedTasks"
23
+ :key="task.id"
24
+ class="cn-tasks-card__task">
25
+ <!-- Status icon -->
26
+ <div class="cn-tasks-card__status-icon">
27
+ <CheckboxMarkedOutline
28
+ v-if="task.status === 'completed'"
29
+ :size="20"
30
+ class="cn-tasks-card__icon--completed" />
31
+ <ProgressClock
32
+ v-else-if="task.status === 'active' || task.status === 'in-process'"
33
+ :size="20"
34
+ class="cn-tasks-card__icon--active" />
35
+ <CloseCircleOutline
36
+ v-else-if="task.status === 'terminated'"
37
+ :size="20"
38
+ class="cn-tasks-card__icon--terminated" />
39
+ <CheckboxBlankOutline
40
+ v-else
41
+ :size="20"
42
+ class="cn-tasks-card__icon--available" />
43
+ </div>
44
+
45
+ <!-- Task content -->
46
+ <div class="cn-tasks-card__content">
47
+ <span class="cn-tasks-card__title">{{ task.title || task.name }}</span>
48
+ <div class="cn-tasks-card__meta">
49
+ <!-- Assignee -->
50
+ <span v-if="hasAssignee(task)" class="cn-tasks-card__assignee">
51
+ <CnUserActionMenu
52
+ v-if="!isCurrentUser(task.assignee)"
53
+ :user-id="task.assignee"
54
+ :display-name="task.assignee">
55
+ <span class="cn-tasks-card__assignee-name">{{ task.assignee }}</span>
56
+ </CnUserActionMenu>
57
+ <span v-else class="cn-tasks-card__assignee-name cn-tasks-card__assignee-name--self">
58
+ {{ task.assignee }}
59
+ </span>
60
+ </span>
61
+ <span v-else class="cn-tasks-card__unassigned">
62
+ {{ unassignedLabel }}
63
+ </span>
64
+
65
+ <!-- Due date -->
66
+ <span
67
+ v-if="task.dueDate"
68
+ class="cn-tasks-card__due-date"
69
+ :class="{ 'cn-tasks-card__due-date--overdue': isOverdue(task) }">
70
+ {{ formatDate(task.dueDate) }}
71
+ </span>
72
+ </div>
73
+ </div>
74
+ </div>
75
+ </div>
76
+ </div>
77
+
78
+ <!-- Footer: "Show all" link -->
79
+ <template v-if="allTasks.length > maxDisplay" #footer>
80
+ <button
81
+ class="cn-tasks-card__show-all"
82
+ @click="$emit('show-all')">
83
+ {{ showAllLabel }} ({{ allTasks.length }})
84
+ </button>
85
+ </template>
86
+ </CnDetailCard>
87
+ </template>
88
+
89
+ <script>
90
+ import { NcLoadingIcon } from '@nextcloud/vue'
91
+ import CheckboxMarkedOutline from 'vue-material-design-icons/CheckboxMarkedOutline.vue'
92
+ import CheckboxBlankOutline from 'vue-material-design-icons/CheckboxBlankOutline.vue'
93
+ import ProgressClock from 'vue-material-design-icons/ProgressClock.vue'
94
+ import CloseCircleOutline from 'vue-material-design-icons/CloseCircleOutline.vue'
95
+
96
+ import CnDetailCard from '../CnDetailCard/CnDetailCard.vue'
97
+ import CnUserActionMenu from '../CnUserActionMenu/CnUserActionMenu.vue'
98
+ import { buildHeaders } from '../../utils/index.js'
99
+
100
+ /**
101
+ * CnTasksCard — Inline tasks widget for detail pages.
102
+ *
103
+ * Shows up to 5 tasks sorted by due date with status indicators.
104
+ * Highlights overdue tasks and integrates CnUserActionMenu on assignees.
105
+ *
106
+ * @example Basic usage
107
+ * <CnTasksCard
108
+ * register-id="uuid-register"
109
+ * schema-id="uuid-schema"
110
+ * object-id="uuid-object" />
111
+ *
112
+ * @example With sidebar sync
113
+ * <CnTasksCard
114
+ * register-id="reg"
115
+ * schema-id="schema"
116
+ * object-id="obj"
117
+ * @show-all="openSidebarTasksTab" />
118
+ */
119
+ export default {
120
+ name: 'CnTasksCard',
121
+
122
+ components: {
123
+ CnDetailCard,
124
+ CnUserActionMenu,
125
+ NcLoadingIcon,
126
+ CheckboxMarkedOutline,
127
+ CheckboxBlankOutline,
128
+ ProgressClock,
129
+ CloseCircleOutline,
130
+ },
131
+
132
+ props: {
133
+ /** OpenRegister register ID */
134
+ registerId: {
135
+ type: String,
136
+ required: true,
137
+ },
138
+ /** OpenRegister schema ID */
139
+ schemaId: {
140
+ type: String,
141
+ required: true,
142
+ },
143
+ /** Object UUID */
144
+ objectId: {
145
+ type: String,
146
+ required: true,
147
+ },
148
+ /** Base API URL for OpenRegister */
149
+ apiBase: {
150
+ type: String,
151
+ default: '/apps/openregister/api',
152
+ },
153
+ /** Maximum number of tasks to display */
154
+ maxDisplay: {
155
+ type: Number,
156
+ default: 5,
157
+ },
158
+ /** Whether the card is collapsible */
159
+ collapsible: {
160
+ type: Boolean,
161
+ default: false,
162
+ },
163
+
164
+ // --- Pre-translated labels ---
165
+ titleLabel: { type: String, default: 'Tasks' },
166
+ noTasksLabel: { type: String, default: 'No tasks' },
167
+ showAllLabel: { type: String, default: 'Show all' },
168
+ unassignedLabel: { type: String, default: 'Unassigned' },
169
+ },
170
+
171
+ emits: ['show-all'],
172
+
173
+ data() {
174
+ return {
175
+ CheckboxMarkedOutline,
176
+ allTasks: [],
177
+ loading: false,
178
+ }
179
+ },
180
+
181
+ computed: {
182
+ displayedTasks() {
183
+ // Sort by due date (soonest first), then limit
184
+ const sorted = [...this.allTasks].sort((a, b) => {
185
+ const dateA = a.dueDate ? new Date(a.dueDate) : new Date('9999-12-31')
186
+ const dateB = b.dueDate ? new Date(b.dueDate) : new Date('9999-12-31')
187
+ return dateA - dateB
188
+ })
189
+ return sorted.slice(0, this.maxDisplay)
190
+ },
191
+ },
192
+
193
+ watch: {
194
+ objectId: {
195
+ immediate: true,
196
+ handler(newId) {
197
+ if (newId && this.registerId && this.schemaId) {
198
+ this.fetchTasks()
199
+ }
200
+ },
201
+ },
202
+ },
203
+
204
+ methods: {
205
+ hasAssignee(task) {
206
+ return task.assignee && task.assignee.trim() !== ''
207
+ },
208
+
209
+ isCurrentUser(userId) {
210
+ const currentUser = typeof OC !== 'undefined' ? OC?.currentUser : null
211
+ return userId === currentUser
212
+ },
213
+
214
+ isOverdue(task) {
215
+ if (!task.dueDate || task.status === 'completed') return false
216
+ try {
217
+ return new Date(task.dueDate) < new Date()
218
+ } catch {
219
+ return false
220
+ }
221
+ },
222
+
223
+ async fetchTasks() {
224
+ if (!this.registerId || !this.schemaId || !this.objectId) return
225
+ this.loading = true
226
+ try {
227
+ const url = `${this.apiBase}/objects/${this.registerId}/${this.schemaId}/${this.objectId}/tasks`
228
+ const response = await fetch(url, { headers: buildHeaders() })
229
+ if (response.ok) {
230
+ const data = await response.json()
231
+ this.allTasks = data.results || data || []
232
+ }
233
+ } catch (err) {
234
+ console.error('CnTasksCard: Failed to fetch tasks', err)
235
+ } finally {
236
+ this.loading = false
237
+ }
238
+ },
239
+
240
+ formatDate(dateStr) {
241
+ if (!dateStr) return ''
242
+ try {
243
+ return new Date(dateStr).toLocaleDateString(undefined, {
244
+ year: 'numeric',
245
+ month: 'short',
246
+ day: 'numeric',
247
+ })
248
+ } catch {
249
+ return dateStr
250
+ }
251
+ },
252
+ },
253
+ }
254
+ </script>
255
+
256
+ <style scoped>
257
+ .cn-tasks-card__empty {
258
+ text-align: center;
259
+ padding: 16px 12px;
260
+ color: var(--color-text-maxcontrast);
261
+ font-size: 13px;
262
+ }
263
+
264
+ .cn-tasks-card__list {
265
+ display: flex;
266
+ flex-direction: column;
267
+ }
268
+
269
+ .cn-tasks-card__task {
270
+ display: flex;
271
+ align-items: flex-start;
272
+ gap: 10px;
273
+ padding: 8px 0;
274
+ border-bottom: 1px solid var(--color-border);
275
+ }
276
+
277
+ .cn-tasks-card__task:last-child {
278
+ border-bottom: none;
279
+ }
280
+
281
+ .cn-tasks-card__status-icon {
282
+ flex-shrink: 0;
283
+ padding-top: 1px;
284
+ }
285
+
286
+ .cn-tasks-card__icon--completed {
287
+ color: var(--color-success);
288
+ }
289
+
290
+ .cn-tasks-card__icon--active {
291
+ color: var(--color-primary-element);
292
+ }
293
+
294
+ .cn-tasks-card__icon--terminated {
295
+ color: var(--color-error);
296
+ }
297
+
298
+ .cn-tasks-card__icon--available {
299
+ color: var(--color-text-maxcontrast);
300
+ }
301
+
302
+ .cn-tasks-card__content {
303
+ flex: 1;
304
+ min-width: 0;
305
+ }
306
+
307
+ .cn-tasks-card__title {
308
+ display: block;
309
+ font-size: 13px;
310
+ font-weight: 500;
311
+ white-space: nowrap;
312
+ overflow: hidden;
313
+ text-overflow: ellipsis;
314
+ }
315
+
316
+ .cn-tasks-card__meta {
317
+ display: flex;
318
+ align-items: center;
319
+ gap: 8px;
320
+ margin-top: 2px;
321
+ font-size: 12px;
322
+ color: var(--color-text-maxcontrast);
323
+ }
324
+
325
+ .cn-tasks-card__assignee-name {
326
+ color: var(--color-primary-element);
327
+ font-weight: 500;
328
+ cursor: pointer;
329
+ }
330
+
331
+ .cn-tasks-card__assignee-name:hover {
332
+ text-decoration: underline;
333
+ }
334
+
335
+ .cn-tasks-card__assignee-name--self {
336
+ color: var(--color-text-maxcontrast);
337
+ cursor: default;
338
+ }
339
+
340
+ .cn-tasks-card__assignee-name--self:hover {
341
+ text-decoration: none;
342
+ }
343
+
344
+ .cn-tasks-card__unassigned {
345
+ font-style: italic;
346
+ color: var(--color-text-maxcontrast);
347
+ }
348
+
349
+ .cn-tasks-card__due-date {
350
+ white-space: nowrap;
351
+ }
352
+
353
+ .cn-tasks-card__due-date--overdue {
354
+ color: var(--color-error);
355
+ font-weight: 500;
356
+ }
357
+
358
+ .cn-tasks-card__show-all {
359
+ background: none;
360
+ border: none;
361
+ color: var(--color-primary-element);
362
+ font-size: 13px;
363
+ font-weight: 500;
364
+ cursor: pointer;
365
+ padding: 0;
366
+ width: 100%;
367
+ text-align: center;
368
+ }
369
+
370
+ .cn-tasks-card__show-all:hover {
371
+ text-decoration: underline;
372
+ }
373
+ </style>
@@ -0,0 +1 @@
1
+ export { default as CnTasksCard } from './CnTasksCard.vue'
@@ -0,0 +1,159 @@
1
+ <!--
2
+ CnTileWidget — Quick-access tile with icon and link.
3
+
4
+ A simple, colorful tile for app shortcuts or external links.
5
+ Supports SVG paths, CSS icon classes, image URLs, and emoji icons.
6
+ -->
7
+ <template>
8
+ <div
9
+ v-if="tile"
10
+ class="cn-tile-widget"
11
+ :style="tileStyles">
12
+ <a
13
+ :href="tileUrl"
14
+ class="cn-tile-widget__link"
15
+ :target="tile.linkType === 'url' ? '_blank' : '_self'"
16
+ rel="noopener noreferrer">
17
+ <!-- SVG icon -->
18
+ <svg
19
+ v-if="tile.iconType === 'svg'"
20
+ class="cn-tile-widget__icon cn-tile-widget__icon--svg"
21
+ :style="{ fill: tile.textColor || '#ffffff' }"
22
+ viewBox="0 0 24 24">
23
+ <path :d="tile.icon" />
24
+ </svg>
25
+ <!-- Other icon types -->
26
+ <div v-else class="cn-tile-widget__icon">
27
+ <span v-if="tile.iconType === 'class'" :class="['icon', tile.icon]" />
28
+ <img v-else-if="tile.iconType === 'url'" :src="tile.icon" alt="">
29
+ <span v-else-if="tile.iconType === 'emoji'" class="cn-tile-widget__emoji">{{ tile.icon }}</span>
30
+ </div>
31
+ <div class="cn-tile-widget__title" :style="{ color: tile.textColor || '#ffffff' }">
32
+ {{ tile.title }}
33
+ </div>
34
+ </a>
35
+ </div>
36
+ </template>
37
+
38
+ <script>
39
+ import { generateUrl } from '@nextcloud/router'
40
+
41
+ /**
42
+ * CnTileWidget — Quick-access tile with icon and link.
43
+ *
44
+ * @example
45
+ * <CnTileWidget :tile="{
46
+ * title: 'Files',
47
+ * icon: 'M12,2C6.48,...',
48
+ * iconType: 'svg',
49
+ * backgroundColor: '#0082c9',
50
+ * textColor: '#ffffff',
51
+ * linkType: 'app',
52
+ * linkValue: 'files',
53
+ * }" />
54
+ */
55
+ export default {
56
+ name: 'CnTileWidget',
57
+
58
+ props: {
59
+ /**
60
+ * Tile configuration object.
61
+ * @type {{ title: string, icon: string, iconType: 'svg'|'class'|'url'|'emoji', backgroundColor?: string, textColor?: string, linkType: 'app'|'url', linkValue: string }}
62
+ */
63
+ tile: {
64
+ type: Object,
65
+ required: true,
66
+ },
67
+ },
68
+
69
+ computed: {
70
+ tileUrl() {
71
+ if (this.tile.linkType === 'app') {
72
+ return generateUrl('/apps/' + this.tile.linkValue)
73
+ }
74
+ return this.tile.linkValue || '#'
75
+ },
76
+
77
+ tileStyles() {
78
+ return {
79
+ '--cn-tile-bg': this.tile.backgroundColor || '#0082c9',
80
+ '--cn-tile-text': this.tile.textColor || '#ffffff',
81
+ }
82
+ },
83
+ },
84
+ }
85
+ </script>
86
+
87
+ <style scoped>
88
+ .cn-tile-widget {
89
+ height: 100%;
90
+ width: 100%;
91
+ position: absolute;
92
+ top: 0;
93
+ left: 0;
94
+ overflow: hidden;
95
+ background-color: var(--cn-tile-bg);
96
+ }
97
+
98
+ .cn-tile-widget__link {
99
+ display: flex;
100
+ flex-direction: column;
101
+ align-items: center;
102
+ justify-content: center;
103
+ height: 100%;
104
+ width: 100%;
105
+ text-decoration: none;
106
+ padding: 20px;
107
+ gap: 12px;
108
+ transition: transform 0.2s ease, opacity 0.2s ease;
109
+ background-color: var(--cn-tile-bg);
110
+ color: var(--cn-tile-text);
111
+ }
112
+
113
+ .cn-tile-widget__link:hover {
114
+ transform: scale(1.02);
115
+ opacity: 0.95;
116
+ }
117
+
118
+ .cn-tile-widget__icon {
119
+ font-size: 48px;
120
+ width: 48px;
121
+ height: 48px;
122
+ display: flex;
123
+ align-items: center;
124
+ justify-content: center;
125
+ flex-shrink: 0;
126
+ }
127
+
128
+ .cn-tile-widget__icon--svg {
129
+ width: 48px;
130
+ height: 48px;
131
+ }
132
+
133
+ .cn-tile-widget__icon span.icon {
134
+ display: inline-block;
135
+ width: 48px;
136
+ height: 48px;
137
+ background-size: 48px;
138
+ filter: brightness(0) invert(1);
139
+ }
140
+
141
+ .cn-tile-widget__icon img {
142
+ width: 100%;
143
+ height: 100%;
144
+ object-fit: contain;
145
+ }
146
+
147
+ .cn-tile-widget__emoji {
148
+ font-size: 48px;
149
+ }
150
+
151
+ .cn-tile-widget__title {
152
+ font-size: 16px;
153
+ font-weight: 700;
154
+ text-align: center;
155
+ word-break: break-word;
156
+ line-height: 1.3;
157
+ color: var(--cn-tile-text);
158
+ }
159
+ </style>
@@ -0,0 +1 @@
1
+ export { default as CnTileWidget } from './CnTileWidget.vue'