@conduction/nextcloud-vue 2.145.0 → 2.147.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/CnAiCompanion/CnAiChatPanel.vue2.js.map +1 -1
- package/dist/esm/components/CnAiCompanion/CnAiChatPanel.vue3.js.map +1 -1
- package/dist/esm/components/CnChecklistRunWidget/CnChecklistRunWidget.vue.js +1 -1
- package/dist/esm/components/CnChecklistRunWidget/CnChecklistRunWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnChecklistRunWidget/CnChecklistRunWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js +12 -2
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js +42 -30
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +22 -0
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js +2 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue.js +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue2.js.map +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue3.js.map +1 -1
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue.js +1 -1
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js +112 -15
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue3.js +40 -16
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnNotesCard/CnNotesCard.vue.js +1 -1
- package/dist/esm/components/CnNotesCard/CnNotesCard.vue2.js.map +1 -1
- package/dist/esm/components/CnNotesCard/CnNotesCard.vue3.js +1 -0
- package/dist/esm/components/CnNotesCard/CnNotesCard.vue3.js.map +1 -1
- package/dist/esm/components/CnNotificationMatrix/CnNotificationMatrix.vue.js +1 -1
- package/dist/esm/components/CnNotificationMatrix/CnNotificationMatrix.vue2.js +21 -2
- package/dist/esm/components/CnNotificationMatrix/CnNotificationMatrix.vue2.js.map +1 -1
- package/dist/esm/components/CnNotificationMatrix/CnNotificationMatrix.vue3.js.map +1 -1
- package/dist/esm/components/CnObjectPartiesWidget/CnObjectPartiesWidget.vue.js +1 -1
- package/dist/esm/components/CnObjectPartiesWidget/CnObjectPartiesWidget.vue2.js +2 -2
- package/dist/esm/components/CnObjectPartiesWidget/CnObjectPartiesWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectPartiesWidget/CnObjectPartiesWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue.js +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnRetentionWidget/CnRetentionWidget.vue.js +1 -1
- package/dist/esm/components/CnRetentionWidget/CnRetentionWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnRetentionWidget/CnRetentionWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue.js +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js.map +1 -1
- package/dist/esm/library-style.js +1 -1
- package/dist/esm/nextcloud-vue.css +634 -301
- package/dist/esm/utils/detailObjectContext.js +7 -2
- package/dist/esm/utils/detailObjectContext.js.map +1 -1
- package/dist/esm/utils/objectParties.js +30 -1
- package/dist/esm/utils/objectParties.js.map +1 -1
- package/dist/esm/utils/validateManifestV2.compiled.js +2 -2
- package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
- package/dist/esm/utils/visibleWhen.js +6 -0
- package/dist/esm/utils/visibleWhen.js.map +1 -1
- package/dist/nextcloud-vue.cjs.js +362 -138
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +634 -301
- package/package.json +1 -1
- package/src/components/CnAiCompanion/CnAiChatPanel.vue +3 -0
- package/src/components/CnChecklistRunWidget/CnChecklistRunWidget.vue +4 -2
- package/src/components/CnDataTable/CnDataTable.vue +19 -2
- package/src/components/CnDetailPage/CnDetailPage.md +1 -0
- package/src/components/CnDetailPage/CnDetailPage.vue +23 -0
- package/src/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue +1 -0
- package/src/components/CnFactsWidget/CnFactsWidget.vue +168 -16
- package/src/components/CnNotesCard/CnNotesCard.vue +7 -2
- package/src/components/CnNotificationMatrix/CnNotificationMatrix.vue +21 -2
- package/src/components/CnObjectPartiesWidget/CnObjectPartiesWidget.vue +2 -1
- package/src/components/CnRecordListWidget/CnRecordListWidget.vue +1 -0
- package/src/components/CnRetentionWidget/CnRetentionWidget.vue +2 -0
- package/src/components/CnTabsWidget/CnTabsWidget.vue +6 -1
- package/src/css/dialog.css +7 -0
- package/src/css/look-board-detail.css +152 -8
- package/src/css/look-board-index.css +78 -0
- package/src/css/look-board.css +33 -3
- package/src/css/table.css +9 -0
- package/src/schemas/app-manifest-v2.schema.json +2 -2
- package/src/utils/detailObjectContext.js +7 -2
- package/src/utils/objectParties.js +29 -0
- package/src/utils/validateManifestV2.compiled.js +2 -2
- package/src/utils/visibleWhen.js +6 -0
|
@@ -2,7 +2,7 @@ import script from './CnDetailWidgetHeaderItems.vue2.js';
|
|
|
2
2
|
import { render } from './CnDetailWidgetHeaderItems.vue3.js';
|
|
3
3
|
|
|
4
4
|
script.render = render;
|
|
5
|
-
script.__scopeId = "data-v-
|
|
5
|
+
script.__scopeId = "data-v-c81df510";
|
|
6
6
|
const __sfc_main = script;
|
|
7
7
|
|
|
8
8
|
export { __sfc_main as default };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CnDetailWidgetHeaderItems.vue2.js","sources":["../../../../src/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue"],"sourcesContent":["<!--\n SPDX-FileCopyrightText: 2026 Conduction B.V.\n SPDX-License-Identifier: EUPL-1.2\n-->\n<template>\n\t<span class=\"cn-detail-widget-header-items\">\n\t\t<CnStatusBadge\n\t\t\tv-if=\"header.pill\"\n\t\t\t:label=\"header.pill.label\"\n\t\t\t:variant=\"header.pill.variant\"\n\t\t\tdata-testid=\"cn-detail-widget-header-pill\" />\n\t\t<span\n\t\t\tv-if=\"header.note\"\n\t\t\tclass=\"cn-detail-page__catalog-note\"\n\t\t\tdata-testid=\"cn-detail-widget-header-note\">{{ header.note }}</span>\n\t\t<template v-for=\"(action, index) in header.actions\" :key=\"`${index}-${action.label}`\">\n\t\t\t<!-- `variant: 'primary'`: the card's main action as a filled button\n\t\t\t (a task table's \"New task\"); otherwise the quiet header link. -->\n\t\t\t<NcButton\n\t\t\t\tv-if=\"action.variant === 'primary'\"\n\t\t\t\tvariant=\"primary\"\n\t\t\t\tclass=\"cn-detail-widget-header-items__primary\"\n\t\t\t\tdata-testid=\"cn-detail-widget-header-action\"\n\t\t\t\t@click=\"action.run()\">\n\t\t\t\t<template v-if=\"action.icon\" #icon>\n\t\t\t\t\t<CnIcon :name=\"action.icon\" :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t{{ action.label }}\n\t\t\t</NcButton>\n\t\t\t<button\n\t\t\t\tv-else\n\t\t\t\ttype=\"button\"\n\t\t\t\tclass=\"cn-detail-page__catalog-action\"\n\t\t\t\t:class=\"{ 'cn-detail-page__catalog-action--add': action.add === true }\"\n\t\t\t\tdata-testid=\"cn-detail-widget-header-action\"\n\t\t\t\t@click=\"action.run()\">\n\t\t\t\t<CnIcon v-if=\"action.icon\" :name=\"action.icon\" :size=\"16\" />\n\t\t\t\t{{ action.label }}\n\t\t\t</button>\n\t\t</template>\n\t</span>\n</template>\n\n<script>\nimport { NcButton } from '@nextcloud/vue'\nimport CnIcon from '../CnIcon/CnIcon.vue'\nimport CnStatusBadge from '../CnStatusBadge/CnStatusBadge.vue'\n\n/**\n * The extras a widget reports for its card's title row through its `header`\n * event: a status pill, a note and its actions. Drawn by CnDetailWidgetHost in\n * the `#actions` slot of the card it wraps a widget in.\n */\nexport default {\n\tname: 'CnDetailWidgetHeaderItems',\n\n\tcomponents: { CnIcon, CnStatusBadge, NcButton },\n\n\tprops: {\n\t\t/** The reported header: `{ pill, note, actions: [{ label, icon?, variant?, add?, run }] }`; `add: true` marks a list's Add. */\n\t\theader: {\n\t\t\ttype: Object,\n\t\t\trequired: true,\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-detail-widget-header-items {\n\tdisplay: inline-flex;\n\tflex-wrap: wrap;\n\talign-items: center;\n\tgap: 12px;\n}\n\n.cn-detail-page__catalog-action {\n\talign-items: center;\n\tbackground: var(--color-primary-element-light);\n\tborder: 0;\n\tborder-radius: 16px;\n\tcolor: var(--color-primary-element-light-text, var(--color-primary-element));\n\tcursor: pointer;\n\tdisplay: inline-flex;\n\tfont: inherit;\n\tfont-size: 13px;\n\tfont-weight: 700;\n\tgap: 6px;\n\tmin-height: 32px;\n\tpadding: 0 14px;\n\twhite-space: nowrap;\n}\n</style>\n"],"names":["CnIcon","CnStatusBadge"],"mappings":";;;;AAgDA;;AAEC;AACA;;AAED,aAAe;AACd,CAAA,IAAI,EAAE,2BAA2B;;AAEjC,CAAA,UAAU,EAAE,UAAEA,UAAM,iBAAEC,YAAa,EAAE,UAAU;;AAE/C,CAAA,KAAK,EAAE;;AAEN,EAAA,MAAM,EAAE;GACP,IAAI,EAAE,MAAM;GACZ,QAAQ,EAAE,IAAI;GACd;EACD;AACF;;;;"}
|
|
1
|
+
{"version":3,"file":"CnDetailWidgetHeaderItems.vue2.js","sources":["../../../../src/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue"],"sourcesContent":["<!--\n SPDX-FileCopyrightText: 2026 Conduction B.V.\n SPDX-License-Identifier: EUPL-1.2\n-->\n<template>\n\t<span class=\"cn-detail-widget-header-items\">\n\t\t<CnStatusBadge\n\t\t\tv-if=\"header.pill\"\n\t\t\t:label=\"header.pill.label\"\n\t\t\t:variant=\"header.pill.variant\"\n\t\t\tdata-testid=\"cn-detail-widget-header-pill\" />\n\t\t<span\n\t\t\tv-if=\"header.note\"\n\t\t\tclass=\"cn-detail-page__catalog-note\"\n\t\t\tdata-testid=\"cn-detail-widget-header-note\">{{ header.note }}</span>\n\t\t<template v-for=\"(action, index) in header.actions\" :key=\"`${index}-${action.label}`\">\n\t\t\t<!-- `variant: 'primary'`: the card's main action as a filled button\n\t\t\t (a task table's \"New task\"); otherwise the quiet header link. -->\n\t\t\t<NcButton\n\t\t\t\tv-if=\"action.variant === 'primary'\"\n\t\t\t\tvariant=\"primary\"\n\t\t\t\tclass=\"cn-detail-widget-header-items__primary\"\n\t\t\t\tdata-testid=\"cn-detail-widget-header-action\"\n\t\t\t\t@click=\"action.run()\">\n\t\t\t\t<template v-if=\"action.icon\" #icon>\n\t\t\t\t\t<CnIcon :name=\"action.icon\" :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t{{ action.label }}\n\t\t\t</NcButton>\n\t\t\t<button\n\t\t\t\tv-else\n\t\t\t\ttype=\"button\"\n\t\t\t\tclass=\"cn-detail-page__catalog-action\"\n\t\t\t\t:class=\"{ 'cn-detail-page__catalog-action--add': action.add === true }\"\n\t\t\t\tdata-testid=\"cn-detail-widget-header-action\"\n\t\t\t\t@click=\"action.run()\">\n\t\t\t\t<CnIcon v-if=\"action.icon\" :name=\"action.icon\" :size=\"16\" />\n\t\t\t\t{{ action.label }}\n\t\t\t</button>\n\t\t</template>\n\t</span>\n</template>\n\n<script>\nimport { NcButton } from '@nextcloud/vue'\nimport CnIcon from '../CnIcon/CnIcon.vue'\nimport CnStatusBadge from '../CnStatusBadge/CnStatusBadge.vue'\n\n/**\n * The extras a widget reports for its card's title row through its `header`\n * event: a status pill, a note and its actions. Drawn by CnDetailWidgetHost in\n * the `#actions` slot of the card it wraps a widget in.\n */\nexport default {\n\tname: 'CnDetailWidgetHeaderItems',\n\n\tcomponents: { CnIcon, CnStatusBadge, NcButton },\n\n\tprops: {\n\t\t/** The reported header: `{ pill, note, actions: [{ label, icon?, variant?, add?, run }] }`; `add: true` marks a list's Add. */\n\t\theader: {\n\t\t\ttype: Object,\n\t\t\trequired: true,\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-detail-widget-header-items {\n\tdisplay: inline-flex;\n\tflex-wrap: wrap;\n\talign-items: center;\n\tgap: 12px;\n}\n\n.cn-detail-page__catalog-action {\n\talign-items: center;\n\tbackground: var(--color-primary-element-light);\n\tborder: 0;\n\tborder-radius: 16px;\n\tcolor: var(--color-primary-element-light-text, var(--color-primary-element));\n\tcursor: pointer;\n\tdisplay: inline-flex;\n\tfont: inherit;\n\tfont-size: 13px;\n\tfont-weight: 700;\n\tgap: 6px;\n\tmargin: 0;\n\tmin-height: 32px;\n\tpadding: 0 14px;\n\twhite-space: nowrap;\n}\n</style>\n"],"names":["CnIcon","CnStatusBadge"],"mappings":";;;;AAgDA;;AAEC;AACA;;AAED,aAAe;AACd,CAAA,IAAI,EAAE,2BAA2B;;AAEjC,CAAA,UAAU,EAAE,UAAEA,UAAM,iBAAEC,YAAa,EAAE,UAAU;;AAE/C,CAAA,KAAK,EAAE;;AAEN,EAAA,MAAM,EAAE;GACP,IAAI,EAAE,MAAM;GACZ,QAAQ,EAAE,IAAI;GACd;EACD;AACF;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CnDetailWidgetHeaderItems.vue3.js","sources":["../../../../src/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue?vue&type=template&id=
|
|
1
|
+
{"version":3,"file":"CnDetailWidgetHeaderItems.vue3.js","sources":["../../../../src/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue?vue&type=template&id=c81df510&lang.js"],"sourcesContent":["<!--\n SPDX-FileCopyrightText: 2026 Conduction B.V.\n SPDX-License-Identifier: EUPL-1.2\n-->\n<template>\n\t<span class=\"cn-detail-widget-header-items\">\n\t\t<CnStatusBadge\n\t\t\tv-if=\"header.pill\"\n\t\t\t:label=\"header.pill.label\"\n\t\t\t:variant=\"header.pill.variant\"\n\t\t\tdata-testid=\"cn-detail-widget-header-pill\" />\n\t\t<span\n\t\t\tv-if=\"header.note\"\n\t\t\tclass=\"cn-detail-page__catalog-note\"\n\t\t\tdata-testid=\"cn-detail-widget-header-note\">{{ header.note }}</span>\n\t\t<template v-for=\"(action, index) in header.actions\" :key=\"`${index}-${action.label}`\">\n\t\t\t<!-- `variant: 'primary'`: the card's main action as a filled button\n\t\t\t (a task table's \"New task\"); otherwise the quiet header link. -->\n\t\t\t<NcButton\n\t\t\t\tv-if=\"action.variant === 'primary'\"\n\t\t\t\tvariant=\"primary\"\n\t\t\t\tclass=\"cn-detail-widget-header-items__primary\"\n\t\t\t\tdata-testid=\"cn-detail-widget-header-action\"\n\t\t\t\t@click=\"action.run()\">\n\t\t\t\t<template v-if=\"action.icon\" #icon>\n\t\t\t\t\t<CnIcon :name=\"action.icon\" :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t{{ action.label }}\n\t\t\t</NcButton>\n\t\t\t<button\n\t\t\t\tv-else\n\t\t\t\ttype=\"button\"\n\t\t\t\tclass=\"cn-detail-page__catalog-action\"\n\t\t\t\t:class=\"{ 'cn-detail-page__catalog-action--add': action.add === true }\"\n\t\t\t\tdata-testid=\"cn-detail-widget-header-action\"\n\t\t\t\t@click=\"action.run()\">\n\t\t\t\t<CnIcon v-if=\"action.icon\" :name=\"action.icon\" :size=\"16\" />\n\t\t\t\t{{ action.label }}\n\t\t\t</button>\n\t\t</template>\n\t</span>\n</template>\n\n<script>\nimport { NcButton } from '@nextcloud/vue'\nimport CnIcon from '../CnIcon/CnIcon.vue'\nimport CnStatusBadge from '../CnStatusBadge/CnStatusBadge.vue'\n\n/**\n * The extras a widget reports for its card's title row through its `header`\n * event: a status pill, a note and its actions. Drawn by CnDetailWidgetHost in\n * the `#actions` slot of the card it wraps a widget in.\n */\nexport default {\n\tname: 'CnDetailWidgetHeaderItems',\n\n\tcomponents: { CnIcon, CnStatusBadge, NcButton },\n\n\tprops: {\n\t\t/** The reported header: `{ pill, note, actions: [{ label, icon?, variant?, add?, run }] }`; `add: true` marks a list's Add. */\n\t\theader: {\n\t\t\ttype: Object,\n\t\t\trequired: true,\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-detail-widget-header-items {\n\tdisplay: inline-flex;\n\tflex-wrap: wrap;\n\talign-items: center;\n\tgap: 12px;\n}\n\n.cn-detail-page__catalog-action {\n\talign-items: center;\n\tbackground: var(--color-primary-element-light);\n\tborder: 0;\n\tborder-radius: 16px;\n\tcolor: var(--color-primary-element-light-text, var(--color-primary-element));\n\tcursor: pointer;\n\tdisplay: inline-flex;\n\tfont: inherit;\n\tfont-size: 13px;\n\tfont-weight: 700;\n\tgap: 6px;\n\tmargin: 0;\n\tmin-height: 32px;\n\tpadding: 0 14px;\n\twhite-space: nowrap;\n}\n</style>\n"],"names":["_createBlock","_openBlock","_createElementBlock","_toDisplayString","_createVNode","_normalizeClass"],"mappings":";;AASO,MAAA,UAAA,GAAA,EAAA,KAAK,EAAC,+BAAmB,GAAA;;;OAQxB,EAAC,8BAA8B;AACpC,EAAA,aAAQ,EAAA,8BAAA;;;;;;;;;;AAPL,IAAA,CAAA,MAAA,CAAA,MAAA,CAAA,IAAA;sBADHA,WAI8C,CAAA,wBAAA,EAAA;;AAF7C,UAAA,KAAK,EAAE,MAAA,CAAA,MAAM,CAAC,IAAE,CAAA,KAAA;AAChB,UAAA,OAAO,EAAE,MAAA,CAAA,MAAM,CAAC,IAAI,CAAC,OAAO;AAC7B,UAAA,aAAW,EAAC,8BAA8B;;;AAEpC,IAAA,CAAA,MAAA,CAAA,MAAM,CAAC,IAAI;AADlB,SAAAC,SAAA,EAAA,EAAAC,kBAAA,CAGS,MAHT,EAAA,UAGS,EAAAC,eAAA,CAAA,MAAA,CAAA,MAAA,CAAA,IAAA,CAAA,EAAA,CAAA,YAAA;;AACP,KAAAF,SAAA,CAAA,IAAA,CAAA,EAAAC,kBAAA,4BAAkC,MAAA,CAAA,MAAA,CAAA,OAAA,EAAlB,CAAA,MAAM,EAAG,KAAI,KAAA;;gBAAK,KAAA,CAAA,CAAA,EAAA,MAAA,CAAA,KAAA,CAAA,CAAA;;AAI5B,QAAA,CAAA,MAAM,CAAC,OAAO,KAAA,SAAA;0BADpBF,WAUU,CAAA,mBAAA,EAAA;;AARV,cAAA,OAAO,EAAC,SAAS;AAChB,cAAA,KAAI,EAAC,wCAAmC;AACzC,cAAA,aAAU,EAAA,gCAAA;cACT,OAAK,EAAA,MAAA,KAAE,MAAM,IAAG,EAAA,CAAA;;+BAGZ,MACL;gCADK,GACL,GAAAG,eAAA,CAAG,MAAM,CAAC,KAAE,CAAA,EAAA,CAAA,YAAA;;;;AAHH,cAAA,CAAA,MAAA,CAAA,IAAA;;0BAAA,MAAA;gCACR,MAAI;sBAAJC,WAAI,CAAA,iBAAA,EAAA;wBAAA,IAAA,EAAA,MAAA,CAAA,IAAA;AAAA,wBAAA,IAAA,EAAA,EAAA;;;;;;;0BAILF;;AAEA,cAAA,IAAI,EAAC,QAAQ;AACb,cAAA,KAAK,EAACG,cAAA,CAAA,CAAA,gCAAgC,EACrB,EAAA,qCAAA,EAAA,MAAA,CAAA,GAAA,KAAA,IAAA,EAAA,CAAA,CAAA;AACjB,cAAA,aAAO,EAAA,gCAAA;cACN,OAAK,EAAA,MAAA,KAAE,MAAA,CAAA,GAAA,EAAA,CAAA;;AACL,cAAA,CAAA,MAAA,CAAA,IAAA;gCAAHL,WAAG,CAAA,iBAAA,EAAA;;oBAAA,IAAA,EAAA,MAAA,CAAA,IAAA;AAAA,oBAAA,IAAA,EAAA,EAAA;;;8BAAA;;;;;;;;;"}
|
|
@@ -3,7 +3,7 @@ export { FACTS_REVEAL_CHANNEL } from './CnFactsWidget.vue2.js';
|
|
|
3
3
|
import { render } from './CnFactsWidget.vue3.js';
|
|
4
4
|
|
|
5
5
|
script.render = render;
|
|
6
|
-
script.__scopeId = "data-v-
|
|
6
|
+
script.__scopeId = "data-v-6351bc64";
|
|
7
7
|
const __sfc_main = script;
|
|
8
8
|
|
|
9
9
|
export { __sfc_main as default };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getCurrentUser } from '@nextcloud/auth';
|
|
2
2
|
import { subscribe, unsubscribe, emit } from '@nextcloud/event-bus';
|
|
3
3
|
import { formatFileSize } from '@nextcloud/files';
|
|
4
|
-
import { translate } from '@nextcloud/l10n';
|
|
4
|
+
import { translate, translatePlural } from '@nextcloud/l10n';
|
|
5
5
|
import { generateUrl } from '@nextcloud/router';
|
|
6
6
|
import { NcLoadingIcon, NcNoteCard } from '@nextcloud/vue';
|
|
7
7
|
import Check from 'vue-material-design-icons/Check.vue';
|
|
@@ -20,6 +20,7 @@ import { parseDateValue } from '../../utils/dateVariant.js';
|
|
|
20
20
|
import { fetchListTotal } from '../../utils/fetchFilterCounts.js';
|
|
21
21
|
import { fillTemplate, formatLongDate } from '../../utils/fillTemplate.js';
|
|
22
22
|
import { metricLocale, formatMoney, unwrapAppConfig } from '../../utils/formatMetric.js';
|
|
23
|
+
import { groupDisplayName, loadGroupDisplayName } from '../../utils/groupAutocomplete.js';
|
|
23
24
|
import { readPath } from '../../utils/readPath.js';
|
|
24
25
|
import { resolveDeepTokens, hasUnresolvedDeepTokens } from '../../utils/resolveFilterTokens.js';
|
|
25
26
|
import { userDisplayName } from '../../utils/userDisplayName.js';
|
|
@@ -63,6 +64,30 @@ function resolveSourceTokens(value, record) {
|
|
|
63
64
|
}
|
|
64
65
|
|
|
65
66
|
/** Kinds of entry a `fields[]` item can be. A labelled item without `as` is a row. */
|
|
67
|
+
/**
|
|
68
|
+
* Two or more pills in a row become one `pills` block, drawn on one line.
|
|
69
|
+
*
|
|
70
|
+
* @param {Array<object>} blocks The blocks in order.
|
|
71
|
+
* @return {Array<object>}
|
|
72
|
+
* @spec openspec/changes/facts-fields-from-context/specs/facts-widget/spec.md#requirement-a-facts-card-can-take-its-entries-from-the-page-context
|
|
73
|
+
*/
|
|
74
|
+
function groupPills(blocks) {
|
|
75
|
+
const out = [];
|
|
76
|
+
blocks.forEach((block) => {
|
|
77
|
+
const last = out[out.length - 1];
|
|
78
|
+
if (block.kind !== 'pill') {
|
|
79
|
+
out.push(block);
|
|
80
|
+
} else if (last && last.kind === 'pills') {
|
|
81
|
+
last.pills.push(block);
|
|
82
|
+
} else if (last && last.kind === 'pill') {
|
|
83
|
+
out[out.length - 1] = { kind: 'pills', key: `pills-${last.key}`, pills: [last, block] };
|
|
84
|
+
} else {
|
|
85
|
+
out.push(block);
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
return out
|
|
89
|
+
}
|
|
90
|
+
|
|
66
91
|
const KINDS = Object.freeze(['row', 'title', 'line', 'pill', 'lead', 'text', 'meter', 'progress']);
|
|
67
92
|
|
|
68
93
|
/** The schemes a facts link opens, besides a path on this server. */
|
|
@@ -193,31 +218,34 @@ var script = {
|
|
|
193
218
|
/**
|
|
194
219
|
* The widget configuration.
|
|
195
220
|
*
|
|
196
|
-
* - `fields` — the entries, in order. Each is `{ path, label?, as?, from?, format?, map?, itemPath?, parts?, separator?, route?, variant?, variantMap?, colorMap?, icon?, copy?, reveal?, text?, title?, subtitle?, initialsPath?, tone? }`.
|
|
221
|
+
* - `fields` — the entries, in order. Each is `{ path, label?, as?, from?, format?, map?, itemPath?, parts?, separator?, route?, variant?, variantMap?, colorMap?, icon?, copy?, reveal?, inline?, text?, title?, subtitle?, initialsPath?, tone? }`.
|
|
197
222
|
* `as` is `row` (default when `label` or `icon` is set), `title`, `line`, `text` (a line in the normal ink), `lead` (an icon tile or initials beside `title` and `subtitle`), `pill` or `meter`.
|
|
198
223
|
* `countFrom` (`{ register, schema, filter? }`, `@objectId` / `@object.<field>` in the filter) shows how many records that list holds ("Lopende zaken 43"); the row is left out while the count cannot be read.
|
|
199
224
|
* A `meter` shows the amount at `path` against the limit at `limitPath` (or a constant `limit`) as "12 of 50" with a bar; past the limit the bar turns red and the text says "over the limit"; without a positive limit it shows the amount and no bar.
|
|
225
|
+
* A row with `inline: true` spans both columns as one line, the label, the value and its buttons side by side (a masked BSN with Show).
|
|
200
226
|
* A row's `format` may also be `email`, `phone` or `url` (a link) or `masked` (the last four characters; `reveal: true` adds Show, which unmasks the record's value; `reveal: { url, path? }` makes Show ask the server for the value at `url` (tokens resolved), read at `path` (else the entry's path), so a server that answers the mask can check and record the reveal). `copy: true` adds a copy button; `icon` replaces the label.
|
|
201
227
|
* A part may be `{ text }`, a constant; a `line` or `text` entry without `path` or `parts` shows its `text`.
|
|
202
228
|
* `resolve: { register, schema, labelField? }` on an entry or a part turns a value that is a reference (an id, or a list of ids) into the label of the referenced object (`labelField`, else `title`, then `name`): the case type or status of a task shows its name, not its uuid. The ids are fetched once per register and schema through the object store and shared by every facts widget on the page; the entry stays empty until its label is known, and when no label can be read. A resolved value works as a pill too: `map` is applied to the resolved label, and `variantMap` / `colorMap` look the tone up by the value of `resolve.toneField` on the referenced object when that is set (a status named by its `name`, coloured by its `state`), then by the resolved label, then by the stored value.
|
|
203
229
|
* `route` (`{ name, params?, query? }`, `@source.<path>` in a param) on a `title` or a `row` links its value to that route; a param that does not fill leaves it plain.
|
|
204
230
|
* `format: 'user'` shows a Nextcloud user id as the user's display name, read once per id; the entry stays empty until the name is known.
|
|
205
|
-
* `template` ("{available} {unit}") fills its `{path}` placeholders from the record instead of reading `path
|
|
231
|
+
* `template` ("{available} {unit}") fills its `{path}` placeholders from the record instead of reading `path` (`{path:format}` formats one, "{from:year}"); it is empty when every placeholder is. `suffix` (" kg") is added to a value that is not empty, its words translated.
|
|
206
232
|
* `labelPath` ("@context.caseType.handlerLabel") names a value on the record or the page's `@context` records that labels the row when it holds text; `label` is the fallback.
|
|
207
233
|
* `emptyValue` ("No") is shown, translated, when the entry has no value, so the entry stays drawn whatever `hideEmpty` says (an override that was never set reads "No").
|
|
208
234
|
* - `action` — an action drawn as a button under the facts; `headerAction` — one drawn in the card header (reported through the `header` event).
|
|
209
235
|
* - `actions` — action buttons under the facts in the `headerActions` shape (`api-call`, `open-form`, `navigate`, `open-modal`, ...; `confirm`, `variant`). `@source.<field>` names a field of the record shown, and an action whose token names an empty field is not drawn. `visibleWhen` reads the record shown; `adminOnly: true` draws the action for an instance admin only (visibility, never authorisation). An api-call or a saved form refreshes the page, and the facts read their source again.
|
|
236
|
+
* - `fieldsFrom` — `@context.<name>.<path>`, a list of entries on a record the page reads beside this one (a case type's `requestFields`); when it holds entries they are drawn instead of `fields`.
|
|
210
237
|
* - `rowsPath` — a path to a list of `{ label, value }` the record holds, drawn as rows after `fields` (a preview the server builds).
|
|
211
238
|
* - `headerPill` — a status pill in the card header (reported through the `header` event): `{ path?, text?, map?, variant?, variantMap?, colorMap? }`, read from the record like a `pill` entry (DqBezwaar "Advies ontvangen"); nothing shows while the value is empty.
|
|
212
239
|
* - `notice` — `{ text, variant? }`, a note band inside the card under the facts (`info` by default; `success`, `warning` or `error`); the text is translated.
|
|
213
|
-
*
|
|
240
|
+
* - `footnote` — a plain muted line under the facts, without a band (DqZaakBesluiten "Na het ondertekenen ..."); the text is translated.
|
|
241
|
+
* `format` is `text` (default), `date` (board short date), `date-long` (always with the year), `longdate` (the month written out, the year only outside this year: "3 oktober"), `year` ("2026"), `list` (an array joined by ", ", each item read at `itemPath` and written in `itemFormat`), `group` (a Nextcloud group by its display name), `bytes` (a size, "1.5 MB"), `number` (in the reader's language, `decimals` fraction digits when set), `months` (a number of months in words, whole years as years: 240 is "20 jaar") or `currency` (a money amount in the reader's language, "€ 1.234,50": the code in `currency`, else the record's `currencyField`, else the app's reporting currency, else EUR; `decimals` defaults to 2).
|
|
214
242
|
* `map` turns a raw value into a label (translated). `parts` (on a `line`) lists paths, or `{ path, label?, format? }`, joined by `separator` (default " · "); empty parts are dropped.
|
|
215
243
|
* - `source` — `{ register, schema, id }` or `{ url }`; omitted = the current object. `{ register, schema, filter, sort? }` without `id` reads the first object that matches `filter` in `sort` order (`{ field, dir }`): the latest count of a shift. An entry with `from: "object"` reads the current object even then (a client card that also shows the ticket's channel).
|
|
216
244
|
* - `endpointSource` — `{ url, method?, params?, responsePath? }`, the block a stat or chart takes: the facts read an app endpoint, shared and cached like those.
|
|
217
245
|
* - `emptyWhen` — a path; when the record's value there is truthy the card shows `emptyText` (an endpoint that answers `empty: true`).
|
|
218
246
|
* - `link` — `{ label, route? | href? }` at the foot. `{ label, icon?, sidebarTab }` instead opens the page's object sidebar on that tab (no link without a sidebar).
|
|
219
247
|
* - `hideEmpty` — drop an entry whose value is empty (default true).
|
|
220
|
-
* - `columns` — `2` lays the rows out in two columns with the label above the value (board DqContact); a row with `parts` joins them like a line (an address on one row).
|
|
248
|
+
* - `columns` — `2` lays the rows out in two columns with the label above the value (board DqContact); a row with `parts` joins them like a line (an address on one row). `1` stacks each label above its value in one column, for a narrow card with long labels (board DqHandhaving "Afwijking en definitief").
|
|
221
249
|
* - `emptyText` — shown when no entry has a value.
|
|
222
250
|
*
|
|
223
251
|
* @type {{fields?: Array<object>, source?: object, link?: object, hideEmpty?: boolean, emptyText?: string}}
|
|
@@ -269,6 +297,29 @@ var script = {
|
|
|
269
297
|
},
|
|
270
298
|
|
|
271
299
|
computed: {
|
|
300
|
+
/**
|
|
301
|
+
* The entries to draw: the list `fieldsFrom` names on the page's
|
|
302
|
+
* `@context` records when it holds entries (a case type's
|
|
303
|
+
* `requestFields`), else `fields`.
|
|
304
|
+
*
|
|
305
|
+
* @return {Array<object>}
|
|
306
|
+
* @spec openspec/changes/facts-fields-from-context/specs/facts-widget/spec.md#requirement-a-facts-card-can-take-its-entries-from-the-page-context
|
|
307
|
+
*/
|
|
308
|
+
entries() {
|
|
309
|
+
const from = this.content?.fieldsFrom;
|
|
310
|
+
if (typeof from === 'string' && from.startsWith('@context.')) {
|
|
311
|
+
const rows = this.cnDetailVisibilityRows && typeof this.cnDetailVisibilityRows === 'object' && 'value' in this.cnDetailVisibilityRows
|
|
312
|
+
? this.cnDetailVisibilityRows.value
|
|
313
|
+
: this.cnDetailVisibilityRows;
|
|
314
|
+
const named = readPath({ '@context': rows || {} }, from);
|
|
315
|
+
const list = Array.isArray(named) ? named.filter((entry) => entry && typeof entry === 'object' && !Array.isArray(entry)) : [];
|
|
316
|
+
if (list.length > 0) {
|
|
317
|
+
return list
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
return Array.isArray(this.content?.fields) ? this.content.fields : []
|
|
321
|
+
},
|
|
322
|
+
|
|
272
323
|
/**
|
|
273
324
|
* Whether the rows sit in two columns, label above value.
|
|
274
325
|
*
|
|
@@ -279,6 +330,15 @@ var script = {
|
|
|
279
330
|
return Number(this.content?.columns) === 2
|
|
280
331
|
},
|
|
281
332
|
|
|
333
|
+
/**
|
|
334
|
+
* Whether the rows stack in one column, label above value.
|
|
335
|
+
*
|
|
336
|
+
* @return {boolean}
|
|
337
|
+
*/
|
|
338
|
+
stacked() {
|
|
339
|
+
return Number(this.content?.columns) === 1
|
|
340
|
+
},
|
|
341
|
+
|
|
282
342
|
/**
|
|
283
343
|
* The token context: the detail object (prop, else the injected context)
|
|
284
344
|
* and the page workspace.
|
|
@@ -304,7 +364,7 @@ var script = {
|
|
|
304
364
|
* @spec openspec/changes/facts-entry-count/specs/facts-widget/spec.md#requirement-a-facts-entry-can-count-a-related-list
|
|
305
365
|
*/
|
|
306
366
|
countJobsKey() {
|
|
307
|
-
const fields =
|
|
367
|
+
const fields = this.entries;
|
|
308
368
|
const keys = fields
|
|
309
369
|
.filter((field) => field && field.countFrom && typeof field.countFrom === 'object' && field.countFrom.register && field.countFrom.schema)
|
|
310
370
|
.map((field) => this.countKey(field.countFrom));
|
|
@@ -465,7 +525,7 @@ var script = {
|
|
|
465
525
|
*/
|
|
466
526
|
blocks() {
|
|
467
527
|
const sourceRecord = this.record;
|
|
468
|
-
const fields =
|
|
528
|
+
const fields = this.entries;
|
|
469
529
|
// A source that finds nothing still leaves the entries that read the
|
|
470
530
|
// page's own object (`from: "object"`).
|
|
471
531
|
const ownEntries = Boolean(this.objectData) && fields.some((field) => field && field.from === 'object');
|
|
@@ -494,7 +554,7 @@ var script = {
|
|
|
494
554
|
}
|
|
495
555
|
if (kind === 'row') {
|
|
496
556
|
const last = out[out.length - 1];
|
|
497
|
-
const row = { key, label: this.labelOf(record, field), value, ...this.rowExtras(record, field, value) };
|
|
557
|
+
const row = { key, label: this.labelOf(record, field), value, inline: field.inline === true, ...this.rowExtras(record, field, value) };
|
|
498
558
|
if (field.route && !row.href) {
|
|
499
559
|
row.to = this.resolveRoute(field.route, record);
|
|
500
560
|
}
|
|
@@ -544,7 +604,7 @@ var script = {
|
|
|
544
604
|
out.push({ kind: 'rows', key: 'rows-answered', rows: [row] });
|
|
545
605
|
}
|
|
546
606
|
});
|
|
547
|
-
return out
|
|
607
|
+
return groupPills(out)
|
|
548
608
|
},
|
|
549
609
|
|
|
550
610
|
/**
|
|
@@ -636,6 +696,12 @@ var script = {
|
|
|
636
696
|
return { text, type: ['success', 'warning', 'error'].includes(notice.variant) ? notice.variant : 'info' }
|
|
637
697
|
},
|
|
638
698
|
|
|
699
|
+
/** @return {string} The translated footnote, or '' when none is set. */
|
|
700
|
+
footnote() {
|
|
701
|
+
const footnote = this.content?.footnote;
|
|
702
|
+
return typeof footnote === 'string' && footnote.trim() !== '' ? this.tr(footnote) : ''
|
|
703
|
+
},
|
|
704
|
+
|
|
639
705
|
/** @return {string} The reveal button's text. */
|
|
640
706
|
showLabel() {
|
|
641
707
|
return translate('nextcloud-vue', 'Show')
|
|
@@ -873,7 +939,7 @@ var script = {
|
|
|
873
939
|
* @spec openspec/changes/facts-entry-count/specs/facts-widget/spec.md#requirement-a-facts-entry-can-count-a-related-list
|
|
874
940
|
*/
|
|
875
941
|
async loadCounts() {
|
|
876
|
-
const fields =
|
|
942
|
+
const fields = this.entries;
|
|
877
943
|
const seen = new Set();
|
|
878
944
|
for (const field of fields) {
|
|
879
945
|
const countFrom = field && field.countFrom;
|
|
@@ -899,7 +965,12 @@ var script = {
|
|
|
899
965
|
if (value === '') {
|
|
900
966
|
return typeof field.emptyValue === 'string' && field.emptyValue !== '' ? this.tr(field.emptyValue) : ''
|
|
901
967
|
}
|
|
902
|
-
|
|
968
|
+
if (typeof field.suffix !== 'string') {
|
|
969
|
+
return value
|
|
970
|
+
}
|
|
971
|
+
// The words of a suffix are translated; its leading space stays as written.
|
|
972
|
+
const lead = field.suffix.match(/^\s*/)[0];
|
|
973
|
+
return `${value}${lead}${this.tr(field.suffix.slice(lead.length))}`
|
|
903
974
|
},
|
|
904
975
|
|
|
905
976
|
/**
|
|
@@ -945,8 +1016,8 @@ var script = {
|
|
|
945
1016
|
*/
|
|
946
1017
|
templateValue(record, template) {
|
|
947
1018
|
let filled = false;
|
|
948
|
-
const text = this.tr(template).replace(/\{([\w.@]+)\}/g, (match, path) => {
|
|
949
|
-
const value = this.format(readPath(record, path), {}, record);
|
|
1019
|
+
const text = this.tr(template).replace(/\{([\w.@]+)(?::([\w-]+))?\}/g, (match, path, format) => {
|
|
1020
|
+
const value = this.format(readPath(record, path), format ? { format } : {}, record);
|
|
950
1021
|
filled = filled || value !== '';
|
|
951
1022
|
return value
|
|
952
1023
|
});
|
|
@@ -1338,7 +1409,7 @@ var script = {
|
|
|
1338
1409
|
* @return {Array<{spec: object, raw: unknown}>}
|
|
1339
1410
|
*/
|
|
1340
1411
|
refSpecs(record) {
|
|
1341
|
-
const fields =
|
|
1412
|
+
const fields = this.entries;
|
|
1342
1413
|
const specs = [];
|
|
1343
1414
|
const visit = (spec) => {
|
|
1344
1415
|
if (!spec || typeof spec !== 'object') {
|
|
@@ -1567,10 +1638,14 @@ var script = {
|
|
|
1567
1638
|
if (format === 'list' || Array.isArray(raw)) {
|
|
1568
1639
|
const items = (Array.isArray(raw) ? raw : [raw])
|
|
1569
1640
|
.map((item) => (spec.itemPath && item && typeof item === 'object' ? readPath(item, spec.itemPath) : item))
|
|
1570
|
-
.map((item) => this.format(item, { ...spec, format: 'text' }))
|
|
1641
|
+
.map((item) => this.format(item, { ...spec, format: spec.itemFormat || 'text' }))
|
|
1571
1642
|
.filter((item) => item !== '');
|
|
1572
1643
|
return items.join(', ')
|
|
1573
1644
|
}
|
|
1645
|
+
if (format === 'year') {
|
|
1646
|
+
const date = parseDateValue(raw);
|
|
1647
|
+
return date === null ? '' : String(date.getFullYear())
|
|
1648
|
+
}
|
|
1574
1649
|
// The month written out, the year only outside this year: "3 oktober".
|
|
1575
1650
|
if (format === 'longdate') {
|
|
1576
1651
|
return formatLongDate(raw)
|
|
@@ -1585,6 +1660,16 @@ var script = {
|
|
|
1585
1660
|
? formatBoardDate(date, new Date(date.getFullYear() + 1, 0, 1))
|
|
1586
1661
|
: formatBoardDate(date)
|
|
1587
1662
|
}
|
|
1663
|
+
// A number of months in words: whole years as years ("20 jaar"), else months.
|
|
1664
|
+
if (format === 'months') {
|
|
1665
|
+
const months = Number(raw);
|
|
1666
|
+
if (typeof raw === 'object' || !Number.isInteger(months) || months < 0) {
|
|
1667
|
+
return typeof raw === 'object' ? '' : String(raw)
|
|
1668
|
+
}
|
|
1669
|
+
return months > 0 && months % 12 === 0
|
|
1670
|
+
? translatePlural('nextcloud-vue', '%n year', '%n years', months / 12)
|
|
1671
|
+
: translatePlural('nextcloud-vue', '%n month', '%n months', months)
|
|
1672
|
+
}
|
|
1588
1673
|
if (format === 'bytes') {
|
|
1589
1674
|
const bytes = Number(raw);
|
|
1590
1675
|
return Number.isFinite(bytes) && bytes >= 0 ? formatFileSize(bytes) : ''
|
|
@@ -1592,6 +1677,18 @@ var script = {
|
|
|
1592
1677
|
if (format === 'user') {
|
|
1593
1678
|
return userDisplayName(raw)
|
|
1594
1679
|
}
|
|
1680
|
+
// A Nextcloud group by its display name; the id until the name is known.
|
|
1681
|
+
if (format === 'group') {
|
|
1682
|
+
if (typeof raw === 'object') {
|
|
1683
|
+
return ''
|
|
1684
|
+
}
|
|
1685
|
+
const name = groupDisplayName(String(raw));
|
|
1686
|
+
if (name === null) {
|
|
1687
|
+
loadGroupDisplayName(String(raw));
|
|
1688
|
+
return String(raw)
|
|
1689
|
+
}
|
|
1690
|
+
return name
|
|
1691
|
+
}
|
|
1595
1692
|
if (format === 'number') {
|
|
1596
1693
|
const number = Number(raw);
|
|
1597
1694
|
if (typeof raw === 'object' || !Number.isFinite(number)) {
|