@conduction/nextcloud-vue 2.79.0 → 2.80.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/CnActionButtons/CnActionButtons.vue2.js.map +1 -1
- package/dist/esm/components/CnActionButtons/CnActionButtons.vue3.js +3 -1
- package/dist/esm/components/CnActionButtons/CnActionButtons.vue3.js.map +1 -1
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue2.js +32 -3
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue2.js.map +1 -1
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js +10 -8
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js.map +1 -1
- package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue2.js +39 -3
- 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/CnCellRenderer/CnCellRenderer.vue2.js +79 -1
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js.map +1 -1
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js +133 -96
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js +1 -0
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +62 -4
- 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/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js +24 -0
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js.map +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js +43 -4
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js.map +1 -1
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue.js +11 -0
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue.js.map +1 -0
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js +736 -0
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue3.js +238 -0
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue3.js.map +1 -0
- package/dist/esm/components/CnFactsWidget/index.js +30 -0
- package/dist/esm/components/CnFactsWidget/index.js.map +1 -0
- package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue.js +10 -0
- package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue.js.map +1 -0
- package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue2.js +551 -0
- package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue3.js +183 -0
- package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue3.js.map +1 -0
- package/dist/esm/components/CnFieldListWidget/index.js +29 -0
- package/dist/esm/components/CnFieldListWidget/index.js.map +1 -0
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js +65 -17
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js.map +1 -1
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue3.js +4 -4
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue3.js.map +1 -1
- package/dist/esm/components/CnFormPage/CnFormPage.vue2.js +18 -3
- package/dist/esm/components/CnFormPage/CnFormPage.vue2.js.map +1 -1
- package/dist/esm/components/CnFormPage/CnFormPage.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +305 -72
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +31 -13
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue.js +10 -0
- package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue.js.map +1 -0
- package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue2.js +99 -0
- package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue2.js.map +1 -0
- package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue3.js +48 -0
- package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue3.js.map +1 -0
- package/dist/esm/components/CnPageRenderer/CnPageRenderer.vue2.js +29 -1
- package/dist/esm/components/CnPageRenderer/CnPageRenderer.vue2.js.map +1 -1
- package/dist/esm/components/CnPageRenderer/CnPageRenderer.vue3.js.map +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue.js +10 -0
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue.js.map +1 -0
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js +387 -0
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js +169 -0
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js.map +1 -0
- package/dist/esm/components/CnRecordListWidget/index.js +31 -0
- package/dist/esm/components/CnRecordListWidget/index.js.map +1 -0
- package/dist/esm/components/CnSectionsWidget/CnSectionsWidget.vue.js +10 -0
- package/dist/esm/components/CnSectionsWidget/CnSectionsWidget.vue.js.map +1 -0
- package/dist/esm/components/CnSectionsWidget/CnSectionsWidget.vue2.js +351 -0
- package/dist/esm/components/CnSectionsWidget/CnSectionsWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnSectionsWidget/CnSectionsWidget.vue3.js +71 -0
- package/dist/esm/components/CnSectionsWidget/CnSectionsWidget.vue3.js.map +1 -0
- package/dist/esm/components/CnSectionsWidget/index.js +35 -0
- package/dist/esm/components/CnSectionsWidget/index.js.map +1 -0
- package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue2.js +81 -2
- package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnStatWidget/CnStatWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnStatWidget/CnStatWidget.vue3.js +1 -0
- package/dist/esm/components/CnStatWidget/CnStatWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js +122 -7
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js +84 -23
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js +4 -0
- package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js.map +1 -1
- package/dist/esm/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue2.js +106 -2
- package/dist/esm/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue3.js +105 -53
- package/dist/esm/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue3.js.map +1 -1
- package/dist/esm/composables/useFormDraft.js +140 -9
- package/dist/esm/composables/useFormDraft.js.map +1 -1
- package/dist/esm/index.js +4 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionCard.vue2.js +28 -20
- package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionCard.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionCard.vue3.js +9 -0
- package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionCard.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/field-inspection.js +21 -0
- package/dist/esm/integrations/builtin/field-inspection.js.map +1 -1
- package/dist/esm/integrations/offline/checklistSubmission.js +141 -0
- package/dist/esm/integrations/offline/checklistSubmission.js.map +1 -0
- package/dist/esm/integrations/offline/fieldCollectionHelpers.js +70 -5
- package/dist/esm/integrations/offline/fieldCollectionHelpers.js.map +1 -1
- package/dist/esm/integrations/offline/index.js +2 -1
- package/dist/esm/integrations/offline/index.js.map +1 -1
- package/dist/esm/integrations/offline/offlineDb.js +6 -1
- package/dist/esm/integrations/offline/offlineDb.js.map +1 -1
- package/dist/esm/integrations/offline/syncReplayService.js +8 -2
- package/dist/esm/integrations/offline/syncReplayService.js.map +1 -1
- package/dist/esm/l10n/en.json.js +12 -1
- package/dist/esm/l10n/en.json.js.map +1 -1
- package/dist/esm/l10n/nl.json.js +16 -2
- package/dist/esm/l10n/nl.json.js.map +1 -1
- package/dist/esm/nextcloud-vue.css +1000 -59
- package/dist/esm/utils/detailActionModel.js +60 -3
- package/dist/esm/utils/detailActionModel.js.map +1 -1
- package/dist/esm/utils/fillTemplate.js +114 -0
- package/dist/esm/utils/fillTemplate.js.map +1 -0
- package/dist/esm/utils/libraryWidgetKeys.js +4 -0
- package/dist/esm/utils/libraryWidgetKeys.js.map +1 -1
- package/dist/esm/utils/queryPresets.js +96 -0
- package/dist/esm/utils/queryPresets.js.map +1 -0
- package/dist/esm/utils/resolveFilterTokens.js +11 -0
- package/dist/esm/utils/resolveFilterTokens.js.map +1 -1
- package/dist/esm/utils/schema.js +21 -0
- package/dist/esm/utils/schema.js.map +1 -1
- package/dist/esm/utils/sentinelTokens.js +3 -3
- package/dist/esm/utils/sentinelTokens.js.map +1 -1
- package/dist/esm/utils/validateManifestV2.compiled.js +3 -3
- package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
- package/dist/esm/utils/widgetDispatch.js +7 -1
- package/dist/esm/utils/widgetDispatch.js.map +1 -1
- package/dist/nextcloud-vue.cjs.js +12368 -7717
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +1000 -59
- package/l10n/en.json +12 -1
- package/l10n/nl.json +16 -2
- package/package.json +1 -1
- package/src/components/CnActionButtons/CnActionButtons.vue +2 -0
- package/src/components/CnActionsBar/CnActionsBar.md +4 -0
- package/src/components/CnActionsBar/CnActionsBar.vue +42 -10
- package/src/components/CnBannerWidget/CnBannerWidget.vue +39 -3
- package/src/components/CnCellRenderer/CnCellRenderer.vue +188 -1
- package/src/components/CnDataTable/CnDataTable.vue +1 -0
- package/src/components/CnDetailPage/CnDetailPage.md +1 -1
- package/src/components/CnDetailPage/CnDetailPage.vue +63 -3
- package/src/components/CnDetailWidgetHost/CnDetailWidgetHost.vue +66 -0
- package/src/components/CnFactsWidget/CnFactsWidget.vue +1050 -0
- package/src/components/CnFactsWidget/index.js +29 -0
- package/src/components/CnFieldListWidget/CnFieldListWidget.vue +746 -0
- package/src/components/CnFieldListWidget/index.js +28 -0
- package/src/components/CnFormDialog/CnFormDialog.md +9 -3
- package/src/components/CnFormDialog/CnFormDialog.vue +69 -21
- package/src/components/CnFormPage/CnFormPage.vue +18 -3
- package/src/components/CnIndexPage/CnIndexPage.vue +254 -6
- package/src/components/CnIndexPage/CnIndexPageWidgets.vue +169 -0
- package/src/components/CnPageRenderer/CnPageRenderer.vue +29 -1
- package/src/components/CnRecordListWidget/CnRecordListWidget.vue +603 -0
- package/src/components/CnRecordListWidget/index.js +30 -0
- package/src/components/CnSectionsWidget/CnSectionsWidget.vue +489 -0
- package/src/components/CnSectionsWidget/index.js +34 -0
- package/src/components/CnStagesWidget/CnStagesWidget.vue +81 -2
- package/src/components/CnStatWidget/CnStatWidget.vue +1 -1
- package/src/components/CnTabsWidget/CnTabsWidget.vue +184 -8
- package/src/components/CnWidgetGrid/registerDashboardWidgets.js +4 -0
- package/src/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue +188 -4
- package/src/components/index.js +4 -0
- package/src/composables/__tests__/useFormDraft.spec.js +69 -0
- package/src/composables/useFormDraft.js +139 -8
- package/src/css/form-field.css +14 -0
- package/src/css/index-page.css +71 -0
- package/src/css/kpi-card.css +32 -0
- package/src/css/look-board-detail.css +77 -0
- package/src/css/look-board-index.css +51 -0
- package/src/css/look-board.css +37 -2
- package/src/css/table.css +19 -0
- package/src/index.js +4 -0
- package/src/integrations/builtin/field-inspection/CnFieldInspectionCard.vue +35 -20
- package/src/integrations/builtin/field-inspection.js +21 -0
- package/src/integrations/offline/checklistSubmission.js +137 -0
- package/src/integrations/offline/fieldCollectionHelpers.js +69 -4
- package/src/integrations/offline/index.js +3 -0
- package/src/integrations/offline/offlineDb.js +6 -1
- package/src/integrations/offline/syncReplayService.js +8 -2
- package/src/schemas/app-manifest-v2.schema.json +104 -5
- package/src/utils/detailActionModel.js +59 -2
- package/src/utils/fillTemplate.js +110 -0
- package/src/utils/libraryWidgetKeys.js +4 -0
- package/src/utils/queryPresets.js +93 -0
- package/src/utils/resolveFilterTokens.js +11 -0
- package/src/utils/schema.js +21 -0
- package/src/utils/sentinelTokens.js +3 -3
- package/src/utils/validateManifestV2.compiled.js +3 -3
- package/src/utils/widgetDispatch.js +7 -1
|
@@ -1231,12 +1231,15 @@ import {
|
|
|
1231
1231
|
groupMenuEntries,
|
|
1232
1232
|
MAX_QUICK_ACTIONS,
|
|
1233
1233
|
normalisePinnedAction,
|
|
1234
|
+
pillCountSource,
|
|
1235
|
+
resolveCountPill,
|
|
1234
1236
|
resolveNextStep,
|
|
1235
1237
|
resolvePill,
|
|
1236
1238
|
stageEntry,
|
|
1237
1239
|
stageOf,
|
|
1238
1240
|
} from '../../utils/detailActionModel.js'
|
|
1239
1241
|
import { reportBindingProblems } from '../../utils/diagnostics.js'
|
|
1242
|
+
import { fetchListTotal } from '../../utils/fetchFilterCounts.js'
|
|
1240
1243
|
import { cnGridCellStyle, hasGridRow } from '../../utils/grid.js'
|
|
1241
1244
|
import { isActivityWidget, resolveHeaderMeta } from '../../utils/headerMeta.js'
|
|
1242
1245
|
import { patchStoredSelf } from '../../utils/patchStoredSelf.js'
|
|
@@ -2393,9 +2396,13 @@ export default {
|
|
|
2393
2396
|
* A pill above the title saying what kind of record this is
|
|
2394
2397
|
* (manifest `config.typePill`): `{ field, colorMap?, labels?, variant? }`.
|
|
2395
2398
|
* Rendered through `CnStatusBadge`; `colorMap` is keyed on the field's
|
|
2396
|
-
* raw value, `labels` maps a raw value to the text to show.
|
|
2399
|
+
* raw value, `labels` maps a raw value to the text to show. Instead of
|
|
2400
|
+
* `field`: `text`, a constant ("Inwoner"), or `countFrom`
|
|
2401
|
+
* (`{ register, schema, filter? }`) with `countLabel` (`{ one, other }`
|
|
2402
|
+
* with `{count}`), a count of a related list ("1 lopende zaak") that
|
|
2403
|
+
* shows nothing at 0.
|
|
2397
2404
|
*
|
|
2398
|
-
* @type {{field
|
|
2405
|
+
* @type {{field?: string, text?: string, countFrom?: object, countLabel?: object, colorMap?: object, labels?: object, variant?: string}|null}
|
|
2399
2406
|
*/
|
|
2400
2407
|
typePill: {
|
|
2401
2408
|
type: Object,
|
|
@@ -2747,6 +2754,10 @@ export default {
|
|
|
2747
2754
|
|
|
2748
2755
|
data() {
|
|
2749
2756
|
return {
|
|
2757
|
+
/** The counts of the header's count pills (`countFrom`), by pill key (`type`, `status`). */
|
|
2758
|
+
pillCounts: {},
|
|
2759
|
+
/** Sequence of the last pill count round, so a late answer does not overwrite a newer one. */
|
|
2760
|
+
pillCountSeq: 0,
|
|
2750
2761
|
/** `register/schema/id` the read-state call was last made for, so it is sent once per load. */
|
|
2751
2762
|
readStateSentFor: '',
|
|
2752
2763
|
/** Whether the user is arranging the chosen view (`userLayout`). */
|
|
@@ -3259,12 +3270,25 @@ export default {
|
|
|
3259
3270
|
headerPills() {
|
|
3260
3271
|
return [['type', this.typePill], ['status', this.statusPill]]
|
|
3261
3272
|
.map(([key, config]) => {
|
|
3262
|
-
const pill =
|
|
3273
|
+
const pill = pillCountSource(config)
|
|
3274
|
+
? resolveCountPill(config, this.pillCounts[key], (text) => this.effectiveTranslate(text))
|
|
3275
|
+
: resolvePill(config, this.resolvedObject)
|
|
3263
3276
|
return pill ? { ...pill, key, label: this.effectiveTranslate(pill.label) } : null
|
|
3264
3277
|
})
|
|
3265
3278
|
.filter(Boolean)
|
|
3266
3279
|
},
|
|
3267
3280
|
|
|
3281
|
+
/**
|
|
3282
|
+
* What the count pills depend on: the record id and the lists they
|
|
3283
|
+
* count. A change counts again.
|
|
3284
|
+
*
|
|
3285
|
+
* @return {string} The key.
|
|
3286
|
+
* @spec openspec/changes/screens-relation-pages/specs/relation-pages/spec.md#requirement-a-header-pill-can-be-a-constant-or-a-count
|
|
3287
|
+
*/
|
|
3288
|
+
pillCountKey() {
|
|
3289
|
+
return JSON.stringify([this.objectId, pillCountSource(this.typePill), pillCountSource(this.statusPill)])
|
|
3290
|
+
},
|
|
3291
|
+
|
|
3268
3292
|
/**
|
|
3269
3293
|
* The widget the header holds (`headerWidget`): the definition in
|
|
3270
3294
|
* `widgets` with that id, or null without the key or a match.
|
|
@@ -4337,6 +4361,14 @@ export default {
|
|
|
4337
4361
|
},
|
|
4338
4362
|
|
|
4339
4363
|
watch: {
|
|
4364
|
+
// The header's count pills count again for another record or other lists.
|
|
4365
|
+
pillCountKey: {
|
|
4366
|
+
immediate: true,
|
|
4367
|
+
handler() {
|
|
4368
|
+
this.refreshPillCounts()
|
|
4369
|
+
},
|
|
4370
|
+
},
|
|
4371
|
+
|
|
4340
4372
|
// Opening a record marks it read, once, after its data has rendered.
|
|
4341
4373
|
readStateDue: {
|
|
4342
4374
|
immediate: true,
|
|
@@ -4754,6 +4786,33 @@ export default {
|
|
|
4754
4786
|
}
|
|
4755
4787
|
},
|
|
4756
4788
|
|
|
4789
|
+
/**
|
|
4790
|
+
* Count the lists behind the header's count pills (`countFrom`): one
|
|
4791
|
+
* list request each (`_limit=1`, the `total`). A failed count, or a
|
|
4792
|
+
* record without an id yet, shows no pill.
|
|
4793
|
+
*
|
|
4794
|
+
* @return {Promise<void>}
|
|
4795
|
+
* @spec openspec/changes/screens-relation-pages/specs/relation-pages/spec.md#requirement-a-header-pill-can-be-a-constant-or-a-count
|
|
4796
|
+
*/
|
|
4797
|
+
async refreshPillCounts() {
|
|
4798
|
+
const pills = [['type', this.typePill], ['status', this.statusPill]]
|
|
4799
|
+
.map(([key, config]) => [key, pillCountSource(config)])
|
|
4800
|
+
.filter(([, source]) => source)
|
|
4801
|
+
const seq = ++this.pillCountSeq
|
|
4802
|
+
if (pills.length === 0 || this.objectId === null || this.objectId === undefined || this.objectId === '') {
|
|
4803
|
+
this.pillCounts = {}
|
|
4804
|
+
return
|
|
4805
|
+
}
|
|
4806
|
+
const ctx = { objectId: this.objectId, object: this.resolvedObject || undefined }
|
|
4807
|
+
const counts = {}
|
|
4808
|
+
await Promise.all(pills.map(async ([key, source]) => {
|
|
4809
|
+
counts[key] = await fetchListTotal(source.register, source.schema, source.filter, ctx).catch(() => null)
|
|
4810
|
+
}))
|
|
4811
|
+
if (seq === this.pillCountSeq) {
|
|
4812
|
+
this.pillCounts = counts
|
|
4813
|
+
}
|
|
4814
|
+
},
|
|
4815
|
+
|
|
4757
4816
|
/**
|
|
4758
4817
|
* A `cn:page:refresh` reached the page — re-read the object so every
|
|
4759
4818
|
* object-bound widget re-renders from what the backend now holds.
|
|
@@ -4768,6 +4827,7 @@ export default {
|
|
|
4768
4827
|
* @return {void}
|
|
4769
4828
|
*/
|
|
4770
4829
|
onPageRefreshBus(payload) {
|
|
4830
|
+
this.refreshPillCounts()
|
|
4771
4831
|
if (!this.hasSchemaDrivenFetch) {
|
|
4772
4832
|
return
|
|
4773
4833
|
}
|
|
@@ -169,10 +169,28 @@
|
|
|
169
169
|
:showActions="actionsShown || catalogAddEnabled"
|
|
170
170
|
:showRefresh="false"
|
|
171
171
|
:showRequestFeature="false"
|
|
172
|
+
:headerLink="rendererHeader.link"
|
|
172
173
|
class="cn-detail-page__catalog-card">
|
|
173
174
|
<template v-if="widget.icon" #title-icon>
|
|
174
175
|
<CnIcon :name="widget.icon" :size="20" />
|
|
175
176
|
</template>
|
|
177
|
+
<!-- A renderer that reports its own header (`header` event:
|
|
178
|
+
`{ link, note }`, e.g. record-list's "3 in totaal"). -->
|
|
179
|
+
<template v-if="rendererHeader.note || rendererHeader.action" #actions>
|
|
180
|
+
<span
|
|
181
|
+
v-if="rendererHeader.note"
|
|
182
|
+
class="cn-detail-page__catalog-note"
|
|
183
|
+
data-testid="cn-detail-widget-header-note">{{ rendererHeader.note }}</span>
|
|
184
|
+
<button
|
|
185
|
+
v-if="rendererHeader.action"
|
|
186
|
+
type="button"
|
|
187
|
+
class="cn-detail-page__catalog-action"
|
|
188
|
+
data-testid="cn-detail-widget-header-action"
|
|
189
|
+
@click="rendererHeader.action.run()">
|
|
190
|
+
<CnIcon v-if="rendererHeader.action.icon" :name="rendererHeader.action.icon" :size="16" />
|
|
191
|
+
{{ rendererHeader.action.label }}
|
|
192
|
+
</button>
|
|
193
|
+
</template>
|
|
176
194
|
<template v-if="catalogAddEnabled" #action-items>
|
|
177
195
|
<NcActionButton @click="invokeCatalogAdd">
|
|
178
196
|
<template #icon>
|
|
@@ -185,6 +203,7 @@
|
|
|
185
203
|
:is="renderer"
|
|
186
204
|
ref="renderer"
|
|
187
205
|
v-bind="rendererProps"
|
|
206
|
+
@header="onRendererHeader"
|
|
188
207
|
@selectObject="onSelectObject" />
|
|
189
208
|
</CnWidgetWrapper>
|
|
190
209
|
|
|
@@ -534,6 +553,17 @@ export default {
|
|
|
534
553
|
}
|
|
535
554
|
},
|
|
536
555
|
|
|
556
|
+
data() {
|
|
557
|
+
return {
|
|
558
|
+
/**
|
|
559
|
+
* The card header a content-only renderer reports through its
|
|
560
|
+
* `header` event (screens-relation-pages): a link and a note,
|
|
561
|
+
* with the list's total already filled in.
|
|
562
|
+
*/
|
|
563
|
+
rendererHeader: { link: null, note: '', action: null },
|
|
564
|
+
}
|
|
565
|
+
},
|
|
566
|
+
|
|
537
567
|
computed: {
|
|
538
568
|
/**
|
|
539
569
|
* Whether the caller owns the title and card.
|
|
@@ -992,6 +1022,19 @@ export default {
|
|
|
992
1022
|
},
|
|
993
1023
|
|
|
994
1024
|
methods: {
|
|
1025
|
+
/**
|
|
1026
|
+
* Take the header a content-only renderer reports.
|
|
1027
|
+
*
|
|
1028
|
+
* @param {{link?: object|null, note?: string, action?: {label: string, icon?: string, run: () => unknown}|null}} header The header parts.
|
|
1029
|
+
* @spec openspec/changes/screens-relation-pages/specs/relation-pages/spec.md#requirement-a-record-list-shows-the-objects-that-point-at-this-record
|
|
1030
|
+
*/
|
|
1031
|
+
onRendererHeader(header) {
|
|
1032
|
+
const link = header && header.link && typeof header.link === 'object' ? header.link : null
|
|
1033
|
+
const note = header && typeof header.note === 'string' ? header.note : ''
|
|
1034
|
+
const action = header && header.action && typeof header.action.run === 'function' && header.action.label ? header.action : null
|
|
1035
|
+
this.rendererHeader = { link, note, action }
|
|
1036
|
+
},
|
|
1037
|
+
|
|
995
1038
|
/**
|
|
996
1039
|
* A manifest label through the host's translate; '' stays ''.
|
|
997
1040
|
*
|
|
@@ -1110,6 +1153,29 @@ export default {
|
|
|
1110
1153
|
</script>
|
|
1111
1154
|
|
|
1112
1155
|
<style scoped>
|
|
1156
|
+
.cn-detail-page__catalog-action {
|
|
1157
|
+
align-items: center;
|
|
1158
|
+
background: var(--color-primary-element-light);
|
|
1159
|
+
border: 0;
|
|
1160
|
+
border-radius: 16px;
|
|
1161
|
+
color: var(--color-primary-element-light-text, var(--color-primary-element));
|
|
1162
|
+
cursor: pointer;
|
|
1163
|
+
display: inline-flex;
|
|
1164
|
+
font: inherit;
|
|
1165
|
+
font-size: 13px;
|
|
1166
|
+
font-weight: 700;
|
|
1167
|
+
gap: 6px;
|
|
1168
|
+
min-height: 32px;
|
|
1169
|
+
padding: 0 14px;
|
|
1170
|
+
white-space: nowrap;
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1173
|
+
.cn-detail-page__catalog-note {
|
|
1174
|
+
color: var(--color-text-maxcontrast);
|
|
1175
|
+
font-size: 14px;
|
|
1176
|
+
white-space: nowrap;
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1113
1179
|
.cn-detail-widget-host,
|
|
1114
1180
|
.cn-detail-widget-host > * {
|
|
1115
1181
|
height: 100%;
|