@conduction/nextcloud-vue 2.103.0 → 2.105.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/CnActionsBar/CnActionsBar.vue2.js +23 -0
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue2.js.map +1 -1
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js +94 -72
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js.map +1 -1
- package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue.js +1 -1
- package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue2.js.map +1 -1
- package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue3.js +1 -1
- package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue3.js.map +1 -1
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js +18 -1
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js.map +1 -1
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js +3 -3
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js.map +1 -1
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue.js +1 -1
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue2.js +93 -1
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue.js +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +6 -3
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js +3 -3
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js +39 -2
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js +14 -0
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +99 -3
- 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/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue.js +1 -1
- package/dist/esm/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue2.js +1 -1
- package/dist/esm/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue2.js.map +1 -1
- package/dist/esm/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue3.js.map +1 -1
- package/dist/esm/components/CnFeaturesBoard/CnFeaturesBoard.vue.js +1 -1
- package/dist/esm/components/CnFeaturesBoard/CnFeaturesBoard.vue2.js +2 -0
- package/dist/esm/components/CnFeaturesBoard/CnFeaturesBoard.vue2.js.map +1 -1
- package/dist/esm/components/CnFeaturesBoard/CnFeaturesBoard.vue3.js +32 -29
- package/dist/esm/components/CnFeaturesBoard/CnFeaturesBoard.vue3.js.map +1 -1
- package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue.js +1 -1
- package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue2.js +73 -4
- package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue2.js.map +1 -1
- package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue3.js +74 -27
- package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +213 -4
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +105 -85
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/useSelfFetchList.js +10 -4
- package/dist/esm/components/CnIndexPage/useSelfFetchList.js.map +1 -1
- package/dist/esm/components/CnNoticeWidget/CnNoticeWidget.vue.js +9 -0
- package/dist/esm/components/CnNoticeWidget/CnNoticeWidget.vue.js.map +1 -0
- package/dist/esm/components/CnNoticeWidget/CnNoticeWidget.vue2.js +88 -0
- package/dist/esm/components/CnNoticeWidget/CnNoticeWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnNoticeWidget/CnNoticeWidget.vue3.js +39 -0
- package/dist/esm/components/CnNoticeWidget/CnNoticeWidget.vue3.js.map +1 -0
- package/dist/esm/components/CnObjectRow/CnObjectRow.vue.js +1 -1
- package/dist/esm/components/CnObjectRow/CnObjectRow.vue2.js +57 -5
- package/dist/esm/components/CnObjectRow/CnObjectRow.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectRow/CnObjectRow.vue3.js +37 -4
- package/dist/esm/components/CnObjectRow/CnObjectRow.vue3.js.map +1 -1
- package/dist/esm/components/CnSettingsField/CnSettingsField.vue.js +1 -1
- package/dist/esm/components/CnSettingsField/CnSettingsField.vue2.js.map +1 -1
- package/dist/esm/components/CnSettingsField/CnSettingsField.vue3.js +3 -3
- package/dist/esm/components/CnSettingsField/CnSettingsField.vue3.js.map +1 -1
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue.js +1 -1
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue2.js.map +1 -1
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue3.js +16 -4
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue3.js.map +1 -1
- package/dist/esm/components/CnUserSettingsDialog/CnUserSettingsDialog.vue.js +1 -1
- package/dist/esm/components/CnUserSettingsDialog/CnUserSettingsDialog.vue2.js.map +1 -1
- package/dist/esm/components/CnUserSettingsDialog/CnUserSettingsDialog.vue3.js.map +1 -1
- package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue.js +1 -1
- package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue2.js +11 -0
- package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue2.js.map +1 -1
- package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue3.js +4 -4
- package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue3.js.map +1 -1
- package/dist/esm/components/CnWidgetGrid/builtInWidgets.js +16 -14
- package/dist/esm/components/CnWidgetGrid/builtInWidgets.js.map +1 -1
- package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue.js +1 -1
- package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js +18 -2
- package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js.map +1 -1
- package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue3.js.map +1 -1
- package/dist/esm/composables/indexSources.js +7 -7
- package/dist/esm/composables/indexSources.js.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/l10n/en.json.js +8 -1
- package/dist/esm/l10n/en.json.js.map +1 -1
- package/dist/esm/l10n/nl.json.js +8 -1
- package/dist/esm/l10n/nl.json.js.map +1 -1
- package/dist/esm/library-style.js +1 -1
- package/dist/esm/nextcloud-vue.css +680 -328
- package/dist/esm/utils/libraryWidgetKeys.js +1 -0
- package/dist/esm/utils/libraryWidgetKeys.js.map +1 -1
- package/dist/esm/utils/nextcloudApps.js +45 -0
- package/dist/esm/utils/nextcloudApps.js.map +1 -0
- package/dist/esm/utils/nextcloudDirectory.js +18 -1
- package/dist/esm/utils/nextcloudDirectory.js.map +1 -1
- package/dist/esm/utils/scopeListLayout.js +9 -2
- package/dist/esm/utils/scopeListLayout.js.map +1 -1
- package/dist/esm/utils/sortOrder.js +61 -0
- package/dist/esm/utils/sortOrder.js.map +1 -0
- package/dist/esm/utils/validateManifestV2.compiled.js +3 -3
- package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
- package/dist/esm/utils/visibleWhen.js +12 -4
- package/dist/esm/utils/visibleWhen.js.map +1 -1
- package/dist/nextcloud-vue.cjs.js +4046 -2999
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +680 -328
- package/l10n/en.json +8 -1
- package/l10n/nl.json +8 -1
- package/package.json +1 -1
- package/src/components/CnActionsBar/CnActionsBar.md +1 -0
- package/src/components/CnActionsBar/CnActionsBar.vue +39 -2
- package/src/components/CnAdminSettingsShell/CnAdminSettingsShell.vue +1 -1
- package/src/components/CnAppRoot/CnAppRoot.md +1 -1
- package/src/components/CnAppRoot/CnAppRoot.vue +21 -4
- package/src/components/CnChartWidget/CnChartWidget.md +2 -0
- package/src/components/CnChartWidget/CnChartWidget.vue +93 -1
- package/src/components/CnDashboardPage/CnDashboardPage.vue +9 -6
- package/src/components/CnDataTable/CnDataTable.md +1 -0
- package/src/components/CnDataTable/CnDataTable.vue +49 -0
- package/src/components/CnDetailPage/CnDetailPage.md +2 -0
- package/src/components/CnDetailPage/CnDetailPage.vue +99 -3
- package/src/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue +1 -1
- package/src/components/CnFeaturesBoard/CnFeaturesBoard.vue +4 -1
- package/src/components/CnFlowsPage/CnFlowBoard.vue +132 -8
- package/src/components/CnIndexPage/CnIndexPage.md +5 -2
- package/src/components/CnIndexPage/CnIndexPage.vue +228 -9
- package/src/components/CnIndexPage/useSelfFetchList.js +9 -3
- package/src/components/CnNoticeWidget/CnNoticeWidget.vue +153 -0
- package/src/components/CnNoticeWidget/index.js +12 -0
- package/src/components/CnObjectRow/CnObjectRow.vue +95 -1
- package/src/components/CnSettingsField/CnSettingsField.vue +4 -1
- package/src/components/CnSetupWizard/CnSetupWizard.vue +9 -1
- package/src/components/CnUserSettingsDialog/CnUserSettingsDialog.vue +7 -2
- package/src/components/CnVersionInfoCard/CnVersionInfoCard.vue +15 -4
- package/src/components/CnWidgetGrid/builtInWidgets.js +2 -0
- package/src/components/CnWidgetObjectTable/CnWidgetObjectTable.vue +18 -2
- package/src/components/index.js +1 -0
- package/src/composables/indexSources.js +7 -7
- package/src/css/dialog.css +20 -2
- package/src/css/index-page.css +19 -0
- package/src/css/look-board-detail.css +77 -4
- package/src/css/look-board-index.css +84 -2
- package/src/css/look-board.css +97 -12
- package/src/index.js +1 -0
- package/src/schemas/app-manifest-v2.schema.json +58 -3
- package/src/utils/libraryWidgetKeys.js +1 -0
- package/src/utils/nextcloudApps.js +50 -0
- package/src/utils/nextcloudDirectory.js +17 -0
- package/src/utils/scopeListLayout.js +9 -2
- package/src/utils/sortOrder.js +58 -0
- package/src/utils/validateManifestV2.compiled.js +3 -3
- package/src/utils/visibleWhen.js +12 -4
|
@@ -191,8 +191,9 @@
|
|
|
191
191
|
:listIcon="listIcon"
|
|
192
192
|
:showSortSelect="showSortSelect"
|
|
193
193
|
:sortOptions="sortSelectOptions"
|
|
194
|
-
:sortValue="
|
|
195
|
-
:showSearch="inlineSearch || isBoardLook"
|
|
194
|
+
:sortValue="effectiveSortSelectValue"
|
|
195
|
+
:showSearch="search !== false && (inlineSearch || isBoardLook)"
|
|
196
|
+
:searchPlacement="searchPlacement"
|
|
196
197
|
:searchValue="effectiveSearchValue"
|
|
197
198
|
:searchPlaceholder="presented('searchPlaceholder') ? cnTranslate(presented('searchPlaceholder')) : presented('searchPlaceholder')"
|
|
198
199
|
:showCountWithSearch="showCountWithSearch"
|
|
@@ -209,7 +210,7 @@
|
|
|
209
210
|
:bulkActions="mergedBulkActions"
|
|
210
211
|
:documentationUrl="documentationUrl"
|
|
211
212
|
:documentationLabel="documentationLabel || undefined"
|
|
212
|
-
@sortChange="
|
|
213
|
+
@sortChange="onSortSelectChange"
|
|
213
214
|
@add="onAddClick"
|
|
214
215
|
@clearSelection="onSelect([])"
|
|
215
216
|
@removeFilter="onRemoveActiveFilter"
|
|
@@ -675,8 +676,8 @@
|
|
|
675
676
|
:partial="folderSidebarPartial"
|
|
676
677
|
:filesPath="folderSidebar.filesPath || '/'"
|
|
677
678
|
:selectedId="selectedFolderId"
|
|
678
|
-
:allLabel="folderSidebar.allLabel
|
|
679
|
-
:title="folderSidebar.title
|
|
679
|
+
:allLabel="folderSidebar.allLabel ? cnTranslate(folderSidebar.allLabel) : undefined"
|
|
680
|
+
:title="folderSidebar.title ? cnTranslate(folderSidebar.title) : ''"
|
|
680
681
|
:idField="folderPassthroughIdField"
|
|
681
682
|
:nameField="folderPassthroughNameField"
|
|
682
683
|
:allowCreate="Boolean(folderSidebar.allowCreate)"
|
|
@@ -701,6 +702,15 @@
|
|
|
701
702
|
<!-- @slot before-collection Content rendered above the collection in EVERY view mode (table, cards, list, map) — e.g. a folder/group strip that must stay visually separate from the objects instead of masquerading as rows or cards. -->
|
|
702
703
|
<slot name="before-collection" />
|
|
703
704
|
|
|
705
|
+
<!-- The selected folder as a heading above the list (a group on
|
|
706
|
+
DqAfdelingen: its name, then its parent and member count). -->
|
|
707
|
+
<div v-if="scopeHeading" class="cn-index-page__scope-heading" data-testid="cn-index-page-scope-heading">
|
|
708
|
+
<h2 class="cn-index-page__scope-title">
|
|
709
|
+
{{ scopeHeading.name }}
|
|
710
|
+
</h2>
|
|
711
|
+
<span v-if="scopeHeading.subtitle" class="cn-index-page__scope-subtitle" data-testid="cn-index-page-scope-subtitle">{{ scopeHeading.subtitle }}</span>
|
|
712
|
+
</div>
|
|
713
|
+
|
|
704
714
|
<!-- Loading state — initial fetch only; a background refresh keeps the table visible -->
|
|
705
715
|
<div v-if="showInitialLoader" class="cn-index-page__loading">
|
|
706
716
|
<!-- name gives NcLoadingIcon a non-empty aria-label (WCAG role-img-alt); empty name ships an unlabeled role="img" -->
|
|
@@ -1278,6 +1288,7 @@ import {
|
|
|
1278
1288
|
import { reportBindingProblems } from '../../utils/diagnostics.js'
|
|
1279
1289
|
import { fetchGroupedCounts } from '../../utils/fetchAggregate.js'
|
|
1280
1290
|
import { fetchFilterCounts, fetchListTotal } from '../../utils/fetchFilterCounts.js'
|
|
1291
|
+
import { unwrapAppConfig } from '../../utils/formatMetric.js'
|
|
1281
1292
|
import { buildExportUrl } from '../../utils/indexExportHelpers.js'
|
|
1282
1293
|
import { lensUnavailableText } from '../../utils/lensAvailability.js'
|
|
1283
1294
|
import { isModifiedClick, openRowTarget } from '../../utils/linkNavigation.js'
|
|
@@ -1300,6 +1311,7 @@ import { DEFAULT_ROW_INDICATOR_CAP } from '../../utils/rowIndicators.js'
|
|
|
1300
1311
|
import { buildRouteQueryFromViewState, buildViewCreatePayload, extractViewState, extractViewStateFromRouteQuery, normalizeSharedWith, savedViewScope, viewMatchesScope } from '../../utils/savedViewHelpers.js'
|
|
1301
1312
|
import { columnsFromSchema, fieldsFromSchema } from '../../utils/schema.js'
|
|
1302
1313
|
import { resolveScopeLayout, resolveScopePresentation } from '../../utils/scopeListLayout.js'
|
|
1314
|
+
import { orderToSortKeys, sameSortKeys } from '../../utils/sortOrder.js'
|
|
1303
1315
|
import { dispatchObjectCreated } from '../../utils/walkthroughSignals.js'
|
|
1304
1316
|
import { CnActionButtons } from '../CnActionButtons/index.js'
|
|
1305
1317
|
import { CnActionsBar } from '../CnActionsBar/index.js'
|
|
@@ -1666,6 +1678,8 @@ export default {
|
|
|
1666
1678
|
cnCustomComponents: { default: () => ({}) },
|
|
1667
1679
|
/** The permissions the user holds, provided by CnAppRoot; for gated page tabs. */
|
|
1668
1680
|
cnPermissions: { default: () => [] },
|
|
1681
|
+
/** The app config an ancestor provides, for `@config.<key>` in quick-filter labels. */
|
|
1682
|
+
cnAppConfig: { default: null },
|
|
1669
1683
|
/** The app id CnAppRoot provides, for the plural form of `countSubtitle`. */
|
|
1670
1684
|
cnAppId: { default: '' },
|
|
1671
1685
|
/**
|
|
@@ -1969,7 +1983,10 @@ export default {
|
|
|
1969
1983
|
* case" (manifest `config.headerButtons`). Each is `{ label?, action,
|
|
1970
1984
|
* variant?, icon?, format?, id? }`: `action` is `add` (the Add flow;
|
|
1971
1985
|
* its label defaults to the Add label), `export` (the export leaf in
|
|
1972
|
-
* `format`, `csv` by default, else the export dialog
|
|
1986
|
+
* `format`, `csv` by default, else the export dialog; with `run` the
|
|
1987
|
+
* `headerActions` entry of that id; on an `entitySource` page without
|
|
1988
|
+
* `run` and without a `@mass-export` listener it is not drawn),
|
|
1989
|
+
* `import`,
|
|
1973
1990
|
* `refresh`, `save-view` (the save-current-view dialog: the board's
|
|
1974
1991
|
* "Zoekopdracht opslaan", label "Save view" by default), or the id of a
|
|
1975
1992
|
* `headerActions` entry; `variant` is
|
|
@@ -2149,6 +2166,20 @@ export default {
|
|
|
2149
2166
|
validator: (v) => ['', 'toolbar'].includes(v),
|
|
2150
2167
|
},
|
|
2151
2168
|
|
|
2169
|
+
/**
|
|
2170
|
+
* Where the board look's search field sits (manifest
|
|
2171
|
+
* `config.searchPlacement`): `''` (the default) opens row 2 with it,
|
|
2172
|
+
* `'toolbar'` puts it on row 1 before the Filter button and the view
|
|
2173
|
+
* switch (DqTeamwachtrij).
|
|
2174
|
+
*
|
|
2175
|
+
* @type {''|'toolbar'}
|
|
2176
|
+
*/
|
|
2177
|
+
searchPlacement: {
|
|
2178
|
+
type: String,
|
|
2179
|
+
default: '',
|
|
2180
|
+
validator: (v) => ['', 'toolbar'].includes(v),
|
|
2181
|
+
},
|
|
2182
|
+
|
|
2152
2183
|
/**
|
|
2153
2184
|
* How the quick filters render: `'chips'` (pill strip, default) or
|
|
2154
2185
|
* `'dropdown'` (a single `NcSelect`). Sourced from the manifest as
|
|
@@ -3095,6 +3126,29 @@ export default {
|
|
|
3095
3126
|
default: false,
|
|
3096
3127
|
},
|
|
3097
3128
|
|
|
3129
|
+
/**
|
|
3130
|
+
* `false` draws no inline search in the actions bar, also in the board
|
|
3131
|
+
* look, which otherwise draws one on every index page. Fed from the
|
|
3132
|
+
* manifest as `pages[].config.search`.
|
|
3133
|
+
*/
|
|
3134
|
+
search: {
|
|
3135
|
+
type: Boolean,
|
|
3136
|
+
default: true,
|
|
3137
|
+
},
|
|
3138
|
+
|
|
3139
|
+
/**
|
|
3140
|
+
* The app config `@config.<key>` tokens resolve against, in quick-filter
|
|
3141
|
+
* filters and labels (`"Residence @config.municipality"`), as on the
|
|
3142
|
+
* dashboard and detail pages. Merged over a config an ancestor provides
|
|
3143
|
+
* on `cnAppConfig`. Manifest: `config.appConfig`.
|
|
3144
|
+
*
|
|
3145
|
+
* @type {object}
|
|
3146
|
+
*/
|
|
3147
|
+
appConfig: {
|
|
3148
|
+
type: Object,
|
|
3149
|
+
default: () => ({}),
|
|
3150
|
+
},
|
|
3151
|
+
|
|
3098
3152
|
/**
|
|
3099
3153
|
* Keep the "Showing X of Y" counter visible beside the inline search field,
|
|
3100
3154
|
* after any `#after-search` controls (only relevant with `inlineSearch`,
|
|
@@ -3162,12 +3216,28 @@ export default {
|
|
|
3162
3216
|
default: () => [],
|
|
3163
3217
|
},
|
|
3164
3218
|
|
|
3165
|
-
/**
|
|
3219
|
+
/**
|
|
3220
|
+
* Selected value of the standalone sort dropdown. Empty lets a
|
|
3221
|
+
* self-fetch page show the option matching its current order.
|
|
3222
|
+
*/
|
|
3166
3223
|
sortSelectValue: {
|
|
3167
3224
|
type: String,
|
|
3168
3225
|
default: '',
|
|
3169
3226
|
},
|
|
3170
3227
|
|
|
3228
|
+
/**
|
|
3229
|
+
* The order a self-fetch page opens on when neither the address nor
|
|
3230
|
+
* `sortKeys`/`sortKey` gives one (manifest `config.defaultOrder`):
|
|
3231
|
+
* `"-createdAt"`, `"priority:desc,title"`, an `_order` map or a
|
|
3232
|
+
* `[{ key, order }]` list.
|
|
3233
|
+
*
|
|
3234
|
+
* @type {string|object|Array}
|
|
3235
|
+
*/
|
|
3236
|
+
defaultOrder: {
|
|
3237
|
+
type: [String, Object, Array],
|
|
3238
|
+
default: '',
|
|
3239
|
+
},
|
|
3240
|
+
|
|
3171
3241
|
/** MDI icon name for the list view-toggle option (manifest `config.listIcon`) */
|
|
3172
3242
|
listIcon: {
|
|
3173
3243
|
type: String,
|
|
@@ -4896,6 +4966,60 @@ export default {
|
|
|
4896
4966
|
return match || null
|
|
4897
4967
|
},
|
|
4898
4968
|
|
|
4969
|
+
/**
|
|
4970
|
+
* The heading above the list for the selected folder: on a `groups`
|
|
4971
|
+
* pane (or with `folderSidebar.heading: true`), its name and, under
|
|
4972
|
+
* it, its parent folder and its count. The count reads
|
|
4973
|
+
* `folderSidebar.countText` (`{count}`, through the app's translate),
|
|
4974
|
+
* else "{count} members" on a groups pane.
|
|
4975
|
+
*
|
|
4976
|
+
* @return {{name: string, subtitle: string}|null} The heading, or null on All.
|
|
4977
|
+
*/
|
|
4978
|
+
scopeHeading() {
|
|
4979
|
+
const cfg = this.folderSidebar
|
|
4980
|
+
const scope = this.activeScope
|
|
4981
|
+
if (!cfg || !scope || !(cfg.source === 'groups' || cfg.heading === true)) {
|
|
4982
|
+
return null
|
|
4983
|
+
}
|
|
4984
|
+
const idField = this.folderPassthroughIdField
|
|
4985
|
+
const name = String(this.getByPath(scope, this.folderPassthroughNameField) ?? this.selectedFolderId)
|
|
4986
|
+
const parentId = scope.parentId ?? scope.parent ?? null
|
|
4987
|
+
const parent = parentId === null || parentId === undefined
|
|
4988
|
+
? null
|
|
4989
|
+
: this.folderSidebarFolders.find((f) => f && String(this.getByPath(f, idField)) === String(parentId))
|
|
4990
|
+
const parts = []
|
|
4991
|
+
if (parent) {
|
|
4992
|
+
parts.push(String(this.getByPath(parent, this.folderPassthroughNameField) ?? parentId))
|
|
4993
|
+
}
|
|
4994
|
+
if (typeof scope.count === 'number') {
|
|
4995
|
+
if (cfg.countText) {
|
|
4996
|
+
parts.push(this.cnTranslate(cfg.countText).replace('{count}', String(scope.count)))
|
|
4997
|
+
} else if (cfg.source === 'groups') {
|
|
4998
|
+
parts.push(n('nextcloud-vue', '{count} member', '{count} members', scope.count, { count: scope.count }))
|
|
4999
|
+
}
|
|
5000
|
+
}
|
|
5001
|
+
return { name, subtitle: parts.join(' · ') }
|
|
5002
|
+
},
|
|
5003
|
+
|
|
5004
|
+
/**
|
|
5005
|
+
* The sort select's shown value: `sortSelectValue` when the host
|
|
5006
|
+
* controls it, else on a self-fetch page the option whose order is the
|
|
5007
|
+
* list's current order (a header click that matches one shows it).
|
|
5008
|
+
*
|
|
5009
|
+
* @return {string} The option value, or '' when none matches.
|
|
5010
|
+
*/
|
|
5011
|
+
effectiveSortSelectValue() {
|
|
5012
|
+
if (this.sortSelectValue) {
|
|
5013
|
+
return this.sortSelectValue
|
|
5014
|
+
}
|
|
5015
|
+
if (!this.isSelfFetchMode || !this.list || !this.list.sortKeys) {
|
|
5016
|
+
return ''
|
|
5017
|
+
}
|
|
5018
|
+
const current = this.list.sortKeys.value || []
|
|
5019
|
+
const match = (this.sortSelectOptions || []).find((o) => o && sameSortKeys(this.sortSelectKeys(o), current))
|
|
5020
|
+
return match ? match.value : ''
|
|
5021
|
+
},
|
|
5022
|
+
|
|
4899
5023
|
/**
|
|
4900
5024
|
* The `x-index` block the active scope's own schema row carries, for a
|
|
4901
5025
|
* folder list derived from a register. Empty for every other source:
|
|
@@ -6570,11 +6694,21 @@ export default {
|
|
|
6570
6694
|
effectiveQuickFilters() {
|
|
6571
6695
|
const own = withPersonalLenses(this.presented('quickFilters') || this.generatedQuickFilters, this.personalLenses)
|
|
6572
6696
|
if (own && own.length > 0) {
|
|
6573
|
-
return own
|
|
6697
|
+
return own.map((tab) => this.withConfigLabels(tab))
|
|
6574
6698
|
}
|
|
6575
6699
|
return (this.isNamedSource && this.namedQuickFilters) || null
|
|
6576
6700
|
},
|
|
6577
6701
|
|
|
6702
|
+
/**
|
|
6703
|
+
* The app config `@config.<key>` tokens resolve against: the `appConfig`
|
|
6704
|
+
* prop over a config an ancestor provides.
|
|
6705
|
+
*
|
|
6706
|
+
* @return {object} The config.
|
|
6707
|
+
*/
|
|
6708
|
+
effectiveAppConfig() {
|
|
6709
|
+
return { ...unwrapAppConfig(this.cnAppConfig), ...(this.appConfig || {}) }
|
|
6710
|
+
},
|
|
6711
|
+
|
|
6578
6712
|
/**
|
|
6579
6713
|
* Whether the Add button renders. A named source that declares
|
|
6580
6714
|
* `showAdd: false` suppresses it (a task is created by a flow, never
|
|
@@ -6669,6 +6803,7 @@ export default {
|
|
|
6669
6803
|
variant: button.variant === 'primary' ? 'primary' : 'secondary',
|
|
6670
6804
|
icon,
|
|
6671
6805
|
format: button.format === 'excel' ? 'excel' : 'csv',
|
|
6806
|
+
run: typeof button.run === 'string' ? button.run : '',
|
|
6672
6807
|
items: Array.isArray(button.items)
|
|
6673
6808
|
? button.items.filter((item) => (typeof item === 'string' && item !== '')
|
|
6674
6809
|
|| (item && typeof item === 'object' && typeof item.heading === 'string' && item.heading !== ''))
|
|
@@ -6676,6 +6811,10 @@ export default {
|
|
|
6676
6811
|
}
|
|
6677
6812
|
})
|
|
6678
6813
|
.filter((button) => button.label !== '')
|
|
6814
|
+
// An Export with nothing to export through is not drawn: a
|
|
6815
|
+
// named or endpoint source with no `run` and no `@mass-export`
|
|
6816
|
+
// listener.
|
|
6817
|
+
.filter((button) => button.action !== 'export' || this.headerExportAvailable(button))
|
|
6679
6818
|
// The Actions menu lists the page's header actions (or the
|
|
6680
6819
|
// entries its `items` name), so a menu with nothing to list
|
|
6681
6820
|
// is not drawn.
|
|
@@ -8464,7 +8603,9 @@ export default {
|
|
|
8464
8603
|
if (button.action === 'add') {
|
|
8465
8604
|
this.onAddClick()
|
|
8466
8605
|
} else if (button.action === 'export') {
|
|
8467
|
-
if (
|
|
8606
|
+
if (button.run) {
|
|
8607
|
+
this.onHeaderAction({ action: button.run, id: button.run })
|
|
8608
|
+
} else if (this.register && this.exportSchemaSlug) {
|
|
8468
8609
|
this.onExportClick(button.format)
|
|
8469
8610
|
} else {
|
|
8470
8611
|
this.showExportDialog = true
|
|
@@ -8480,6 +8621,25 @@ export default {
|
|
|
8480
8621
|
}
|
|
8481
8622
|
},
|
|
8482
8623
|
|
|
8624
|
+
/**
|
|
8625
|
+
* Whether a header Export has something to export through. Any page
|
|
8626
|
+
* listing OpenRegister objects (self-fetch or the consumer's
|
|
8627
|
+
* `objects`) keeps it; a named or endpoint source (`entitySource`)
|
|
8628
|
+
* needs a `run` naming one of the page's header actions, or a
|
|
8629
|
+
* `@mass-export` listener.
|
|
8630
|
+
*
|
|
8631
|
+
* @spec openspec/changes/index-header-export-source/specs/index-page/spec.md#requirement-a-header-export-is-drawn-only-when-it-can-export
|
|
8632
|
+
* @param {{run?: string}} button The resolved header button.
|
|
8633
|
+
* @return {boolean}
|
|
8634
|
+
*/
|
|
8635
|
+
headerExportAvailable(button) {
|
|
8636
|
+
if (!this.isNamedSource || (button && button.run)) {
|
|
8637
|
+
return true
|
|
8638
|
+
}
|
|
8639
|
+
const props = this.$ && this.$.vnode && this.$.vnode.props
|
|
8640
|
+
return Boolean(props && typeof props.onMassExport === 'function')
|
|
8641
|
+
},
|
|
8642
|
+
|
|
8483
8643
|
/**
|
|
8484
8644
|
* Click dispatch from CnActionsBar's `@header-action`. Looks
|
|
8485
8645
|
* up the resolved entry by id, invokes its handler if any,
|
|
@@ -8600,6 +8760,65 @@ export default {
|
|
|
8600
8760
|
this.$emit('quick-filter-change', this.selectedQuickFilterIndices)
|
|
8601
8761
|
},
|
|
8602
8762
|
|
|
8763
|
+
/**
|
|
8764
|
+
* The sort keys a sort-select option stands for: its `order` (any
|
|
8765
|
+
* `orderToSortKeys` form), else its `value` read as an order.
|
|
8766
|
+
*
|
|
8767
|
+
* @param {object} option A `sortSelectOptions` entry.
|
|
8768
|
+
* @return {Array<{key: string, order: string}>} The sort keys.
|
|
8769
|
+
*/
|
|
8770
|
+
sortSelectKeys(option) {
|
|
8771
|
+
if (!option) {
|
|
8772
|
+
return []
|
|
8773
|
+
}
|
|
8774
|
+
return orderToSortKeys(option.order !== undefined ? option.order : option.value)
|
|
8775
|
+
},
|
|
8776
|
+
|
|
8777
|
+
/**
|
|
8778
|
+
* A choice in the sort select. On a self-fetch page it orders the list
|
|
8779
|
+
* as a header click does (`_order`, kept in the address); every page
|
|
8780
|
+
* also emits `sort-change` with the value.
|
|
8781
|
+
*
|
|
8782
|
+
* @param {string} value The chosen option's value.
|
|
8783
|
+
* @return {void}
|
|
8784
|
+
*/
|
|
8785
|
+
onSortSelectChange(value) {
|
|
8786
|
+
const option = (this.sortSelectOptions || []).find((o) => o && o.value === value)
|
|
8787
|
+
const keys = this.sortSelectKeys(option)
|
|
8788
|
+
if (option && keys.length > 0 && this.isSelfFetchMode && typeof this.list.onSort === 'function') {
|
|
8789
|
+
this.list.onSort({ key: keys[0].key, order: keys[0].order, keys })
|
|
8790
|
+
this.persistViewStateToRoute(this.currentViewState())
|
|
8791
|
+
}
|
|
8792
|
+
this.$emit('sort-change', value)
|
|
8793
|
+
},
|
|
8794
|
+
|
|
8795
|
+
/**
|
|
8796
|
+
* A quick filter with `@config.<key>` in its `label` or `activeLabel`
|
|
8797
|
+
* (`"Residence @config.municipality"`): the label translated first, then
|
|
8798
|
+
* each token replaced by its configured value. A key the config does
|
|
8799
|
+
* not hold leaves its token in place. Other tabs pass unchanged.
|
|
8800
|
+
*
|
|
8801
|
+
* @param {object} tab A quick-filter tab.
|
|
8802
|
+
* @return {object} The tab, with its labels resolved.
|
|
8803
|
+
*/
|
|
8804
|
+
withConfigLabels(tab) {
|
|
8805
|
+
if (!tab || typeof tab !== 'object') {
|
|
8806
|
+
return tab
|
|
8807
|
+
}
|
|
8808
|
+
const hasToken = (value) => typeof value === 'string' && value.includes('@config.')
|
|
8809
|
+
if (!hasToken(tab.label) && !hasToken(tab.activeLabel)) {
|
|
8810
|
+
return tab
|
|
8811
|
+
}
|
|
8812
|
+
const config = this.effectiveAppConfig
|
|
8813
|
+
const fill = (value) => (hasToken(value)
|
|
8814
|
+
? this.cnTranslate(value).replace(/@config\.([A-Za-z0-9_.-]*[A-Za-z0-9_])/g, (token, key) => {
|
|
8815
|
+
const found = this.getByPath(config, key)
|
|
8816
|
+
return found === undefined || found === null || found === '' ? token : String(found)
|
|
8817
|
+
})
|
|
8818
|
+
: value)
|
|
8819
|
+
return { ...tab, label: fill(tab.label), activeLabel: fill(tab.activeLabel) }
|
|
8820
|
+
},
|
|
8821
|
+
|
|
8603
8822
|
/**
|
|
8604
8823
|
* @param {{key: string, order: string, keys?: Array<{key: string, order: string}>}} payload Sort change from CnDataTable.
|
|
8605
8824
|
* @return {void}
|
|
@@ -7,6 +7,7 @@ import { useObjectStore } from '../../store/index.js'
|
|
|
7
7
|
// without pulling in this composable's index-only sidebar/subscription wiring.
|
|
8
8
|
import { withPersonalLenses } from '../../utils/personalLenses.js'
|
|
9
9
|
import { parseSortKeysFromQuery, resolveFilterMap, resolveQueryFilters } from '../../utils/routeFilters.js'
|
|
10
|
+
import { orderToSortKeys } from '../../utils/sortOrder.js'
|
|
10
11
|
|
|
11
12
|
function resolveInitialQuickFilterIndex(quickFilters) {
|
|
12
13
|
const tabs = Array.isArray(quickFilters) ? quickFilters : null
|
|
@@ -170,7 +171,8 @@ export function useSelfFetchList(props, instance, inject, extras = {}) {
|
|
|
170
171
|
const objCtx = unwrapCtx(objectCtxRaw)
|
|
171
172
|
const base = (objCtx && typeof objCtx === 'object') ? { ...objCtx } : {}
|
|
172
173
|
base.workspace = unwrapCtx(workspaceCtxRaw) || {}
|
|
173
|
-
|
|
174
|
+
// The page's own `appConfig` prop wins over a config an ancestor provides.
|
|
175
|
+
base.config = { ...(unwrapCtx(appConfigRaw) || {}), ...(props.appConfig || {}) }
|
|
174
176
|
return base
|
|
175
177
|
}
|
|
176
178
|
|
|
@@ -182,7 +184,7 @@ export function useSelfFetchList(props, instance, inject, extras = {}) {
|
|
|
182
184
|
// never again. Stringified (like CnDeltaWidget's `sourceKey`) so the
|
|
183
185
|
// watcher fires on real content changes only, not object identity.
|
|
184
186
|
const workspaceSignature = computed(() => JSON.stringify(unwrapCtx(workspaceCtxRaw) || {}))
|
|
185
|
-
const appConfigSignature = computed(() => JSON.stringify(unwrapCtx(appConfigRaw) || {}))
|
|
187
|
+
const appConfigSignature = computed(() => JSON.stringify({ ...(unwrapCtx(appConfigRaw) || {}), ...(props.appConfig || {}) }))
|
|
186
188
|
|
|
187
189
|
// Pass register/schema in their positional id slots (not as a {register, schema} object as
|
|
188
190
|
// second arg) — that previously made fetch URLs go to `/api/objects/undefined/[object Object]`.
|
|
@@ -219,9 +221,12 @@ export function useSelfFetchList(props, instance, inject, extras = {}) {
|
|
|
219
221
|
// legacy single-key `sortKey`/`sortOrder` props.
|
|
220
222
|
const initialRoute = instance && instance.proxy && instance.proxy.$route
|
|
221
223
|
// The page's own order, which a lens without a `sort` goes back to.
|
|
224
|
+
// `defaultOrder` (manifest `config.defaultOrder`) is the order of last
|
|
225
|
+
// resort, after `sortKeys` and `sortKey`.
|
|
226
|
+
const defaultOrderKeys = orderToSortKeys(props.defaultOrder)
|
|
222
227
|
const pageSortKeys = (Array.isArray(props.sortKeys) && props.sortKeys.length > 0)
|
|
223
228
|
? props.sortKeys
|
|
224
|
-
: (props.sortKey ? [{ key: props.sortKey, order: props.sortOrder || 'asc' }] :
|
|
229
|
+
: (props.sortKey ? [{ key: props.sortKey, order: props.sortOrder || 'asc' }] : defaultOrderKeys)
|
|
225
230
|
// The lens that is active on mount may set its own order.
|
|
226
231
|
const initialTabs = withPersonalLenses(props.quickFilters, props.personalLenses)
|
|
227
232
|
const initialTabSort = (!isMultiQuickFilter && Array.isArray(initialTabs))
|
|
@@ -230,6 +235,7 @@ export function useSelfFetchList(props, instance, inject, extras = {}) {
|
|
|
230
235
|
const initialSortKeys = parseSortKeysFromQuery(initialRoute)
|
|
231
236
|
|| initialTabSort
|
|
232
237
|
|| (Array.isArray(props.sortKeys) && props.sortKeys.length > 0 ? props.sortKeys : undefined)
|
|
238
|
+
|| (!props.sortKey && defaultOrderKeys.length > 0 ? defaultOrderKeys : undefined)
|
|
233
239
|
// Same deep-link restore for facet filters and search, so opening a
|
|
234
240
|
// shared/bookmarked URL reproduces the same view (CnIndexPage persists
|
|
235
241
|
// both back to the route on change).
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
- SPDX-FileCopyrightText: 2026 Conduction B.V.
|
|
3
|
+
- SPDX-License-Identifier: EUPL-1.2
|
|
4
|
+
-->
|
|
5
|
+
<template>
|
|
6
|
+
<section
|
|
7
|
+
v-if="resolvedText || resolvedTitle"
|
|
8
|
+
class="cn-notice-widget"
|
|
9
|
+
:class="`cn-notice-widget--${resolvedVariant}`"
|
|
10
|
+
:aria-label="resolvedTitle || null"
|
|
11
|
+
role="note"
|
|
12
|
+
data-testid="cn-notice-widget">
|
|
13
|
+
<CnIcon
|
|
14
|
+
class="cn-notice-widget__icon"
|
|
15
|
+
:name="resolvedIcon"
|
|
16
|
+
:size="18"
|
|
17
|
+
aria-hidden="true" />
|
|
18
|
+
<p class="cn-notice-widget__text">
|
|
19
|
+
<strong v-if="resolvedTitle" class="cn-notice-widget__title" data-testid="cn-notice-widget-title">{{ resolvedTitle }}</strong>{{ resolvedTitle && resolvedText ? ' ' : '' }}{{ resolvedText }}
|
|
20
|
+
</p>
|
|
21
|
+
</section>
|
|
22
|
+
</template>
|
|
23
|
+
|
|
24
|
+
<script>
|
|
25
|
+
import { CnIcon } from '../CnIcon/index.js'
|
|
26
|
+
|
|
27
|
+
/** The tones a notice takes, and the icon each shows by default. */
|
|
28
|
+
const VARIANT_ICONS = Object.freeze({
|
|
29
|
+
info: 'InformationOutline',
|
|
30
|
+
warning: 'AlertOutline',
|
|
31
|
+
error: 'AlertCircleOutline',
|
|
32
|
+
success: 'CheckCircleOutline',
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* CnNoticeWidget — a toned notice box: an icon, a bold title and a line of
|
|
37
|
+
* text in one rounded box, as the boards draw a warning beside a record
|
|
38
|
+
* (DqSociaalDomein "Bijzondere persoonsgegevens: gezondheid. Elke inzage
|
|
39
|
+
* wordt gelogd met het doel."). Usable in a detail page's side column, its
|
|
40
|
+
* body grid and on a dashboard as widget type `notice`; the surface applies
|
|
41
|
+
* the widget's `visibleWhen`.
|
|
42
|
+
*
|
|
43
|
+
* `content`: `{ variant?, title?, text, icon? }`. `variant` is `info`
|
|
44
|
+
* (default), `warning`, `error` or `success`; `title` and `text` go through
|
|
45
|
+
* the host's translate; `icon` names a CnIcon instead of the variant's own.
|
|
46
|
+
*
|
|
47
|
+
* ```vue
|
|
48
|
+
* <CnNoticeWidget :content="{ variant: 'warning', title: 'Special category data: health.', text: 'Every view is logged with its purpose.' }" />
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
export default {
|
|
52
|
+
name: 'CnNoticeWidget',
|
|
53
|
+
|
|
54
|
+
components: { CnIcon },
|
|
55
|
+
|
|
56
|
+
inject: {
|
|
57
|
+
/** The host app's translate function (CnAppRoot `cnTranslate`). */
|
|
58
|
+
cnTranslate: { default: () => (key) => key },
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
props: {
|
|
62
|
+
/**
|
|
63
|
+
* The notice: `{ variant?, title?, text, icon? }`.
|
|
64
|
+
*
|
|
65
|
+
* @type {{variant?: string, title?: string, text?: string, icon?: string}}
|
|
66
|
+
*/
|
|
67
|
+
content: {
|
|
68
|
+
type: Object,
|
|
69
|
+
default: () => ({}),
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
|
|
73
|
+
computed: {
|
|
74
|
+
/** @return {string} `info`, `warning`, `error` or `success`. */
|
|
75
|
+
resolvedVariant() {
|
|
76
|
+
const variant = this.content && this.content.variant === 'danger' ? 'error' : this.content && this.content.variant
|
|
77
|
+
return Object.hasOwn(VARIANT_ICONS, variant) ? variant : 'info'
|
|
78
|
+
},
|
|
79
|
+
|
|
80
|
+
/** @return {string} The icon name. */
|
|
81
|
+
resolvedIcon() {
|
|
82
|
+
const icon = this.content && this.content.icon
|
|
83
|
+
return typeof icon === 'string' && icon !== '' ? icon : VARIANT_ICONS[this.resolvedVariant]
|
|
84
|
+
},
|
|
85
|
+
|
|
86
|
+
/** @return {string} The title through the host translate. */
|
|
87
|
+
resolvedTitle() {
|
|
88
|
+
return this.translate(this.content && this.content.title)
|
|
89
|
+
},
|
|
90
|
+
|
|
91
|
+
/** @return {string} The text through the host translate. */
|
|
92
|
+
resolvedText() {
|
|
93
|
+
return this.translate(this.content && this.content.text)
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
|
|
97
|
+
methods: {
|
|
98
|
+
/**
|
|
99
|
+
* @param {unknown} text A manifest string.
|
|
100
|
+
* @return {string} Its translation, '' for anything but a non-empty string.
|
|
101
|
+
*/
|
|
102
|
+
translate(text) {
|
|
103
|
+
if (typeof text !== 'string' || text === '') {
|
|
104
|
+
return ''
|
|
105
|
+
}
|
|
106
|
+
return typeof this.cnTranslate === 'function' ? this.cnTranslate(text) : text
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
}
|
|
110
|
+
</script>
|
|
111
|
+
|
|
112
|
+
<style scoped>
|
|
113
|
+
.cn-notice-widget {
|
|
114
|
+
display: flex;
|
|
115
|
+
align-items: flex-start;
|
|
116
|
+
gap: 10px;
|
|
117
|
+
padding: 14px 16px;
|
|
118
|
+
border-radius: var(--cn-board-card-radius, 12px);
|
|
119
|
+
font-size: 14px;
|
|
120
|
+
line-height: 1.5;
|
|
121
|
+
background: color-mix(in srgb, var(--color-info, #0071ad) 10%, var(--color-main-background));
|
|
122
|
+
color: var(--color-main-text);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.cn-notice-widget--warning {
|
|
126
|
+
background: var(--color-warning-light, #fff4de);
|
|
127
|
+
color: var(--color-warning-text, #7a4f00);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.cn-notice-widget--error {
|
|
131
|
+
background: color-mix(in srgb, var(--color-error, #db0606) 10%, var(--color-main-background));
|
|
132
|
+
color: var(--color-error-text, var(--color-main-text));
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.cn-notice-widget--success {
|
|
136
|
+
background: color-mix(in srgb, var(--color-success, #2d7b41) 10%, var(--color-main-background));
|
|
137
|
+
color: var(--color-success-text, var(--color-main-text));
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.cn-notice-widget__icon {
|
|
141
|
+
flex: 0 0 auto;
|
|
142
|
+
margin-top: 2px;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.cn-notice-widget__text {
|
|
146
|
+
margin: 0;
|
|
147
|
+
overflow-wrap: anywhere;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.cn-notice-widget__title {
|
|
151
|
+
font-weight: 700;
|
|
152
|
+
}
|
|
153
|
+
</style>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SPDX-FileCopyrightText: 2026 Conduction B.V.
|
|
3
|
+
* SPDX-License-Identifier: EUPL-1.2
|
|
4
|
+
*
|
|
5
|
+
* CnNoticeWidget — a toned notice box (icon, bold title, text) for a side
|
|
6
|
+
* column, a detail body or a dashboard (widget type `notice`).
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import CnNoticeWidget from './CnNoticeWidget.vue'
|
|
10
|
+
|
|
11
|
+
export { CnNoticeWidget }
|
|
12
|
+
export default CnNoticeWidget
|