@conduction/nextcloud-vue 2.74.0 → 2.76.0
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/dist/esm/components/CnAppNav/CnAppNav.vue2.js +19 -14
- package/dist/esm/components/CnAppNav/CnAppNav.vue2.js.map +1 -1
- package/dist/esm/components/CnAppNav/CnAppNav.vue3.js +2 -2
- package/dist/esm/components/CnAppNav/CnAppNav.vue3.js.map +1 -1
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js +77 -26
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js.map +1 -1
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js +22 -14
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js.map +1 -1
- package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue2.js +23 -4
- package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnBrandBar/CnBrandBar.vue.js +9 -0
- package/dist/esm/components/CnBrandBar/CnBrandBar.vue.js.map +1 -0
- package/dist/esm/components/CnBrandBar/CnBrandBar.vue2.js +107 -0
- package/dist/esm/components/CnBrandBar/CnBrandBar.vue2.js.map +1 -0
- package/dist/esm/components/CnBrandBar/CnBrandBar.vue3.js +79 -0
- package/dist/esm/components/CnBrandBar/CnBrandBar.vue3.js.map +1 -0
- package/dist/esm/components/CnCardGrid/CnCardGrid.vue2.js +6 -0
- package/dist/esm/components/CnCardGrid/CnCardGrid.vue2.js.map +1 -1
- package/dist/esm/components/CnCardGrid/CnCardGrid.vue3.js +3 -2
- package/dist/esm/components/CnCardGrid/CnCardGrid.vue3.js.map +1 -1
- package/dist/esm/components/CnCredentials/CnCredentials.vue2.js +11 -10
- package/dist/esm/components/CnCredentials/CnCredentials.vue2.js.map +1 -1
- package/dist/esm/components/CnCredentials/CnCredentials.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +8 -5
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
- package/dist/esm/components/CnEnvironmentBanner/CnEnvironmentBanner.vue2.js +4 -1
- package/dist/esm/components/CnEnvironmentBanner/CnEnvironmentBanner.vue2.js.map +1 -1
- package/dist/esm/components/CnEnvironmentBanner/CnEnvironmentBanner.vue3.js.map +1 -1
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js +7 -0
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js.map +1 -1
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue3.js +14 -7
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue3.js.map +1 -1
- package/dist/esm/components/CnFormPage/CnFormPage.vue2.js +32 -0
- package/dist/esm/components/CnFormPage/CnFormPage.vue2.js.map +1 -1
- package/dist/esm/components/CnFormPage/CnFormPage.vue3.js +6 -3
- package/dist/esm/components/CnFormPage/CnFormPage.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +144 -6
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +14 -13
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/selfModeActions.js +90 -14
- package/dist/esm/components/CnIndexPage/selfModeActions.js.map +1 -1
- package/dist/esm/components/CnIndexPage/useSelfFetchList.js +15 -3
- package/dist/esm/components/CnIndexPage/useSelfFetchList.js.map +1 -1
- package/dist/esm/components/CnObjectCard/CnObjectCard.vue2.js +26 -0
- package/dist/esm/components/CnObjectCard/CnObjectCard.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectCard/CnObjectCard.vue3.js +26 -9
- package/dist/esm/components/CnObjectCard/CnObjectCard.vue3.js.map +1 -1
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js +19 -3
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnQuickFilterBar/CnQuickFilterBar.vue2.js +18 -2
- package/dist/esm/components/CnQuickFilterBar/CnQuickFilterBar.vue2.js.map +1 -1
- package/dist/esm/components/CnQuickFilterBar/CnQuickFilterBar.vue3.js +2 -2
- package/dist/esm/components/CnQuickFilterBar/CnQuickFilterBar.vue3.js.map +1 -1
- package/dist/esm/components/CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue2.js +153 -38
- package/dist/esm/components/CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue3.js +74 -56
- package/dist/esm/components/CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnStatsBlock/CnStatsBlock.vue2.js +16 -0
- package/dist/esm/components/CnStatsBlock/CnStatsBlock.vue2.js.map +1 -1
- package/dist/esm/components/CnStatsBlock/CnStatsBlock.vue3.js +2 -2
- package/dist/esm/components/CnStatsBlock/CnStatsBlock.vue3.js.map +1 -1
- package/dist/esm/composables/useObjectLock.js +41 -10
- package/dist/esm/composables/useObjectLock.js.map +1 -1
- package/dist/esm/directives/cnSelectAria.js +55 -0
- package/dist/esm/directives/cnSelectAria.js.map +1 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/l10n/en.json.js +7 -1
- package/dist/esm/l10n/en.json.js.map +1 -1
- package/dist/esm/l10n/nl.json.js +8 -2
- package/dist/esm/l10n/nl.json.js.map +1 -1
- package/dist/esm/nextcloud-vue.css +154 -2
- package/dist/esm/store/useObjectStore.js +37 -9
- package/dist/esm/store/useObjectStore.js.map +1 -1
- package/dist/esm/utils/cnFetch.js +17 -2
- package/dist/esm/utils/cnFetch.js.map +1 -1
- package/dist/esm/utils/objectSignals.js +44 -0
- package/dist/esm/utils/objectSignals.js.map +1 -0
- package/dist/esm/utils/resolveBrand.js +38 -0
- package/dist/esm/utils/resolveBrand.js.map +1 -0
- package/dist/esm/utils/validateManifestV2.compiled.js +2 -2
- package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
- package/dist/nextcloud-vue.cjs.js +9640 -8649
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +154 -2
- package/l10n/en.json +7 -1
- package/l10n/nl.json +8 -2
- package/package.json +1 -1
- package/src/components/CnAppNav/CnAppNav.vue +21 -16
- package/src/components/CnAppRoot/CnAppRoot.vue +53 -0
- package/src/components/CnBannerWidget/CnBannerWidget.vue +23 -4
- package/src/components/CnBrandBar/CnBrandBar.vue +230 -0
- package/src/components/CnCardGrid/CnCardGrid.md +1 -0
- package/src/components/CnCardGrid/CnCardGrid.vue +7 -0
- package/src/components/CnCredentials/CnCredentials.vue +17 -16
- package/src/components/CnDetailPage/CnDetailPage.vue +8 -5
- package/src/components/CnEnvironmentBanner/CnEnvironmentBanner.vue +4 -1
- package/src/components/CnFormDialog/CnFormDialog.vue +10 -0
- package/src/components/CnFormPage/CnFormPage.vue +33 -0
- package/src/components/CnIndexPage/CnIndexPage.md +15 -0
- package/src/components/CnIndexPage/CnIndexPage.vue +157 -18
- package/src/components/CnIndexPage/selfModeActions.js +89 -13
- package/src/components/CnIndexPage/useSelfFetchList.js +15 -3
- package/src/components/CnObjectCard/CnObjectCard.md +1 -0
- package/src/components/CnObjectCard/CnObjectCard.vue +89 -1
- package/src/components/CnObjectListWidget/CnObjectListWidget.vue +19 -3
- package/src/components/CnQuickFilterBar/CnQuickFilterBar.vue +20 -4
- package/src/components/CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue +181 -38
- package/src/components/CnStatsBlock/CnStatsBlock.vue +18 -2
- package/src/composables/__tests__/useObjectLock.endpoints.spec.js +83 -0
- package/src/composables/useObjectLock.js +41 -10
- package/src/css/form-field.css +1 -1
- package/src/css/look-board-index.css +35 -1
- package/src/directives/cnSelectAria.js +54 -0
- package/src/index.js +1 -0
- package/src/schemas/app-manifest-v2.schema.json +6 -1
- package/src/store/useObjectStore.js +37 -9
- package/src/utils/cnFetch.js +16 -1
- package/src/utils/index.js +1 -0
- package/src/utils/objectSignals.js +41 -0
- package/src/utils/resolveBrand.js +37 -0
- package/src/utils/validateManifestV2.compiled.js +2 -2
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
:activeFilterChips="activeFilterChips"
|
|
83
83
|
:showBuildiqButton="!buildiqInHeader"
|
|
84
84
|
:bulkNoun="boardBulkNoun"
|
|
85
|
-
:bulkHint="bulkHint"
|
|
85
|
+
:bulkHint="bulkHint ? cnTranslate(bulkHint) : bulkHint"
|
|
86
86
|
:pagination="effectivePagination"
|
|
87
87
|
:objectCount="effectiveObjects.length"
|
|
88
88
|
:selectable="selectable"
|
|
@@ -430,19 +430,19 @@
|
|
|
430
430
|
name="form-dialog"
|
|
431
431
|
:show="showFormDialogVisible"
|
|
432
432
|
:item="editItem"
|
|
433
|
-
:schema="
|
|
433
|
+
:schema="formSchema"
|
|
434
434
|
:confirm="onFormConfirm"
|
|
435
435
|
:close="closeFormDialog"
|
|
436
436
|
:refresh="onRefreshEvent">
|
|
437
437
|
<CnFormDialog
|
|
438
438
|
v-if="showFormDialogVisible && !useAdvancedFormDialog"
|
|
439
439
|
ref="formDialog"
|
|
440
|
-
:schema="
|
|
440
|
+
:schema="formSchema"
|
|
441
441
|
:item="editItem"
|
|
442
|
-
:register="
|
|
443
|
-
:excludeFields="excludeFields"
|
|
444
|
-
:includeFields="includeFields"
|
|
445
|
-
:fieldOverrides="fieldOverrides"
|
|
442
|
+
:register="formRegister"
|
|
443
|
+
:excludeFields="rowFormTarget ? [] : excludeFields"
|
|
444
|
+
:includeFields="rowFormTarget ? null : includeFields"
|
|
445
|
+
:fieldOverrides="rowFormTarget ? {} : fieldOverrides"
|
|
446
446
|
:nameField="massActionNameField"
|
|
447
447
|
:size="formSize"
|
|
448
448
|
:columns="formColumns"
|
|
@@ -456,11 +456,11 @@
|
|
|
456
456
|
<CnAdvancedFormDialog
|
|
457
457
|
v-if="showFormDialogVisible && useAdvancedFormDialog"
|
|
458
458
|
ref="formDialog"
|
|
459
|
-
:schema="
|
|
459
|
+
:schema="formSchema"
|
|
460
460
|
:item="editItem"
|
|
461
|
-
:excludeFields="excludeFields"
|
|
462
|
-
:includeFields="includeFields"
|
|
463
|
-
:fieldOverrides="fieldOverrides"
|
|
461
|
+
:excludeFields="rowFormTarget ? [] : excludeFields"
|
|
462
|
+
:includeFields="rowFormTarget ? null : includeFields"
|
|
463
|
+
:fieldOverrides="rowFormTarget ? {} : fieldOverrides"
|
|
464
464
|
:nameField="massActionNameField"
|
|
465
465
|
:initialValues="resolvedCreateDefaults"
|
|
466
466
|
@confirm="onFormConfirm"
|
|
@@ -788,6 +788,7 @@
|
|
|
788
788
|
:selectable="selectable"
|
|
789
789
|
:clickToView="rowClickOpens"
|
|
790
790
|
:cardFields="resolvedCardFields"
|
|
791
|
+
:accentOf="cardAccent"
|
|
791
792
|
:selectedIds="internalSelectedIds"
|
|
792
793
|
:rowKey="rowKey"
|
|
793
794
|
:emptyText="emptyText"
|
|
@@ -848,7 +849,7 @@
|
|
|
848
849
|
<CnPagination
|
|
849
850
|
v-if="effectivePagination && (effectivePagination.pages > 1 || (isBoardLook && effectivePagination.total > 0))"
|
|
850
851
|
:variant="isBoardLook ? 'board' : ''"
|
|
851
|
-
:footerNote="footerNote"
|
|
852
|
+
:footerNote="footerNote ? cnTranslate(footerNote) : footerNote"
|
|
852
853
|
:currentPage="effectivePagination.page || 1"
|
|
853
854
|
:totalPages="effectivePagination.pages || 1"
|
|
854
855
|
:totalItems="effectivePagination.total || 0"
|
|
@@ -971,6 +972,7 @@ import { openRowTarget } from '../../utils/linkNavigation.js'
|
|
|
971
972
|
import { resolveClaimedTeams, resolveClaimTokens, splitViewsIntoTabs, viewAsTab, viewIdOf } from '../../utils/listLenses.js'
|
|
972
973
|
import { LIST_SHORTCUTS, listPaletteCommands, shortcutFor } from '../../utils/listShortcuts.js'
|
|
973
974
|
import { multiKeySort } from '../../utils/multiKeySort.js'
|
|
975
|
+
import { OBJECTS_CHANGED_EVENT } from '../../utils/objectSignals.js'
|
|
974
976
|
import { withPersonalLenses } from '../../utils/personalLenses.js'
|
|
975
977
|
import { resolveDeepTokens, resolveFilterValue } from '../../utils/resolveFilterTokens.js'
|
|
976
978
|
import { resolveRowActions } from '../../utils/resolveRowActions.js'
|
|
@@ -1016,7 +1018,7 @@ import { buildDefaultActions } from './defaultActions.js'
|
|
|
1016
1018
|
import { dispatchAction } from './manifestActionDispatch.js'
|
|
1017
1019
|
import { applyManualOrder, dropInOrder, manualOrderKey, moveInOrder, visibleIdsOf } from './manualOrder.js'
|
|
1018
1020
|
import { orderColumns, personalColumnsKey, reconcilePersonalColumns } from './personalColumns.js'
|
|
1019
|
-
import { createSelfModeActions } from './selfModeActions.js'
|
|
1021
|
+
import { createSelfModeActions, resolveRowTarget } from './selfModeActions.js'
|
|
1020
1022
|
import { applyRowPatches, normalisePaneWidth, rowIdOf, splitLayoutFor } from './splitView.js'
|
|
1021
1023
|
import { useNamedSource } from './useNamedSource.js'
|
|
1022
1024
|
import { useSelfFetchList } from './useSelfFetchList.js'
|
|
@@ -1475,6 +1477,17 @@ export default {
|
|
|
1475
1477
|
default: null,
|
|
1476
1478
|
},
|
|
1477
1479
|
|
|
1480
|
+
/**
|
|
1481
|
+
* Gives each card in the card view a status accent: a colored start
|
|
1482
|
+
* border and icon. See CnObjectCard `accent`.
|
|
1483
|
+
*
|
|
1484
|
+
* @type {((object: object) => ({variant: string, icon: string, label: string}|null))|null}
|
|
1485
|
+
*/
|
|
1486
|
+
cardAccent: {
|
|
1487
|
+
type: Function,
|
|
1488
|
+
default: null,
|
|
1489
|
+
},
|
|
1490
|
+
|
|
1478
1491
|
/**
|
|
1479
1492
|
* Board look: free text after the footer's count ("8 of 48 · click a
|
|
1480
1493
|
* column header to sort"). Manifest key `config.footerNote`.
|
|
@@ -1646,6 +1659,21 @@ export default {
|
|
|
1646
1659
|
default: () => [],
|
|
1647
1660
|
},
|
|
1648
1661
|
|
|
1662
|
+
/**
|
|
1663
|
+
* Self-fetch only: list from this endpoint instead of
|
|
1664
|
+
* `/api/objects/{register}/{schema}`, e.g. an app endpoint that searches
|
|
1665
|
+
* several register/schema pairs at once. `register` and `schema` stay the
|
|
1666
|
+
* page's own pair (columns, create, export, import). Rows of another pair,
|
|
1667
|
+
* read from their `@self.register` / `@self.schema`, are edited, copied and
|
|
1668
|
+
* deleted against that pair, with its own form. The endpoint takes
|
|
1669
|
+
* `_page`, `_limit`, `_search` and `_order[key]=dir` and answers
|
|
1670
|
+
* `{ results, total, page, pages }`.
|
|
1671
|
+
*/
|
|
1672
|
+
collectionUrl: {
|
|
1673
|
+
type: String,
|
|
1674
|
+
default: '',
|
|
1675
|
+
},
|
|
1676
|
+
|
|
1649
1677
|
/**
|
|
1650
1678
|
* Offer an "Also search inside files" switch beside the search box. On,
|
|
1651
1679
|
* a search also matches words inside attached files (OpenRegister
|
|
@@ -3153,6 +3181,8 @@ export default {
|
|
|
3153
3181
|
*/
|
|
3154
3182
|
persistedFilterKeys: [...(this.initialQueryFilterKeys || [])],
|
|
3155
3183
|
internalSelectedIds: [...this.selectedIds],
|
|
3184
|
+
// Rows seen in a collectionUrl list, so a selection kept across pages still resolves its own pair.
|
|
3185
|
+
collectionRowsById: markRaw(new Map()),
|
|
3156
3186
|
// Folder-sidebar state: selected folder id + the register-fetched list.
|
|
3157
3187
|
selectedFolderId: null,
|
|
3158
3188
|
/**
|
|
@@ -3190,6 +3220,9 @@ export default {
|
|
|
3190
3220
|
// Dialog targets
|
|
3191
3221
|
actionTargetItem: null,
|
|
3192
3222
|
editItem: null,
|
|
3223
|
+
// The pair and schema of a row edited outside the page's own pair (collectionUrl).
|
|
3224
|
+
rowFormTarget: null,
|
|
3225
|
+
rowFormSchema: null,
|
|
3193
3226
|
// Drives the Actions-menu Refresh spinner during a self-fetch
|
|
3194
3227
|
// refresh, where the host has no promise to bind `:refreshing` to.
|
|
3195
3228
|
internalRefreshing: false,
|
|
@@ -4471,6 +4504,16 @@ export default {
|
|
|
4471
4504
|
return (this.schema && typeof this.schema === 'object') ? this.schema : null
|
|
4472
4505
|
},
|
|
4473
4506
|
|
|
4507
|
+
/** The form dialog's schema: the edited row's own when it is of another pair. */
|
|
4508
|
+
formSchema() {
|
|
4509
|
+
return this.rowFormTarget ? this.rowFormSchema : this.effectiveSchema
|
|
4510
|
+
},
|
|
4511
|
+
|
|
4512
|
+
/** The form dialog's register, following `formSchema`. */
|
|
4513
|
+
formRegister() {
|
|
4514
|
+
return this.rowFormTarget ? this.rowFormTarget.register : this.register
|
|
4515
|
+
},
|
|
4516
|
+
|
|
4474
4517
|
/**
|
|
4475
4518
|
* Schema slug for the export-leaf URL — the `schema` prop directly
|
|
4476
4519
|
* when it's a string (self-fetch mode's precondition), else the
|
|
@@ -4857,8 +4900,7 @@ export default {
|
|
|
4857
4900
|
this.$emit('edit-open', row)
|
|
4858
4901
|
return
|
|
4859
4902
|
}
|
|
4860
|
-
this.
|
|
4861
|
-
this.showFormDialogVisible = true
|
|
4903
|
+
this.openFormFor(row)
|
|
4862
4904
|
},
|
|
4863
4905
|
onCopy: (row) => {
|
|
4864
4906
|
this.actionTargetItem = row
|
|
@@ -5367,6 +5409,21 @@ export default {
|
|
|
5367
5409
|
},
|
|
5368
5410
|
|
|
5369
5411
|
watch: {
|
|
5412
|
+
effectiveObjects: {
|
|
5413
|
+
immediate: true,
|
|
5414
|
+
handler(rows) {
|
|
5415
|
+
if (!this.collectionUrl || !this.isSelfFetchMode || !Array.isArray(rows)) {
|
|
5416
|
+
return
|
|
5417
|
+
}
|
|
5418
|
+
for (const row of rows) {
|
|
5419
|
+
const id = row?.id ?? row?.['@self']?.id
|
|
5420
|
+
if (id !== undefined && id !== null) {
|
|
5421
|
+
this.collectionRowsById.set(id, row)
|
|
5422
|
+
}
|
|
5423
|
+
}
|
|
5424
|
+
},
|
|
5425
|
+
},
|
|
5426
|
+
|
|
5370
5427
|
// A column or form field bound to a property the schema lacks is told to the host once.
|
|
5371
5428
|
effectiveSchema: {
|
|
5372
5429
|
immediate: true,
|
|
@@ -5559,6 +5616,9 @@ export default {
|
|
|
5559
5616
|
if (this.splitViewEnabled && typeof window !== 'undefined') {
|
|
5560
5617
|
window.addEventListener('resize', this.measureSplitViewport)
|
|
5561
5618
|
}
|
|
5619
|
+
if (typeof window !== 'undefined') {
|
|
5620
|
+
window.addEventListener(OBJECTS_CHANGED_EVENT, this.onObjectsChanged)
|
|
5621
|
+
}
|
|
5562
5622
|
this.loadManualOrder()
|
|
5563
5623
|
this.loadPersonalColumns()
|
|
5564
5624
|
this.publishHoistedSidebar()
|
|
@@ -5583,6 +5643,8 @@ export default {
|
|
|
5583
5643
|
this.selfActions = createSelfModeActions({
|
|
5584
5644
|
isSelfFetchMode: () => this.isSelfFetchMode,
|
|
5585
5645
|
selfObjectStore: () => this.selfObjectStore,
|
|
5646
|
+
rowTarget: (row) => this.rowTypeTarget(row),
|
|
5647
|
+
knownRow: (id) => this.collectionRowsById.get(id),
|
|
5586
5648
|
selfObjectType: () => this.selfObjectType,
|
|
5587
5649
|
list: () => this.list,
|
|
5588
5650
|
selectedIds: () => this.internalSelectedIds,
|
|
@@ -5608,13 +5670,14 @@ export default {
|
|
|
5608
5670
|
},
|
|
5609
5671
|
|
|
5610
5672
|
/**
|
|
5611
|
-
* Drop the
|
|
5673
|
+
* Drop the window listeners and the hoisted sidebar.
|
|
5612
5674
|
*
|
|
5613
5675
|
* @spec openspec/changes/case-page-and-list-as-a-place/specs/index-page/spec.md
|
|
5614
5676
|
*/
|
|
5615
5677
|
beforeUnmount() {
|
|
5616
5678
|
if (typeof window !== 'undefined') {
|
|
5617
5679
|
window.removeEventListener('resize', this.measureSplitViewport)
|
|
5680
|
+
window.removeEventListener(OBJECTS_CHANGED_EVENT, this.onObjectsChanged)
|
|
5618
5681
|
}
|
|
5619
5682
|
// Clear the holder so the hoisted sidebar disappears when
|
|
5620
5683
|
// the user navigates away from the index page.
|
|
@@ -7076,6 +7139,33 @@ export default {
|
|
|
7076
7139
|
}
|
|
7077
7140
|
},
|
|
7078
7141
|
|
|
7142
|
+
/**
|
|
7143
|
+
* Refresh the list when `dispatchObjectsChanged` names this page's
|
|
7144
|
+
* register and schema, by slug or id. A part missing on either side matches.
|
|
7145
|
+
*
|
|
7146
|
+
* @param {CustomEvent} event The objects-changed event.
|
|
7147
|
+
* @return {void}
|
|
7148
|
+
*/
|
|
7149
|
+
onObjectsChanged(event) {
|
|
7150
|
+
// A collection list can hold rows of any pair, so any change may show in it.
|
|
7151
|
+
if (this.isSelfFetchMode && this.collectionUrl) {
|
|
7152
|
+
this.onRefreshEvent()
|
|
7153
|
+
return
|
|
7154
|
+
}
|
|
7155
|
+
const detail = (event && event.detail) || {}
|
|
7156
|
+
const schema = this.effectiveSchema
|
|
7157
|
+
const schemaIds = [this.schema, schema && schema.id, schema && schema.slug]
|
|
7158
|
+
.filter((v) => v !== undefined && v !== null && v !== '' && typeof v !== 'object')
|
|
7159
|
+
.map(String)
|
|
7160
|
+
if (detail.register && this.register && detail.register !== String(this.register)) {
|
|
7161
|
+
return
|
|
7162
|
+
}
|
|
7163
|
+
if (detail.schema && schemaIds.length > 0 && !schemaIds.includes(detail.schema)) {
|
|
7164
|
+
return
|
|
7165
|
+
}
|
|
7166
|
+
this.onRefreshEvent()
|
|
7167
|
+
},
|
|
7168
|
+
|
|
7079
7169
|
/** @return {Promise<void>} */
|
|
7080
7170
|
async onRefreshEvent() {
|
|
7081
7171
|
this.$emit('refresh')
|
|
@@ -8218,6 +8308,8 @@ export default {
|
|
|
8218
8308
|
closeFormDialog() {
|
|
8219
8309
|
this.showFormDialogVisible = false
|
|
8220
8310
|
this.editItem = null
|
|
8311
|
+
this.rowFormTarget = null
|
|
8312
|
+
this.rowFormSchema = null
|
|
8221
8313
|
},
|
|
8222
8314
|
|
|
8223
8315
|
/**
|
|
@@ -8278,8 +8370,55 @@ export default {
|
|
|
8278
8370
|
* @public
|
|
8279
8371
|
*/
|
|
8280
8372
|
openFormDialog(item = null) {
|
|
8281
|
-
this.
|
|
8282
|
-
|
|
8373
|
+
return this.openFormFor(item)
|
|
8374
|
+
},
|
|
8375
|
+
|
|
8376
|
+
/**
|
|
8377
|
+
* Open the form dialog for an item. A row of another pair (collectionUrl)
|
|
8378
|
+
* opens with its own schema; everything else opens at once, as before.
|
|
8379
|
+
*
|
|
8380
|
+
* @param {object|null} item The row to edit, or null to create.
|
|
8381
|
+
* @return {Promise<void>|void}
|
|
8382
|
+
*/
|
|
8383
|
+
openFormFor(item) {
|
|
8384
|
+
const target = item ? this.rowTypeTarget(item) : null
|
|
8385
|
+
if (!target) {
|
|
8386
|
+
this.rowFormTarget = null
|
|
8387
|
+
this.rowFormSchema = null
|
|
8388
|
+
this.editItem = item
|
|
8389
|
+
this.showFormDialogVisible = true
|
|
8390
|
+
return
|
|
8391
|
+
}
|
|
8392
|
+
const store = this.selfObjectStore
|
|
8393
|
+
return Promise.resolve(store.getSchema?.(target.type) || store.fetchSchema?.(target.type))
|
|
8394
|
+
.catch(() => null)
|
|
8395
|
+
.then((schema) => {
|
|
8396
|
+
if (!schema) {
|
|
8397
|
+
this.toastSavedView('error', t('nextcloud-vue', 'Could not load the form for this item.'))
|
|
8398
|
+
return
|
|
8399
|
+
}
|
|
8400
|
+
this.rowFormTarget = target
|
|
8401
|
+
this.rowFormSchema = schema
|
|
8402
|
+
this.editItem = item
|
|
8403
|
+
this.showFormDialogVisible = true
|
|
8404
|
+
})
|
|
8405
|
+
},
|
|
8406
|
+
|
|
8407
|
+
/**
|
|
8408
|
+
* The row's own pair when it differs from the page's in a collectionUrl list.
|
|
8409
|
+
*
|
|
8410
|
+
* @param {object} row The row.
|
|
8411
|
+
* @return {{register: string, schema: string, type: string}|null} The pair, or null.
|
|
8412
|
+
*/
|
|
8413
|
+
rowTypeTarget(row) {
|
|
8414
|
+
return resolveRowTarget({
|
|
8415
|
+
collectionUrl: this.isSelfFetchMode ? this.collectionUrl : '',
|
|
8416
|
+
register: this.register,
|
|
8417
|
+
schema: this.schema,
|
|
8418
|
+
primarySchema: this.effectiveSchema,
|
|
8419
|
+
primaryRegister: this.selfObjectStore?.getRegister?.(this.selfObjectType) || null,
|
|
8420
|
+
store: this.selfObjectStore,
|
|
8421
|
+
}, row)
|
|
8283
8422
|
},
|
|
8284
8423
|
|
|
8285
8424
|
/**
|
|
@@ -13,6 +13,58 @@ function resolveNameField(ctx) {
|
|
|
13
13
|
|
|
14
14
|
function findSource(ctx, id) {
|
|
15
15
|
return ctx.effectiveObjects().find((o) => o.id === id || o['@self']?.id === id)
|
|
16
|
+
|| (typeof ctx.knownRow === 'function' ? ctx.knownRow(id) : undefined)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The register/schema of a row that belongs to another pair than the page's,
|
|
21
|
+
* in a list fetched from a `collectionUrl`. Registers a store type for that
|
|
22
|
+
* pair on first use. Returns null for rows of the page's own pair, and always
|
|
23
|
+
* without a `collectionUrl`.
|
|
24
|
+
*
|
|
25
|
+
* @param {object} opts Page context.
|
|
26
|
+
* @param {string} opts.collectionUrl The page's collection endpoint, or ''.
|
|
27
|
+
* @param {string} opts.register The page's register.
|
|
28
|
+
* @param {string} opts.schema The page's schema.
|
|
29
|
+
* @param {object|null} opts.primarySchema The page's resolved schema.
|
|
30
|
+
* @param {object|null} [opts.primaryRegister] The page's resolved register, which matches a slug `register` to `@self.register`.
|
|
31
|
+
* @param {object|null} opts.store The object store.
|
|
32
|
+
* @param {object} row The row.
|
|
33
|
+
* @return {{register: string, schema: string, type: string}|null} The row's own pair.
|
|
34
|
+
*/
|
|
35
|
+
export function resolveRowTarget({ collectionUrl, register, schema, primarySchema, primaryRegister, store }, row) {
|
|
36
|
+
if (!collectionUrl || !row || !store) {
|
|
37
|
+
return null
|
|
38
|
+
}
|
|
39
|
+
const self = row['@self'] || {}
|
|
40
|
+
const reg = self.register !== undefined && self.register !== null ? String(self.register) : ''
|
|
41
|
+
const sch = self.schema !== undefined && self.schema !== null ? String(self.schema) : ''
|
|
42
|
+
if (!reg || !sch) {
|
|
43
|
+
return null
|
|
44
|
+
}
|
|
45
|
+
const idsOf = (...values) => values.filter((v) => v !== undefined && v !== null && v !== '').map(String)
|
|
46
|
+
const schemaIds = idsOf(schema, primarySchema && primarySchema.id, primarySchema && primarySchema.slug)
|
|
47
|
+
const registerIds = idsOf(register, primaryRegister && primaryRegister.id, primaryRegister && primaryRegister.slug)
|
|
48
|
+
if (schemaIds.includes(sch) && registerIds.includes(reg)) {
|
|
49
|
+
return null
|
|
50
|
+
}
|
|
51
|
+
const type = `${reg}-${sch}`
|
|
52
|
+
if (!store.objectTypeRegistry?.[type]) {
|
|
53
|
+
store.registerObjectType(type, sch, reg, { registerSlug: reg, schemaSlug: sch })
|
|
54
|
+
}
|
|
55
|
+
return { register: reg, schema: sch, type }
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* The store type a row is written through: its own pair's, or the page's.
|
|
60
|
+
*
|
|
61
|
+
* @param {object} ctx Accessor closures.
|
|
62
|
+
* @param {object} [row] The row.
|
|
63
|
+
* @return {string} The type slug.
|
|
64
|
+
*/
|
|
65
|
+
function typeFor(ctx, row) {
|
|
66
|
+
const target = row && typeof ctx.rowTarget === 'function' ? ctx.rowTarget(row) : null
|
|
67
|
+
return target ? target.type : ctx.selfObjectType()
|
|
16
68
|
}
|
|
17
69
|
|
|
18
70
|
/**
|
|
@@ -25,6 +77,10 @@ function findSource(ctx, id) {
|
|
|
25
77
|
*/
|
|
26
78
|
function copyAddress(ctx, source) {
|
|
27
79
|
const self = source['@self'] || {}
|
|
80
|
+
const target = typeof ctx.rowTarget === 'function' ? ctx.rowTarget(source) : null
|
|
81
|
+
if (target) {
|
|
82
|
+
return { register: target.register, schema: target.schema, id: String(source.id || self.id) }
|
|
83
|
+
}
|
|
28
84
|
const reg = ctx.register()
|
|
29
85
|
const sch = ctx.schema()
|
|
30
86
|
const register = (typeof reg === 'string' && reg) || self.register
|
|
@@ -54,12 +110,12 @@ function refreshList(ctx) {
|
|
|
54
110
|
}
|
|
55
111
|
}
|
|
56
112
|
|
|
57
|
-
function storeError(ctx) {
|
|
58
|
-
return ctx.selfObjectStore()?.getError?.(
|
|
113
|
+
function storeError(ctx, type = ctx.selfObjectType()) {
|
|
114
|
+
return ctx.selfObjectStore()?.getError?.(type)
|
|
59
115
|
}
|
|
60
116
|
|
|
61
|
-
function storeErrorMessage(ctx, fallback) {
|
|
62
|
-
const err = storeError(ctx)
|
|
117
|
+
function storeErrorMessage(ctx, fallback, type) {
|
|
118
|
+
const err = storeError(ctx, type)
|
|
63
119
|
return (err && err.message) || fallback
|
|
64
120
|
}
|
|
65
121
|
|
|
@@ -76,13 +132,14 @@ export function createSelfModeActions(ctx) {
|
|
|
76
132
|
return false
|
|
77
133
|
}
|
|
78
134
|
try {
|
|
79
|
-
const
|
|
135
|
+
const type = typeFor(ctx, findSource(ctx, id))
|
|
136
|
+
const ok = await ctx.selfObjectStore().deleteObject(type, id)
|
|
80
137
|
if (ok) {
|
|
81
138
|
ctx.setResults.singleDelete({ success: true })
|
|
82
139
|
ctx.emit('delete', id)
|
|
83
140
|
refreshList(ctx)
|
|
84
141
|
} else {
|
|
85
|
-
ctx.setResults.singleDelete({ error: storeErrorMessage(ctx, 'Delete failed') })
|
|
142
|
+
ctx.setResults.singleDelete({ error: storeErrorMessage(ctx, 'Delete failed', type) })
|
|
86
143
|
}
|
|
87
144
|
} catch (err) {
|
|
88
145
|
ctx.setResults.singleDelete({ error: (err && err.message) || 'Delete failed' })
|
|
@@ -95,12 +152,28 @@ export function createSelfModeActions(ctx) {
|
|
|
95
152
|
return false
|
|
96
153
|
}
|
|
97
154
|
try {
|
|
98
|
-
|
|
155
|
+
// One request per pair: a mixed list holds rows of several types.
|
|
156
|
+
const idsByType = new Map()
|
|
157
|
+
for (const id of ids) {
|
|
158
|
+
const type = typeFor(ctx, findSource(ctx, id))
|
|
159
|
+
idsByType.set(type, [...(idsByType.get(type) || []), id])
|
|
160
|
+
}
|
|
161
|
+
const successfulIds = []
|
|
162
|
+
const failedIds = []
|
|
163
|
+
let failedType = null
|
|
164
|
+
for (const [type, typeIds] of idsByType) {
|
|
165
|
+
const outcome = await ctx.selfObjectStore().deleteObjects(type, typeIds)
|
|
166
|
+
successfulIds.push(...outcome.successfulIds)
|
|
167
|
+
failedIds.push(...outcome.failedIds)
|
|
168
|
+
if (outcome.failedIds.length > 0 && failedType === null) {
|
|
169
|
+
failedType = type
|
|
170
|
+
}
|
|
171
|
+
}
|
|
99
172
|
if (failedIds.length === 0) {
|
|
100
173
|
ctx.setResults.massDelete({ success: true, successfulIds })
|
|
101
174
|
} else {
|
|
102
175
|
ctx.setResults.massDelete({
|
|
103
|
-
error: storeErrorMessage(ctx, `Failed to delete ${failedIds.length} item(s)
|
|
176
|
+
error: storeErrorMessage(ctx, `Failed to delete ${failedIds.length} item(s)`, failedType),
|
|
104
177
|
successfulIds,
|
|
105
178
|
failedIds,
|
|
106
179
|
})
|
|
@@ -142,13 +215,14 @@ export function createSelfModeActions(ctx) {
|
|
|
142
215
|
}
|
|
143
216
|
}
|
|
144
217
|
const clone = cloneObjectForCopy(source, newName, resolveNameField(ctx))
|
|
145
|
-
const
|
|
218
|
+
const type = typeFor(ctx, source)
|
|
219
|
+
const saved = await ctx.selfObjectStore().saveObject(type, clone)
|
|
146
220
|
if (saved) {
|
|
147
221
|
ctx.setResults.singleCopy({ success: true })
|
|
148
222
|
ctx.emit('copy', payload)
|
|
149
223
|
refreshList(ctx)
|
|
150
224
|
} else {
|
|
151
|
-
ctx.setResults.singleCopy({ error: storeErrorMessage(ctx, 'Copy failed') })
|
|
225
|
+
ctx.setResults.singleCopy({ error: storeErrorMessage(ctx, 'Copy failed', type) })
|
|
152
226
|
}
|
|
153
227
|
} catch (err) {
|
|
154
228
|
ctx.setResults.singleCopy({ error: (err && err.message) || 'Copy failed' })
|
|
@@ -191,7 +265,7 @@ export function createSelfModeActions(ctx) {
|
|
|
191
265
|
}
|
|
192
266
|
const clone = cloneObjectForCopy(source, getName(source), nameField)
|
|
193
267
|
try {
|
|
194
|
-
const saved = await ctx.selfObjectStore().saveObject(ctx
|
|
268
|
+
const saved = await ctx.selfObjectStore().saveObject(typeFor(ctx, source), clone)
|
|
195
269
|
if (saved) {
|
|
196
270
|
successfulIds.push(id)
|
|
197
271
|
} else {
|
|
@@ -261,7 +335,9 @@ export function createSelfModeActions(ctx) {
|
|
|
261
335
|
return false
|
|
262
336
|
}
|
|
263
337
|
try {
|
|
264
|
-
const
|
|
338
|
+
const item = ctx.editItem()
|
|
339
|
+
const type = item ? typeFor(ctx, item) : ctx.selfObjectType()
|
|
340
|
+
const saved = await ctx.selfObjectStore().saveObject(type, formData)
|
|
265
341
|
if (saved) {
|
|
266
342
|
ctx.setResults.form({ success: true })
|
|
267
343
|
const isCreate = !ctx.editItem()
|
|
@@ -277,7 +353,7 @@ export function createSelfModeActions(ctx) {
|
|
|
277
353
|
ctx.afterCreateSuccess(saved)
|
|
278
354
|
}
|
|
279
355
|
} else {
|
|
280
|
-
const err = storeError(ctx)
|
|
356
|
+
const err = storeError(ctx, type)
|
|
281
357
|
if (err && err.isValidation) {
|
|
282
358
|
// Keep the form visible so the user can fix the invalid data.
|
|
283
359
|
ctx.setResults.formValidation(err.fields, err.message || 'Validation failed')
|
|
@@ -106,7 +106,11 @@ export function useSelfFetchList(props, instance, inject, extras = {}) {
|
|
|
106
106
|
const register = folder.register || props.register
|
|
107
107
|
return { register, schema: folder.schema, type: `${register}-${folder.schema}` }
|
|
108
108
|
}
|
|
109
|
-
|
|
109
|
+
// A collection endpoint gets its own type key, so a plain registration of
|
|
110
|
+
// the same pair elsewhere never resets it.
|
|
111
|
+
const collectionUrl = props.collectionUrl || ''
|
|
112
|
+
const type = `${props.register}-${props.schema}` + (collectionUrl ? `@${collectionUrl}` : '')
|
|
113
|
+
return { register: props.register, schema: props.schema, type, collectionUrl }
|
|
110
114
|
})
|
|
111
115
|
const objectType = computed(() => resolvedTarget.value.type)
|
|
112
116
|
const sidebarState = inject('sidebarState', null) ?? inject('objectSidebarState', null)
|
|
@@ -155,9 +159,17 @@ export function useSelfFetchList(props, instance, inject, extras = {}) {
|
|
|
155
159
|
// second arg) — that previously made fetch URLs go to `/api/objects/undefined/[object Object]`.
|
|
156
160
|
// Runs (sync, ahead of the list's own watcher) again whenever the type switches.
|
|
157
161
|
function registerTarget() {
|
|
158
|
-
const { register, schema, type } = resolvedTarget.value
|
|
162
|
+
const { register, schema, type, collectionUrl } = resolvedTarget.value
|
|
159
163
|
if (typeof objectStore.registerObjectType === 'function') {
|
|
160
|
-
objectStore.registerObjectType(type, schema, register, {
|
|
164
|
+
objectStore.registerObjectType(type, schema, register, {
|
|
165
|
+
registerSlug: register,
|
|
166
|
+
schemaSlug: schema,
|
|
167
|
+
...(collectionUrl ? { collectionUrl } : {}),
|
|
168
|
+
})
|
|
169
|
+
}
|
|
170
|
+
// A mixed list tells its own rows apart by `@self.register`, an id, so a slug register needs resolving.
|
|
171
|
+
if (collectionUrl && !/^\d+$/.test(String(register)) && typeof objectStore.fetchRegister === 'function') {
|
|
172
|
+
objectStore.fetchRegister(type)
|
|
161
173
|
}
|
|
162
174
|
}
|
|
163
175
|
registerTarget()
|
|
@@ -137,6 +137,7 @@ export default {
|
|
|
137
137
|
| Prop | Type | Default | Description |
|
|
138
138
|
|---|---|---|---|
|
|
139
139
|
| `maxMetadata` | `Number` | `4` | Maximum number of schema properties to show in the metadata section. Properties are sorted by their `order` value before slicing |
|
|
140
|
+
| `accent` | `Object` | `null` | Status accent `{ variant, icon?, label? }`: a colored start border and, with `icon`, a colored icon before the title. `variant` is `success`, `warning`, `error`, `info` or `primary`; `label` is the icon's tooltip and accessible name |
|
|
140
141
|
|
|
141
142
|
## Slots
|
|
142
143
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div
|
|
3
3
|
class="cn-object-card"
|
|
4
|
-
:class="{ 'cn-object-card--selected': selected, 'cn-object-card--board': isBoardLook }"
|
|
4
|
+
:class="[{ 'cn-object-card--selected': selected, 'cn-object-card--board': isBoardLook }, accentVariant && ['cn-object-card--accent', `cn-object-card--accent-${accentVariant}`]]"
|
|
5
5
|
@mousedown="onCardMouseDown"
|
|
6
6
|
@click="onCardClick($event)"
|
|
7
7
|
@auxclick="onCardAuxClick($event)">
|
|
@@ -42,6 +42,16 @@
|
|
|
42
42
|
to report. A card whose consumer passes no badges
|
|
43
43
|
would otherwise show no padlock at all. -->
|
|
44
44
|
<CnLockIndicator :object="object" :size="16" />
|
|
45
|
+
<span
|
|
46
|
+
v-if="accentVariant && accent.icon"
|
|
47
|
+
class="cn-object-card__accent-icon"
|
|
48
|
+
data-testid="cn-object-card-accent-icon"
|
|
49
|
+
:role="accent.label ? 'img' : null"
|
|
50
|
+
:aria-label="accent.label || null"
|
|
51
|
+
:aria-hidden="accent.label ? null : 'true'"
|
|
52
|
+
:title="accent.label || null">
|
|
53
|
+
<CnIcon :name="accent.icon" :size="16" />
|
|
54
|
+
</span>
|
|
45
55
|
{{ title }}
|
|
46
56
|
</h3>
|
|
47
57
|
<p v-if="description" class="cn-object-card__description">
|
|
@@ -128,6 +138,8 @@ import { CnIcon } from '../CnIcon/index.js'
|
|
|
128
138
|
import { CnLockIndicator } from '../CnLockIndicator/index.js'
|
|
129
139
|
import { CnStatusBadge } from '../CnStatusBadge/index.js'
|
|
130
140
|
|
|
141
|
+
const ACCENT_VARIANTS = ['success', 'warning', 'error', 'info', 'primary']
|
|
142
|
+
|
|
131
143
|
/**
|
|
132
144
|
* CnObjectCard — Schema-configuration-driven card for object display.
|
|
133
145
|
*
|
|
@@ -244,6 +256,20 @@ export default {
|
|
|
244
256
|
default: null,
|
|
245
257
|
},
|
|
246
258
|
|
|
259
|
+
/**
|
|
260
|
+
* A status accent: a colored border at the start of the card and,
|
|
261
|
+
* with `icon`, a colored icon before the title. `variant` is one of
|
|
262
|
+
* `success`, `warning`, `error`, `info` or `primary`; `icon` is a
|
|
263
|
+
* name registered with CnIcon; `label` names the status for screen
|
|
264
|
+
* readers and as the icon's tooltip.
|
|
265
|
+
*
|
|
266
|
+
* @type {{variant: string, icon?: string, label?: string}}
|
|
267
|
+
*/
|
|
268
|
+
accent: {
|
|
269
|
+
type: Object,
|
|
270
|
+
default: null,
|
|
271
|
+
},
|
|
272
|
+
|
|
247
273
|
/**
|
|
248
274
|
* The property keys the facts list shows, in order (manifest key
|
|
249
275
|
* `config.cardFields`). Without it the card shows the first
|
|
@@ -307,6 +333,16 @@ export default {
|
|
|
307
333
|
return null
|
|
308
334
|
},
|
|
309
335
|
|
|
336
|
+
/**
|
|
337
|
+
* The accent variant when it is a known one, else ''.
|
|
338
|
+
*
|
|
339
|
+
* @return {string}
|
|
340
|
+
*/
|
|
341
|
+
accentVariant() {
|
|
342
|
+
const variant = this.accent?.variant
|
|
343
|
+
return ACCENT_VARIANTS.includes(variant) ? variant : ''
|
|
344
|
+
},
|
|
345
|
+
|
|
310
346
|
config() {
|
|
311
347
|
return this.schema?.configuration || {}
|
|
312
348
|
},
|
|
@@ -502,6 +538,58 @@ export default {
|
|
|
502
538
|
background: var(--color-primary-element-light);
|
|
503
539
|
}
|
|
504
540
|
|
|
541
|
+
/* The 4px start border takes 3px of padding, so the content stays put. */
|
|
542
|
+
.cn-object-card.cn-object-card--accent {
|
|
543
|
+
border-inline-start-width: 4px;
|
|
544
|
+
padding-inline-start: 13px;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
.cn-object-card.cn-object-card--accent-success {
|
|
548
|
+
border-inline-start-color: var(--color-element-success);
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
.cn-object-card.cn-object-card--accent-warning {
|
|
552
|
+
border-inline-start-color: var(--color-element-warning);
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
.cn-object-card.cn-object-card--accent-error {
|
|
556
|
+
border-inline-start-color: var(--color-element-error);
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
.cn-object-card.cn-object-card--accent-info {
|
|
560
|
+
border-inline-start-color: var(--color-element-info);
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
.cn-object-card.cn-object-card--accent-primary {
|
|
564
|
+
border-inline-start-color: var(--color-primary-element);
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
.cn-object-card__accent-icon {
|
|
568
|
+
display: inline-flex;
|
|
569
|
+
vertical-align: -2px;
|
|
570
|
+
margin-inline-end: 4px;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
.cn-object-card--accent-success .cn-object-card__accent-icon {
|
|
574
|
+
color: var(--color-text-success);
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
.cn-object-card--accent-warning .cn-object-card__accent-icon {
|
|
578
|
+
color: var(--color-text-warning);
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
.cn-object-card--accent-error .cn-object-card__accent-icon {
|
|
582
|
+
color: var(--color-text-error);
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
.cn-object-card--accent-info .cn-object-card__accent-icon {
|
|
586
|
+
color: var(--color-element-info);
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
.cn-object-card--accent-primary .cn-object-card__accent-icon {
|
|
590
|
+
color: var(--color-primary-element);
|
|
591
|
+
}
|
|
592
|
+
|
|
505
593
|
.cn-object-card__checkbox {
|
|
506
594
|
flex-shrink: 0;
|
|
507
595
|
padding-top: 2px;
|