@conduction/nextcloud-vue 2.119.0 → 2.121.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/CnAiFeaturesWidget/CnAiFeaturesWidget.vue.js +9 -0
- package/dist/esm/components/CnAiFeaturesWidget/CnAiFeaturesWidget.vue.js.map +1 -0
- package/dist/esm/components/CnAiFeaturesWidget/CnAiFeaturesWidget.vue2.js +226 -0
- package/dist/esm/components/CnAiFeaturesWidget/CnAiFeaturesWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnAiFeaturesWidget/CnAiFeaturesWidget.vue3.js +211 -0
- package/dist/esm/components/CnAiFeaturesWidget/CnAiFeaturesWidget.vue3.js.map +1 -0
- package/dist/esm/components/CnAiFeaturesWidget/CnAiSuggestionDecision.vue.js +9 -0
- package/dist/esm/components/CnAiFeaturesWidget/CnAiSuggestionDecision.vue.js.map +1 -0
- package/dist/esm/components/CnAiFeaturesWidget/CnAiSuggestionDecision.vue2.js +64 -0
- package/dist/esm/components/CnAiFeaturesWidget/CnAiSuggestionDecision.vue2.js.map +1 -0
- package/dist/esm/components/CnAiFeaturesWidget/CnAiSuggestionDecision.vue3.js +89 -0
- package/dist/esm/components/CnAiFeaturesWidget/CnAiSuggestionDecision.vue3.js.map +1 -0
- package/dist/esm/components/CnIcon/semanticIcons.js +2 -2
- package/dist/esm/components/CnIcon/semanticIcons.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +53 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +546 -523
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/useNamedSource.js +9 -0
- package/dist/esm/components/CnIndexPage/useNamedSource.js.map +1 -1
- package/dist/esm/components/CnObjectPermissionsTab/CnObjectPermissionsTab.vue.js +9 -0
- package/dist/esm/components/CnObjectPermissionsTab/CnObjectPermissionsTab.vue.js.map +1 -0
- package/dist/esm/components/CnObjectPermissionsTab/CnObjectPermissionsTab.vue2.js +257 -0
- package/dist/esm/components/CnObjectPermissionsTab/CnObjectPermissionsTab.vue2.js.map +1 -0
- package/dist/esm/components/CnObjectPermissionsTab/CnObjectPermissionsTab.vue3.js +266 -0
- package/dist/esm/components/CnObjectPermissionsTab/CnObjectPermissionsTab.vue3.js.map +1 -0
- package/dist/esm/components/CnObjectSidebar/CnObjectSidebar.vue.js +1 -1
- package/dist/esm/components/CnObjectSidebar/CnObjectSidebar.vue2.js +14 -7
- package/dist/esm/components/CnObjectSidebar/CnObjectSidebar.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectSidebar/CnObjectSidebar.vue3.js.map +1 -1
- package/dist/esm/components/CnObjectTranslationsWidget/CnObjectTranslationsWidget.vue.js +9 -0
- package/dist/esm/components/CnObjectTranslationsWidget/CnObjectTranslationsWidget.vue.js.map +1 -0
- package/dist/esm/components/CnObjectTranslationsWidget/CnObjectTranslationsWidget.vue2.js +278 -0
- package/dist/esm/components/CnObjectTranslationsWidget/CnObjectTranslationsWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnObjectTranslationsWidget/CnObjectTranslationsWidget.vue3.js +128 -0
- package/dist/esm/components/CnObjectTranslationsWidget/CnObjectTranslationsWidget.vue3.js.map +1 -0
- package/dist/esm/components/CnReadinessChecklist/CnReadinessChecklist.vue.js +9 -0
- package/dist/esm/components/CnReadinessChecklist/CnReadinessChecklist.vue.js.map +1 -0
- package/dist/esm/components/CnReadinessChecklist/CnReadinessChecklist.vue2.js +214 -0
- package/dist/esm/components/CnReadinessChecklist/CnReadinessChecklist.vue2.js.map +1 -0
- package/dist/esm/components/CnReadinessChecklist/CnReadinessChecklist.vue3.js +125 -0
- package/dist/esm/components/CnReadinessChecklist/CnReadinessChecklist.vue3.js.map +1 -0
- package/dist/esm/components/CnSchemaRulesWidget/CnSchemaRulesWidget.vue.js +9 -0
- package/dist/esm/components/CnSchemaRulesWidget/CnSchemaRulesWidget.vue.js.map +1 -0
- package/dist/esm/components/CnSchemaRulesWidget/CnSchemaRulesWidget.vue2.js +163 -0
- package/dist/esm/components/CnSchemaRulesWidget/CnSchemaRulesWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnSchemaRulesWidget/CnSchemaRulesWidget.vue3.js +131 -0
- package/dist/esm/components/CnSchemaRulesWidget/CnSchemaRulesWidget.vue3.js.map +1 -0
- package/dist/esm/components/CnSchemaRulesWidget/schemaRules.js +127 -0
- package/dist/esm/components/CnSchemaRulesWidget/schemaRules.js.map +1 -0
- package/dist/esm/components/CnSearchIndexStatus/CnSearchIndexStatus.vue.js +9 -0
- package/dist/esm/components/CnSearchIndexStatus/CnSearchIndexStatus.vue.js.map +1 -0
- package/dist/esm/components/CnSearchIndexStatus/CnSearchIndexStatus.vue2.js +82 -0
- package/dist/esm/components/CnSearchIndexStatus/CnSearchIndexStatus.vue2.js.map +1 -0
- package/dist/esm/components/CnSearchIndexStatus/CnSearchIndexStatus.vue3.js +61 -0
- package/dist/esm/components/CnSearchIndexStatus/CnSearchIndexStatus.vue3.js.map +1 -0
- package/dist/esm/components/CnSearchIndexStatus/searchIndexStatus.js +60 -0
- package/dist/esm/components/CnSearchIndexStatus/searchIndexStatus.js.map +1 -0
- package/dist/esm/components/CnShippedConfigurationSection/CnShippedConfigurationSection.vue.js +10 -0
- package/dist/esm/components/CnShippedConfigurationSection/CnShippedConfigurationSection.vue.js.map +1 -0
- package/dist/esm/components/CnShippedConfigurationSection/CnShippedConfigurationSection.vue2.js +226 -0
- package/dist/esm/components/CnShippedConfigurationSection/CnShippedConfigurationSection.vue2.js.map +1 -0
- package/dist/esm/components/CnShippedConfigurationSection/CnShippedConfigurationSection.vue3.js +126 -0
- package/dist/esm/components/CnShippedConfigurationSection/CnShippedConfigurationSection.vue3.js.map +1 -0
- package/dist/esm/components/CnStateMachineEditor/CnStateMachineEditor.vue.js +10 -0
- package/dist/esm/components/CnStateMachineEditor/CnStateMachineEditor.vue.js.map +1 -0
- package/dist/esm/components/CnStateMachineEditor/CnStateMachineEditor.vue2.js +944 -0
- package/dist/esm/components/CnStateMachineEditor/CnStateMachineEditor.vue2.js.map +1 -0
- package/dist/esm/components/CnStateMachineEditor/CnStateMachineEditor.vue3.js +276 -0
- package/dist/esm/components/CnStateMachineEditor/CnStateMachineEditor.vue3.js.map +1 -0
- package/dist/esm/components/CnStateMachineEditor/CnStateMachineFields.vue.js +9 -0
- package/dist/esm/components/CnStateMachineEditor/CnStateMachineFields.vue.js.map +1 -0
- package/dist/esm/components/CnStateMachineEditor/CnStateMachineFields.vue2.js +354 -0
- package/dist/esm/components/CnStateMachineEditor/CnStateMachineFields.vue2.js.map +1 -0
- package/dist/esm/components/CnStateMachineEditor/CnStateMachineFields.vue3.js +392 -0
- package/dist/esm/components/CnStateMachineEditor/CnStateMachineFields.vue3.js.map +1 -0
- package/dist/esm/components/CnStateMachineEditor/CnStateMachineNode.vue.js +9 -0
- package/dist/esm/components/CnStateMachineEditor/CnStateMachineNode.vue.js.map +1 -0
- package/dist/esm/components/CnStateMachineEditor/CnStateMachineNode.vue2.js +180 -0
- package/dist/esm/components/CnStateMachineEditor/CnStateMachineNode.vue2.js.map +1 -0
- package/dist/esm/components/CnStateMachineEditor/CnStateMachineNode.vue3.js +208 -0
- package/dist/esm/components/CnStateMachineEditor/CnStateMachineNode.vue3.js.map +1 -0
- package/dist/esm/components/CnStateMachineEditor/CnStateMachinePanel.vue.js +9 -0
- package/dist/esm/components/CnStateMachineEditor/CnStateMachinePanel.vue.js.map +1 -0
- package/dist/esm/components/CnStateMachineEditor/CnStateMachinePanel.vue2.js +244 -0
- package/dist/esm/components/CnStateMachineEditor/CnStateMachinePanel.vue2.js.map +1 -0
- package/dist/esm/components/CnStateMachineEditor/CnStateMachinePanel.vue3.js +76 -0
- package/dist/esm/components/CnStateMachineEditor/CnStateMachinePanel.vue3.js.map +1 -0
- package/dist/esm/components/CnStateMachineEditor/stateMachineFields.js +290 -0
- package/dist/esm/components/CnStateMachineEditor/stateMachineFields.js.map +1 -0
- package/dist/esm/components/CnTimelineWidget/CnTimelineManage.vue.js +9 -0
- package/dist/esm/components/CnTimelineWidget/CnTimelineManage.vue.js.map +1 -0
- package/dist/esm/components/CnTimelineWidget/CnTimelineManage.vue2.js +448 -0
- package/dist/esm/components/CnTimelineWidget/CnTimelineManage.vue2.js.map +1 -0
- package/dist/esm/components/CnTimelineWidget/CnTimelineManage.vue3.js +303 -0
- package/dist/esm/components/CnTimelineWidget/CnTimelineManage.vue3.js.map +1 -0
- package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue.js +1 -1
- package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue2.js +19 -2
- package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue3.js +73 -62
- package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnWidgetGrid/builtInWidgets.js +6 -0
- package/dist/esm/components/CnWidgetGrid/builtInWidgets.js.map +1 -1
- package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js +42 -32
- package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js.map +1 -1
- package/dist/esm/composables/indexSources.js +116 -16
- package/dist/esm/composables/indexSources.js.map +1 -1
- package/dist/esm/index.js +9 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/l10n/en.json.js +207 -1
- package/dist/esm/l10n/en.json.js.map +1 -1
- package/dist/esm/l10n/nl.json.js +207 -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 +951 -16
- package/dist/esm/utils/aiFeatures.js +245 -0
- package/dist/esm/utils/aiFeatures.js.map +1 -0
- package/dist/esm/utils/aiSuggestionTracker.js +182 -0
- package/dist/esm/utils/aiSuggestionTracker.js.map +1 -0
- package/dist/esm/utils/libraryWidgetKeys.js +2 -0
- package/dist/esm/utils/libraryWidgetKeys.js.map +1 -1
- package/dist/esm/utils/objectPermissions.js +552 -0
- package/dist/esm/utils/objectPermissions.js.map +1 -0
- package/dist/esm/utils/objectTranslations.js +180 -0
- package/dist/esm/utils/objectTranslations.js.map +1 -0
- package/dist/esm/utils/stateMachineValidation.js +254 -0
- package/dist/esm/utils/stateMachineValidation.js.map +1 -0
- package/dist/esm/utils/widgetDispatch.js +3 -1
- package/dist/esm/utils/widgetDispatch.js.map +1 -1
- package/dist/nextcloud-vue.cjs.js +23038 -14567
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +951 -16
- package/l10n/en.json +207 -1
- package/l10n/nl.json +207 -1
- package/package.json +1 -1
- package/src/components/CnAiFeaturesWidget/CnAiFeaturesWidget.vue +416 -0
- package/src/components/CnAiFeaturesWidget/CnAiSuggestionDecision.vue +136 -0
- package/src/components/CnAiFeaturesWidget/__tests__/CnAiFeaturesWidget.spec.js +213 -0
- package/src/components/CnAiFeaturesWidget/index.js +14 -0
- package/src/components/CnIndexPage/CnIndexPage.vue +74 -3
- package/src/components/CnIndexPage/useNamedSource.js +9 -0
- package/src/components/CnObjectPermissionsTab/CnObjectPermissionsTab.vue +499 -0
- package/src/components/CnObjectPermissionsTab/__tests__/CnObjectPermissionsTab.spec.js +186 -0
- package/src/components/CnObjectPermissionsTab/index.js +13 -0
- package/src/components/CnObjectSidebar/CnObjectSidebar.vue +8 -1
- package/src/components/CnObjectTranslationsWidget/CnObjectTranslationsWidget.vue +424 -0
- package/src/components/CnObjectTranslationsWidget/__tests__/CnObjectTranslationsWidget.spec.js +189 -0
- package/src/components/CnObjectTranslationsWidget/index.js +13 -0
- package/src/components/CnReadinessChecklist/CnReadinessChecklist.vue +335 -0
- package/src/components/CnReadinessChecklist/index.js +9 -0
- package/src/components/CnSchemaRulesWidget/CnSchemaRulesWidget.vue +300 -0
- package/src/components/CnSchemaRulesWidget/index.js +10 -0
- package/src/components/CnSchemaRulesWidget/schemaRules.js +123 -0
- package/src/components/CnSearchIndexStatus/CnSearchIndexStatus.vue +160 -0
- package/src/components/CnSearchIndexStatus/index.js +10 -0
- package/src/components/CnSearchIndexStatus/searchIndexStatus.js +56 -0
- package/src/components/CnShippedConfigurationSection/CnShippedConfigurationSection.vue +328 -0
- package/src/components/CnShippedConfigurationSection/index.js +9 -0
- package/src/components/CnStateMachineEditor/CnStateMachineEditor.vue +1332 -0
- package/src/components/CnStateMachineEditor/CnStateMachineFields.vue +791 -0
- package/src/components/CnStateMachineEditor/CnStateMachineNode.vue +442 -0
- package/src/components/CnStateMachineEditor/CnStateMachinePanel.vue +326 -0
- package/src/components/CnStateMachineEditor/index.js +8 -0
- package/src/components/CnStateMachineEditor/stateMachineFields.js +287 -0
- package/src/components/CnTimelineWidget/CnTimelineManage.vue +827 -0
- package/src/components/CnTimelineWidget/CnTimelineWidget.vue +29 -3
- package/src/components/CnWidgetGrid/builtInWidgets.js +6 -0
- package/src/components/CnWidgetGrid/registerDashboardWidgets.js +10 -0
- package/src/components/index.js +8 -0
- package/src/composables/indexSources.js +116 -16
- package/src/css/index-page.css +7 -0
- package/src/index.js +9 -0
- package/src/utils/aiFeatures.js +241 -0
- package/src/utils/aiSuggestionTracker.js +178 -0
- package/src/utils/libraryWidgetKeys.js +2 -0
- package/src/utils/objectPermissions.js +548 -0
- package/src/utils/objectTranslations.js +176 -0
- package/src/utils/stateMachineValidation.js +250 -0
- package/src/utils/widgetDispatch.js +3 -1
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
import { resolveComponent, openBlock, createElementBlock, createElementVNode, toDisplayString, createBlock, withCtx, createVNode, createTextVNode, createCommentVNode, Fragment, renderList, normalizeClass, withModifiers, withDirectives, vModelText, resolveDynamicComponent, mergeProps, toHandlers } from 'vue';
|
|
2
|
+
|
|
3
|
+
const _hoisted_1 = {
|
|
4
|
+
class: "cn-timeline-manage",
|
|
5
|
+
"data-testid": "cn-timeline-manage"
|
|
6
|
+
};
|
|
7
|
+
const _hoisted_2 = { class: "cn-timeline-manage__header" };
|
|
8
|
+
const _hoisted_3 = { class: "cn-timeline-manage__heading" };
|
|
9
|
+
const _hoisted_4 = { class: "cn-timeline-manage__title" };
|
|
10
|
+
const _hoisted_5 = { class: "cn-timeline-manage__subtitle" };
|
|
11
|
+
const _hoisted_6 = { class: "cn-timeline-manage__header-actions" };
|
|
12
|
+
const _hoisted_7 = ["aria-label"];
|
|
13
|
+
const _hoisted_8 = ["aria-pressed", "data-testid", "onClick"];
|
|
14
|
+
const _hoisted_9 = { class: "cn-timeline-manage__chip-count" };
|
|
15
|
+
const _hoisted_10 = { class: "cn-timeline-manage__controls" };
|
|
16
|
+
const _hoisted_11 = {
|
|
17
|
+
key: 3,
|
|
18
|
+
class: "cn-timeline-manage__list",
|
|
19
|
+
"data-testid": "cn-timeline-list"
|
|
20
|
+
};
|
|
21
|
+
const _hoisted_12 = ["data-kind"];
|
|
22
|
+
const _hoisted_13 = { class: "cn-timeline-manage__head" };
|
|
23
|
+
const _hoisted_14 = { class: "cn-timeline-manage__kind" };
|
|
24
|
+
const _hoisted_15 = { class: "cn-timeline-manage__author" };
|
|
25
|
+
const _hoisted_16 = { class: "cn-timeline-manage__moment" };
|
|
26
|
+
const _hoisted_17 = {
|
|
27
|
+
key: 0,
|
|
28
|
+
class: "cn-timeline-manage__badge",
|
|
29
|
+
"data-testid": "cn-timeline-public"
|
|
30
|
+
};
|
|
31
|
+
const _hoisted_18 = {
|
|
32
|
+
key: 1,
|
|
33
|
+
class: "cn-timeline-manage__badge cn-timeline-manage__badge--open",
|
|
34
|
+
"data-testid": "cn-timeline-followup-open"
|
|
35
|
+
};
|
|
36
|
+
const _hoisted_19 = { class: "cn-timeline-manage__message" };
|
|
37
|
+
const _hoisted_20 = {
|
|
38
|
+
key: 0,
|
|
39
|
+
class: "cn-timeline-manage__siblings",
|
|
40
|
+
"data-testid": "cn-timeline-siblings"
|
|
41
|
+
};
|
|
42
|
+
const _hoisted_21 = {
|
|
43
|
+
key: 1,
|
|
44
|
+
class: "cn-timeline-manage__actions"
|
|
45
|
+
};
|
|
46
|
+
const _hoisted_22 = {
|
|
47
|
+
key: 4,
|
|
48
|
+
class: "cn-timeline-manage__count",
|
|
49
|
+
"data-testid": "cn-timeline-count"
|
|
50
|
+
};
|
|
51
|
+
const _hoisted_23 = { class: "cn-timeline-manage__composer-title" };
|
|
52
|
+
const _hoisted_24 = { class: "cn-timeline-manage__composer-hint" };
|
|
53
|
+
const _hoisted_25 = ["for"];
|
|
54
|
+
const _hoisted_26 = ["id", "placeholder"];
|
|
55
|
+
|
|
56
|
+
function render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
57
|
+
const _component_Plus = resolveComponent("Plus");
|
|
58
|
+
const _component_NcButton = resolveComponent("NcButton");
|
|
59
|
+
const _component_Download = resolveComponent("Download");
|
|
60
|
+
const _component_NcSelect = resolveComponent("NcSelect");
|
|
61
|
+
const _component_NcLoadingIcon = resolveComponent("NcLoadingIcon");
|
|
62
|
+
const _component_NcNoteCard = resolveComponent("NcNoteCard");
|
|
63
|
+
const _component_NcEmptyContent = resolveComponent("NcEmptyContent");
|
|
64
|
+
const _component_NcCheckboxRadioSwitch = resolveComponent("NcCheckboxRadioSwitch");
|
|
65
|
+
|
|
66
|
+
return (openBlock(), createElementBlock("div", _hoisted_1, [
|
|
67
|
+
createElementVNode("div", _hoisted_2, [
|
|
68
|
+
createElementVNode("div", _hoisted_3, [
|
|
69
|
+
createElementVNode("h3", _hoisted_4, toDisplayString($options.titleText), 1 /* TEXT */),
|
|
70
|
+
createElementVNode("p", _hoisted_5, toDisplayString($options.subtitleText), 1 /* TEXT */)
|
|
71
|
+
]),
|
|
72
|
+
createElementVNode("div", _hoisted_6, [
|
|
73
|
+
($data.canManage && $options.composerEnabled)
|
|
74
|
+
? (openBlock(), createBlock(_component_NcButton, {
|
|
75
|
+
key: 0,
|
|
76
|
+
"data-testid": "cn-timeline-add-note",
|
|
77
|
+
onClick: $options.focusComposer
|
|
78
|
+
}, {
|
|
79
|
+
icon: withCtx(() => [
|
|
80
|
+
createVNode(_component_Plus, { size: 20 })
|
|
81
|
+
]),
|
|
82
|
+
default: withCtx(() => [
|
|
83
|
+
createTextVNode(" " + toDisplayString($options.t('nextcloud-vue', 'Add a note')), 1 /* TEXT */)
|
|
84
|
+
]),
|
|
85
|
+
_: 1 /* STABLE */
|
|
86
|
+
}, 8 /* PROPS */, ["onClick"]))
|
|
87
|
+
: createCommentVNode("v-if", true),
|
|
88
|
+
createVNode(_component_NcButton, {
|
|
89
|
+
"data-testid": "cn-timeline-export",
|
|
90
|
+
onClick: $options.exportEntries
|
|
91
|
+
}, {
|
|
92
|
+
icon: withCtx(() => [
|
|
93
|
+
createVNode(_component_Download, { size: 20 })
|
|
94
|
+
]),
|
|
95
|
+
default: withCtx(() => [
|
|
96
|
+
createTextVNode(" " + toDisplayString($options.t('nextcloud-vue', 'Export')), 1 /* TEXT */)
|
|
97
|
+
]),
|
|
98
|
+
_: 1 /* STABLE */
|
|
99
|
+
}, 8 /* PROPS */, ["onClick"])
|
|
100
|
+
])
|
|
101
|
+
]),
|
|
102
|
+
createElementVNode("div", {
|
|
103
|
+
class: "cn-timeline-manage__chips",
|
|
104
|
+
role: "group",
|
|
105
|
+
"aria-label": $options.t('nextcloud-vue', 'Kind'),
|
|
106
|
+
"data-testid": "cn-timeline-kind-filter"
|
|
107
|
+
}, [
|
|
108
|
+
(openBlock(true), createElementBlock(Fragment, null, renderList($options.kindChips, (chip) => {
|
|
109
|
+
return (openBlock(), createElementBlock("button", {
|
|
110
|
+
key: chip.key,
|
|
111
|
+
type: "button",
|
|
112
|
+
class: normalizeClass(["cn-timeline-manage__chip", { 'cn-timeline-manage__chip--active': chip.active }]),
|
|
113
|
+
"aria-pressed": chip.active ? 'true' : 'false',
|
|
114
|
+
"data-testid": 'cn-timeline-chip-' + chip.key,
|
|
115
|
+
onClick: $event => ($options.chooseKind(chip.id))
|
|
116
|
+
}, [
|
|
117
|
+
createTextVNode(toDisplayString(chip.label) + " ", 1 /* TEXT */),
|
|
118
|
+
createElementVNode("span", _hoisted_9, toDisplayString(chip.count), 1 /* TEXT */)
|
|
119
|
+
], 10 /* CLASS, PROPS */, _hoisted_8))
|
|
120
|
+
}), 128 /* KEYED_FRAGMENT */))
|
|
121
|
+
], 8 /* PROPS */, _hoisted_7),
|
|
122
|
+
createElementVNode("div", _hoisted_10, [
|
|
123
|
+
($data.canManage)
|
|
124
|
+
? (openBlock(), createBlock(_component_NcSelect, {
|
|
125
|
+
key: 0,
|
|
126
|
+
modelValue: $data.visibilityFilter,
|
|
127
|
+
"onUpdate:modelValue": [
|
|
128
|
+
_cache[0] || (_cache[0] = $event => (($data.visibilityFilter) = $event)),
|
|
129
|
+
$options.load
|
|
130
|
+
],
|
|
131
|
+
class: "cn-timeline-manage__filter",
|
|
132
|
+
options: $options.visibilityOptions,
|
|
133
|
+
clearable: true,
|
|
134
|
+
label: "label",
|
|
135
|
+
inputLabel: $options.t('nextcloud-vue', 'Visibility'),
|
|
136
|
+
placeholder: $options.t('nextcloud-vue', 'Internal and public'),
|
|
137
|
+
"data-testid": "cn-timeline-visibility-filter"
|
|
138
|
+
}, null, 8 /* PROPS */, ["modelValue", "options", "inputLabel", "placeholder", "onUpdate:modelValue"]))
|
|
139
|
+
: createCommentVNode("v-if", true)
|
|
140
|
+
]),
|
|
141
|
+
($data.loading)
|
|
142
|
+
? (openBlock(), createBlock(_component_NcLoadingIcon, {
|
|
143
|
+
key: 0,
|
|
144
|
+
size: 32
|
|
145
|
+
}))
|
|
146
|
+
: ($data.error)
|
|
147
|
+
? (openBlock(), createBlock(_component_NcNoteCard, {
|
|
148
|
+
key: 1,
|
|
149
|
+
type: "error",
|
|
150
|
+
"data-testid": "cn-timeline-error"
|
|
151
|
+
}, {
|
|
152
|
+
default: withCtx(() => [
|
|
153
|
+
createTextVNode(toDisplayString($data.error), 1 /* TEXT */)
|
|
154
|
+
]),
|
|
155
|
+
_: 1 /* STABLE */
|
|
156
|
+
}))
|
|
157
|
+
: ($data.entries.length === 0)
|
|
158
|
+
? (openBlock(), createBlock(_component_NcEmptyContent, {
|
|
159
|
+
key: 2,
|
|
160
|
+
name: $options.t('nextcloud-vue', 'Nothing recorded yet'),
|
|
161
|
+
description: $options.t('nextcloud-vue', 'Notes, calls and messages appear here in the order they happened.'),
|
|
162
|
+
"data-testid": "cn-timeline-empty"
|
|
163
|
+
}, null, 8 /* PROPS */, ["name", "description"]))
|
|
164
|
+
: (openBlock(), createElementBlock("ul", _hoisted_11, [
|
|
165
|
+
(openBlock(true), createElementBlock(Fragment, null, renderList($data.entries, (entry) => {
|
|
166
|
+
return (openBlock(), createElementBlock("li", {
|
|
167
|
+
key: entry.id,
|
|
168
|
+
class: normalizeClass(["cn-timeline-manage__entry", { 'cn-timeline-manage__entry--pinned': entry.pinned }]),
|
|
169
|
+
"data-kind": entry.kind || 'note',
|
|
170
|
+
"data-testid": "cn-timeline-entry"
|
|
171
|
+
}, [
|
|
172
|
+
createElementVNode("div", _hoisted_13, [
|
|
173
|
+
createElementVNode("span", _hoisted_14, toDisplayString($options.kindLabel(entry)), 1 /* TEXT */),
|
|
174
|
+
createElementVNode("span", _hoisted_15, toDisplayString(entry.author), 1 /* TEXT */),
|
|
175
|
+
createElementVNode("span", _hoisted_16, toDisplayString($options.moment(entry.created)), 1 /* TEXT */),
|
|
176
|
+
(entry.visibility === 'public')
|
|
177
|
+
? (openBlock(), createElementBlock("span", _hoisted_17, toDisplayString($options.publicLabel), 1 /* TEXT */))
|
|
178
|
+
: createCommentVNode("v-if", true),
|
|
179
|
+
(entry.followUp === 'open')
|
|
180
|
+
? (openBlock(), createElementBlock("span", _hoisted_18, toDisplayString($options.t('nextcloud-vue', 'Needs an answer')), 1 /* TEXT */))
|
|
181
|
+
: createCommentVNode("v-if", true)
|
|
182
|
+
]),
|
|
183
|
+
createElementVNode("p", _hoisted_19, toDisplayString(entry.message), 1 /* TEXT */),
|
|
184
|
+
(entry.siblings && entry.siblings.length)
|
|
185
|
+
? (openBlock(), createElementBlock("p", _hoisted_20, toDisplayString($options.n('nextcloud-vue', 'Also written on %n other record', 'Also written on %n other records', entry.siblings.length)), 1 /* TEXT */))
|
|
186
|
+
: createCommentVNode("v-if", true),
|
|
187
|
+
($data.canManage)
|
|
188
|
+
? (openBlock(), createElementBlock("div", _hoisted_21, [
|
|
189
|
+
createVNode(_component_NcButton, {
|
|
190
|
+
variant: "tertiary",
|
|
191
|
+
"data-testid": 'cn-timeline-pin-' + entry.id,
|
|
192
|
+
onClick: $event => ($options.togglePin(entry))
|
|
193
|
+
}, {
|
|
194
|
+
default: withCtx(() => [
|
|
195
|
+
createTextVNode(toDisplayString(entry.pinned ? $options.t('nextcloud-vue', 'Unpin') : $options.t('nextcloud-vue', 'Pin')), 1 /* TEXT */)
|
|
196
|
+
]),
|
|
197
|
+
_: 2 /* DYNAMIC */
|
|
198
|
+
}, 1032 /* PROPS, DYNAMIC_SLOTS */, ["data-testid", "onClick"]),
|
|
199
|
+
(openBlock(true), createElementBlock(Fragment, null, renderList($options.actionsFor(entry), (action) => {
|
|
200
|
+
return (openBlock(), createBlock(_component_NcButton, {
|
|
201
|
+
key: action.id,
|
|
202
|
+
variant: "tertiary",
|
|
203
|
+
"data-testid": 'cn-timeline-action-' + action.id + '-' + entry.id,
|
|
204
|
+
onClick: $event => ($options.openAction(action, entry))
|
|
205
|
+
}, {
|
|
206
|
+
default: withCtx(() => [
|
|
207
|
+
createTextVNode(toDisplayString($options.translate(action.label)), 1 /* TEXT */)
|
|
208
|
+
]),
|
|
209
|
+
_: 2 /* DYNAMIC */
|
|
210
|
+
}, 1032 /* PROPS, DYNAMIC_SLOTS */, ["data-testid", "onClick"]))
|
|
211
|
+
}), 128 /* KEYED_FRAGMENT */)),
|
|
212
|
+
(entry.followUp === 'open')
|
|
213
|
+
? (openBlock(), createBlock(_component_NcButton, {
|
|
214
|
+
key: 0,
|
|
215
|
+
variant: "tertiary",
|
|
216
|
+
"data-testid": 'cn-timeline-followup-' + entry.id,
|
|
217
|
+
onClick: $event => ($options.closeFollowUp(entry))
|
|
218
|
+
}, {
|
|
219
|
+
default: withCtx(() => [
|
|
220
|
+
createTextVNode(toDisplayString($options.t('nextcloud-vue', 'Mark as answered')), 1 /* TEXT */)
|
|
221
|
+
]),
|
|
222
|
+
_: 1 /* STABLE */
|
|
223
|
+
}, 8 /* PROPS */, ["data-testid", "onClick"]))
|
|
224
|
+
: createCommentVNode("v-if", true)
|
|
225
|
+
]))
|
|
226
|
+
: createCommentVNode("v-if", true)
|
|
227
|
+
], 10 /* CLASS, PROPS */, _hoisted_12))
|
|
228
|
+
}), 128 /* KEYED_FRAGMENT */))
|
|
229
|
+
])),
|
|
230
|
+
(!$data.loading && !$data.error && $data.allEntries.length > 0)
|
|
231
|
+
? (openBlock(), createElementBlock("p", _hoisted_22, toDisplayString($options.t('nextcloud-vue', '{shown} of {total} events', { shown: $data.entries.length, total: $data.allEntries.length })), 1 /* TEXT */))
|
|
232
|
+
: createCommentVNode("v-if", true),
|
|
233
|
+
($data.canManage && $options.composerEnabled)
|
|
234
|
+
? (openBlock(), createElementBlock("form", {
|
|
235
|
+
key: 5,
|
|
236
|
+
ref: "composer",
|
|
237
|
+
class: "cn-timeline-manage__composer",
|
|
238
|
+
"data-testid": "cn-timeline-composer",
|
|
239
|
+
onSubmit: _cache[4] || (_cache[4] = withModifiers((...args) => ($options.submit && $options.submit(...args)), ["prevent"]))
|
|
240
|
+
}, [
|
|
241
|
+
createElementVNode("h3", _hoisted_23, toDisplayString($options.t('nextcloud-vue', 'Add a note')), 1 /* TEXT */),
|
|
242
|
+
createElementVNode("p", _hoisted_24, toDisplayString($options.t('nextcloud-vue', 'Goes on the timeline above, internal unless you make it visible')), 1 /* TEXT */),
|
|
243
|
+
($data.textBlocks.length)
|
|
244
|
+
? (openBlock(), createBlock(_component_NcSelect, {
|
|
245
|
+
key: 0,
|
|
246
|
+
modelValue: $data.chosenBlock,
|
|
247
|
+
"onUpdate:modelValue": [
|
|
248
|
+
_cache[1] || (_cache[1] = $event => (($data.chosenBlock) = $event)),
|
|
249
|
+
$options.pickBlock
|
|
250
|
+
],
|
|
251
|
+
class: "cn-timeline-manage__filter",
|
|
252
|
+
options: $options.blockOptions,
|
|
253
|
+
clearable: true,
|
|
254
|
+
label: "label",
|
|
255
|
+
inputLabel: $options.t('nextcloud-vue', 'Standard note'),
|
|
256
|
+
placeholder: $options.t('nextcloud-vue', 'Write your own'),
|
|
257
|
+
"data-testid": "cn-timeline-block"
|
|
258
|
+
}, null, 8 /* PROPS */, ["modelValue", "options", "inputLabel", "placeholder", "onUpdate:modelValue"]))
|
|
259
|
+
: createCommentVNode("v-if", true),
|
|
260
|
+
createElementVNode("label", {
|
|
261
|
+
class: "cn-timeline-manage__draft-label",
|
|
262
|
+
for: $options.draftId
|
|
263
|
+
}, toDisplayString($options.t('nextcloud-vue', 'Write a note on this record')), 9 /* TEXT, PROPS */, _hoisted_25),
|
|
264
|
+
withDirectives(createElementVNode("textarea", {
|
|
265
|
+
id: $options.draftId,
|
|
266
|
+
"onUpdate:modelValue": _cache[2] || (_cache[2] = $event => (($data.draft) = $event)),
|
|
267
|
+
class: "cn-timeline-manage__draft",
|
|
268
|
+
placeholder: $options.t('nextcloud-vue', 'Write a note on this record'),
|
|
269
|
+
"data-testid": "cn-timeline-draft"
|
|
270
|
+
}, null, 8 /* PROPS */, _hoisted_26), [
|
|
271
|
+
[vModelText, $data.draft]
|
|
272
|
+
]),
|
|
273
|
+
createVNode(_component_NcCheckboxRadioSwitch, {
|
|
274
|
+
modelValue: $data.draftIsPublic,
|
|
275
|
+
"onUpdate:modelValue": _cache[3] || (_cache[3] = $event => (($data.draftIsPublic) = $event)),
|
|
276
|
+
"data-testid": "cn-timeline-draft-public"
|
|
277
|
+
}, {
|
|
278
|
+
default: withCtx(() => [
|
|
279
|
+
createTextVNode(toDisplayString($options.publicLabel), 1 /* TEXT */)
|
|
280
|
+
]),
|
|
281
|
+
_: 1 /* STABLE */
|
|
282
|
+
}, 8 /* PROPS */, ["modelValue"]),
|
|
283
|
+
createVNode(_component_NcButton, {
|
|
284
|
+
variant: "primary",
|
|
285
|
+
type: "submit",
|
|
286
|
+
disabled: $data.saving || !$data.draft.trim(),
|
|
287
|
+
"data-testid": "cn-timeline-save"
|
|
288
|
+
}, {
|
|
289
|
+
default: withCtx(() => [
|
|
290
|
+
createTextVNode(toDisplayString($options.t('nextcloud-vue', 'Add to the timeline')), 1 /* TEXT */)
|
|
291
|
+
]),
|
|
292
|
+
_: 1 /* STABLE */
|
|
293
|
+
}, 8 /* PROPS */, ["disabled"])
|
|
294
|
+
], 544 /* NEED_HYDRATION, NEED_PATCH */))
|
|
295
|
+
: createCommentVNode("v-if", true),
|
|
296
|
+
($data.activeModal)
|
|
297
|
+
? (openBlock(), createBlock(resolveDynamicComponent($data.activeModal.component), mergeProps({ key: 6 }, $data.activeModal.props, toHandlers($data.activeModal.listeners)), null, 16 /* FULL_PROPS */))
|
|
298
|
+
: createCommentVNode("v-if", true)
|
|
299
|
+
]))
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
export { render };
|
|
303
|
+
//# sourceMappingURL=CnTimelineManage.vue3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CnTimelineManage.vue3.js","sources":["../../../../src/components/CnTimelineWidget/CnTimelineManage.vue?vue&type=template&id=397b3dd4&lang.js"],"sourcesContent":["<!--\n SPDX-FileCopyrightText: 2026 Conduction B.V.\n SPDX-License-Identifier: EUPL-1.2\n\n CnTimelineManage — the `manage` mode of CnTimelineWidget: one chronological\n read of OpenRegister's timeline on an object (notes, calls, messages), newest\n first with pinned entries on top, plus what a reader who may manage it can do\n there: filter by kind and visibility, pin, close a follow-up, write a note\n (optionally from a standard text block, optionally visible outside), export\n the shown entries as CSV, and run configured entry actions such as a reply\n dialog.\n\n The list read is filtered by OpenRegister whether or not a filter is asked\n for; the response says whether the reader may manage (`canManage`), and the\n controls are drawn from that rather than guessed. A failed read is not an\n empty history.\n-->\n<template>\n\t<div class=\"cn-timeline-manage\" data-testid=\"cn-timeline-manage\">\n\t\t<div class=\"cn-timeline-manage__header\">\n\t\t\t<div class=\"cn-timeline-manage__heading\">\n\t\t\t\t<h3 class=\"cn-timeline-manage__title\">\n\t\t\t\t\t{{ titleText }}\n\t\t\t\t</h3>\n\t\t\t\t<p class=\"cn-timeline-manage__subtitle\">\n\t\t\t\t\t{{ subtitleText }}\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t\t<div class=\"cn-timeline-manage__header-actions\">\n\t\t\t\t<NcButton v-if=\"canManage && composerEnabled\"\n\t\t\t\t\tdata-testid=\"cn-timeline-add-note\"\n\t\t\t\t\t@click=\"focusComposer\">\n\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t<Plus :size=\"20\" />\n\t\t\t\t\t</template>\n\t\t\t\t\t{{ t('nextcloud-vue', 'Add a note') }}\n\t\t\t\t</NcButton>\n\t\t\t\t<NcButton data-testid=\"cn-timeline-export\" @click=\"exportEntries\">\n\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t<Download :size=\"20\" />\n\t\t\t\t\t</template>\n\t\t\t\t\t{{ t('nextcloud-vue', 'Export') }}\n\t\t\t\t</NcButton>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<div class=\"cn-timeline-manage__chips\"\n\t\t\trole=\"group\"\n\t\t\t:aria-label=\"t('nextcloud-vue', 'Kind')\"\n\t\t\tdata-testid=\"cn-timeline-kind-filter\">\n\t\t\t<button v-for=\"chip in kindChips\"\n\t\t\t\t:key=\"chip.key\"\n\t\t\t\ttype=\"button\"\n\t\t\t\tclass=\"cn-timeline-manage__chip\"\n\t\t\t\t:class=\"{ 'cn-timeline-manage__chip--active': chip.active }\"\n\t\t\t\t:aria-pressed=\"chip.active ? 'true' : 'false'\"\n\t\t\t\t:data-testid=\"'cn-timeline-chip-' + chip.key\"\n\t\t\t\t@click=\"chooseKind(chip.id)\">\n\t\t\t\t{{ chip.label }}\n\t\t\t\t<span class=\"cn-timeline-manage__chip-count\">{{ chip.count }}</span>\n\t\t\t</button>\n\t\t</div>\n\n\t\t<div class=\"cn-timeline-manage__controls\">\n\t\t\t<NcSelect v-if=\"canManage\"\n\t\t\t\tv-model=\"visibilityFilter\"\n\t\t\t\tclass=\"cn-timeline-manage__filter\"\n\t\t\t\t:options=\"visibilityOptions\"\n\t\t\t\t:clearable=\"true\"\n\t\t\t\tlabel=\"label\"\n\t\t\t\t:inputLabel=\"t('nextcloud-vue', 'Visibility')\"\n\t\t\t\t:placeholder=\"t('nextcloud-vue', 'Internal and public')\"\n\t\t\t\tdata-testid=\"cn-timeline-visibility-filter\"\n\t\t\t\t@update:modelValue=\"load\" />\n\t\t</div>\n\n\t\t<NcLoadingIcon v-if=\"loading\" :size=\"32\" />\n\n\t\t<NcNoteCard v-else-if=\"error\" type=\"error\" data-testid=\"cn-timeline-error\">\n\t\t\t{{ error }}\n\t\t</NcNoteCard>\n\n\t\t<NcEmptyContent v-else-if=\"entries.length === 0\"\n\t\t\t:name=\"t('nextcloud-vue', 'Nothing recorded yet')\"\n\t\t\t:description=\"t('nextcloud-vue', 'Notes, calls and messages appear here in the order they happened.')\"\n\t\t\tdata-testid=\"cn-timeline-empty\" />\n\n\t\t<ul v-else class=\"cn-timeline-manage__list\" data-testid=\"cn-timeline-list\">\n\t\t\t<li v-for=\"entry in entries\"\n\t\t\t\t:key=\"entry.id\"\n\t\t\t\tclass=\"cn-timeline-manage__entry\"\n\t\t\t\t:class=\"{ 'cn-timeline-manage__entry--pinned': entry.pinned }\"\n\t\t\t\t:data-kind=\"entry.kind || 'note'\"\n\t\t\t\tdata-testid=\"cn-timeline-entry\">\n\t\t\t\t<div class=\"cn-timeline-manage__head\">\n\t\t\t\t\t<span class=\"cn-timeline-manage__kind\">{{ kindLabel(entry) }}</span>\n\t\t\t\t\t<span class=\"cn-timeline-manage__author\">{{ entry.author }}</span>\n\t\t\t\t\t<span class=\"cn-timeline-manage__moment\">{{ moment(entry.created) }}</span>\n\t\t\t\t\t<span v-if=\"entry.visibility === 'public'\"\n\t\t\t\t\t\tclass=\"cn-timeline-manage__badge\"\n\t\t\t\t\t\tdata-testid=\"cn-timeline-public\">\n\t\t\t\t\t\t{{ publicLabel }}\n\t\t\t\t\t</span>\n\t\t\t\t\t<span v-if=\"entry.followUp === 'open'\"\n\t\t\t\t\t\tclass=\"cn-timeline-manage__badge cn-timeline-manage__badge--open\"\n\t\t\t\t\t\tdata-testid=\"cn-timeline-followup-open\">\n\t\t\t\t\t\t{{ t('nextcloud-vue', 'Needs an answer') }}\n\t\t\t\t\t</span>\n\t\t\t\t</div>\n\n\t\t\t\t<p class=\"cn-timeline-manage__message\">\n\t\t\t\t\t{{ entry.message }}\n\t\t\t\t</p>\n\n\t\t\t\t<p v-if=\"entry.siblings && entry.siblings.length\"\n\t\t\t\t\tclass=\"cn-timeline-manage__siblings\"\n\t\t\t\t\tdata-testid=\"cn-timeline-siblings\">\n\t\t\t\t\t{{ n('nextcloud-vue', 'Also written on %n other record', 'Also written on %n other records', entry.siblings.length) }}\n\t\t\t\t</p>\n\n\t\t\t\t<div v-if=\"canManage\" class=\"cn-timeline-manage__actions\">\n\t\t\t\t\t<NcButton variant=\"tertiary\"\n\t\t\t\t\t\t:data-testid=\"'cn-timeline-pin-' + entry.id\"\n\t\t\t\t\t\t@click=\"togglePin(entry)\">\n\t\t\t\t\t\t{{ entry.pinned ? t('nextcloud-vue', 'Unpin') : t('nextcloud-vue', 'Pin') }}\n\t\t\t\t\t</NcButton>\n\t\t\t\t\t<NcButton v-for=\"action in actionsFor(entry)\"\n\t\t\t\t\t\t:key=\"action.id\"\n\t\t\t\t\t\tvariant=\"tertiary\"\n\t\t\t\t\t\t:data-testid=\"'cn-timeline-action-' + action.id + '-' + entry.id\"\n\t\t\t\t\t\t@click=\"openAction(action, entry)\">\n\t\t\t\t\t\t{{ translate(action.label) }}\n\t\t\t\t\t</NcButton>\n\t\t\t\t\t<NcButton v-if=\"entry.followUp === 'open'\"\n\t\t\t\t\t\tvariant=\"tertiary\"\n\t\t\t\t\t\t:data-testid=\"'cn-timeline-followup-' + entry.id\"\n\t\t\t\t\t\t@click=\"closeFollowUp(entry)\">\n\t\t\t\t\t\t{{ t('nextcloud-vue', 'Mark as answered') }}\n\t\t\t\t\t</NcButton>\n\t\t\t\t</div>\n\t\t\t</li>\n\t\t</ul>\n\n\t\t<p v-if=\"!loading && !error && allEntries.length > 0\"\n\t\t\tclass=\"cn-timeline-manage__count\"\n\t\t\tdata-testid=\"cn-timeline-count\">\n\t\t\t{{ t('nextcloud-vue', '{shown} of {total} events', { shown: entries.length, total: allEntries.length }) }}\n\t\t</p>\n\n\t\t<form v-if=\"canManage && composerEnabled\"\n\t\t\tref=\"composer\"\n\t\t\tclass=\"cn-timeline-manage__composer\"\n\t\t\tdata-testid=\"cn-timeline-composer\"\n\t\t\t@submit.prevent=\"submit\">\n\t\t\t<h3 class=\"cn-timeline-manage__composer-title\">\n\t\t\t\t{{ t('nextcloud-vue', 'Add a note') }}\n\t\t\t</h3>\n\t\t\t<p class=\"cn-timeline-manage__composer-hint\">\n\t\t\t\t{{ t('nextcloud-vue', 'Goes on the timeline above, internal unless you make it visible') }}\n\t\t\t</p>\n\t\t\t<NcSelect v-if=\"textBlocks.length\"\n\t\t\t\tv-model=\"chosenBlock\"\n\t\t\t\tclass=\"cn-timeline-manage__filter\"\n\t\t\t\t:options=\"blockOptions\"\n\t\t\t\t:clearable=\"true\"\n\t\t\t\tlabel=\"label\"\n\t\t\t\t:inputLabel=\"t('nextcloud-vue', 'Standard note')\"\n\t\t\t\t:placeholder=\"t('nextcloud-vue', 'Write your own')\"\n\t\t\t\tdata-testid=\"cn-timeline-block\"\n\t\t\t\t@update:modelValue=\"pickBlock\" />\n\n\t\t\t<label class=\"cn-timeline-manage__draft-label\" :for=\"draftId\">\n\t\t\t\t{{ t('nextcloud-vue', 'Write a note on this record') }}\n\t\t\t</label>\n\t\t\t<textarea :id=\"draftId\"\n\t\t\t\tv-model=\"draft\"\n\t\t\t\tclass=\"cn-timeline-manage__draft\"\n\t\t\t\t:placeholder=\"t('nextcloud-vue', 'Write a note on this record')\"\n\t\t\t\tdata-testid=\"cn-timeline-draft\" />\n\n\t\t\t<NcCheckboxRadioSwitch v-model=\"draftIsPublic\" data-testid=\"cn-timeline-draft-public\">\n\t\t\t\t{{ publicLabel }}\n\t\t\t</NcCheckboxRadioSwitch>\n\n\t\t\t<NcButton variant=\"primary\"\n\t\t\t\ttype=\"submit\"\n\t\t\t\t:disabled=\"saving || !draft.trim()\"\n\t\t\t\tdata-testid=\"cn-timeline-save\">\n\t\t\t\t{{ t('nextcloud-vue', 'Add to the timeline') }}\n\t\t\t</NcButton>\n\t\t</form>\n\n\t\t<component :is=\"activeModal.component\"\n\t\t\tv-if=\"activeModal\"\n\t\t\tv-bind=\"activeModal.props\"\n\t\t\tv-on=\"activeModal.listeners\" />\n\t</div>\n</template>\n\n<script>\nimport axios from '@nextcloud/axios'\nimport { translatePlural as n, translate as t } from '@nextcloud/l10n'\nimport { NcButton, NcCheckboxRadioSwitch, NcEmptyContent, NcLoadingIcon, NcNoteCard, NcSelect } from '@nextcloud/vue'\nimport Download from 'vue-material-design-icons/Download.vue'\nimport Plus from 'vue-material-design-icons/Plus.vue'\nimport { prefixUrl } from '../../utils/headers.js'\n\nlet instanceCount = 0\n\n/**\n * Read a dotted path off a value.\n *\n * @param {object} value The value.\n * @param {string} path The path.\n * @return {unknown} What is there, or undefined.\n */\nfunction readPath(value, path) {\n\treturn String(path).split('.').reduce((at, key) => (at === null || at === undefined ? undefined : at[key]), value)\n}\n\nexport default {\n\tname: 'CnTimelineManage',\n\n\tcomponents: { Download, NcButton, NcCheckboxRadioSwitch, NcEmptyContent, NcLoadingIcon, NcNoteCard, NcSelect, Plus },\n\n\tinject: {\n\t\t/** The app's component registry; entry actions resolve their modal here. */\n\t\tcnRegistry: { default: () => ({}) },\n\t\t/** Consumer translation function; manifest labels are authored in English. */\n\t\tcnTranslate: { default: () => (key) => key },\n\t},\n\n\tprops: {\n\t\t/** Register slug. */\n\t\tregister: { type: String, default: '' },\n\t\t/** Schema slug. */\n\t\tschema: { type: String, default: '' },\n\t\t/** The object's id. */\n\t\tobjectId: { type: String, default: '' },\n\t\t/** OpenRegister API base. */\n\t\tapiBase: { type: String, default: '/apps/openregister/api' },\n\t\t/**\n\t\t * The widget content: `{ title?, subtitle?, publicLabel?, exportName?,\n\t\t * composer?, textBlocks?, entryActions? }`.\n\t\t */\n\t\tcontent: { type: Object, default: () => ({}) },\n\t},\n\n\tdata() {\n\t\tinstanceCount += 1\n\t\treturn {\n\t\t\tuid: instanceCount,\n\t\t\tallEntries: [],\n\t\t\tentries: [],\n\t\t\tkinds: [],\n\t\t\tloading: false,\n\t\t\terror: '',\n\t\t\tcanManage: false,\n\t\t\tkindFilter: null,\n\t\t\tvisibilityFilter: null,\n\t\t\ttextBlocks: [],\n\t\t\tchosenBlock: null,\n\t\t\tdraft: '',\n\t\t\tdraftIsPublic: false,\n\t\t\tsaving: false,\n\t\t\tactiveModal: null,\n\t\t}\n\t},\n\n\tcomputed: {\n\t\ttitleText() {\n\t\t\treturn this.content.title ? this.translate(this.content.title) : t('nextcloud-vue', 'History')\n\t\t},\n\n\t\tsubtitleText() {\n\t\t\treturn this.content.subtitle ? this.translate(this.content.subtitle) : t('nextcloud-vue', 'What happened, who did it and when, newest first')\n\t\t},\n\n\t\tpublicLabel() {\n\t\t\treturn this.content.publicLabel ? this.translate(this.content.publicLabel) : t('nextcloud-vue', 'Visible to the applicant')\n\t\t},\n\n\t\tcomposerEnabled() {\n\t\t\treturn this.content.composer !== false\n\t\t},\n\n\t\tdraftId() {\n\t\t\treturn `cn-timeline-draft-${this.uid}`\n\t\t},\n\n\t\t/**\n\t\t * The kind options, the plain note first. A note is an entry with NO\n\t\t * kind, so \"Note\" filters on its absence.\n\t\t *\n\t\t * @return {Array<object>} The options.\n\t\t */\n\t\tkindOptions() {\n\t\t\treturn [{ id: '', label: t('nextcloud-vue', 'Note') }].concat(this.kinds.map((kind) => ({ id: kind.slug, label: kind.title || kind.slug })))\n\t\t},\n\n\t\t/**\n\t\t * All, then every kind the object has entries of, each with its count.\n\t\t *\n\t\t * @return {Array<object>} The chips.\n\t\t */\n\t\tkindChips() {\n\t\t\tconst chosen = this.kindFilter ? (this.kindFilter.id || '') : null\n\t\t\tconst counts = new Map()\n\t\t\tfor (const entry of this.allEntries) {\n\t\t\t\tconst kind = entry.kind || ''\n\t\t\t\tcounts.set(kind, (counts.get(kind) || 0) + 1)\n\t\t\t}\n\t\t\tconst chips = [{ key: 'all', id: null, label: t('nextcloud-vue', 'All'), count: this.allEntries.length, active: chosen === null }]\n\t\t\tfor (const option of this.kindOptions) {\n\t\t\t\tconst count = counts.get(option.id) || 0\n\t\t\t\tif (count > 0) {\n\t\t\t\t\tchips.push({ key: option.id || 'note', id: option.id, label: option.label, count, active: chosen === option.id })\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn chips\n\t\t},\n\n\t\tblockOptions() {\n\t\t\treturn this.textBlocks.map((block) => ({ id: block.slug, label: block.title || block.slug }))\n\t\t},\n\n\t\tvisibilityOptions() {\n\t\t\treturn [\n\t\t\t\t{ id: 'internal', label: t('nextcloud-vue', 'Internal only') },\n\t\t\t\t{ id: 'public', label: this.publicLabel },\n\t\t\t]\n\t\t},\n\n\t\tbase() {\n\t\t\treturn this.apiBase.replace(/\\/$/, '')\n\t\t},\n\n\t\ttimelineUrl() {\n\t\t\tif (!this.objectId || !this.register || !this.schema) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\treturn prefixUrl(`${this.base}/objects/${this.register}/${this.schema}/${this.objectId}/timeline`)\n\t\t},\n\n\t\tentryActions() {\n\t\t\treturn Array.isArray(this.content.entryActions) ? this.content.entryActions.filter((action) => action && action.id) : []\n\t\t},\n\t},\n\n\twatch: {\n\t\tobjectId: 'load',\n\t},\n\n\tmounted() {\n\t\tthis.loadKinds()\n\t\tif (this.content.textBlocks !== false) {\n\t\t\tthis.loadTextBlocks()\n\t\t}\n\t\tthis.load()\n\t},\n\n\tmethods: {\n\t\tt,\n\t\tn,\n\n\t\ttranslate(text) {\n\t\t\treturn text ? this.cnTranslate(text) : ''\n\t\t},\n\n\t\t/** Read the declared kinds, so the filter names them as administered. */\n\t\tasync loadKinds() {\n\t\t\ttry {\n\t\t\t\tconst response = await axios.get(prefixUrl(`${this.base}/timeline/kinds`))\n\t\t\t\tthis.kinds = response.data?.results || []\n\t\t\t} catch {\n\t\t\t\tthis.kinds = []\n\t\t\t}\n\t\t},\n\n\t\t/** Read the seeded standard notes. */\n\t\tasync loadTextBlocks() {\n\t\t\ttry {\n\t\t\t\tconst response = await axios.get(prefixUrl(`${this.base}/timeline/text-blocks`))\n\t\t\t\tthis.textBlocks = response.data?.results || []\n\t\t\t} catch {\n\t\t\t\tthis.textBlocks = []\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Note which standard note was picked. The BLOCK is sent, not its body:\n\t\t * OpenRegister fills the object's own values into it on the way in.\n\t\t *\n\t\t * @param {object|null} block The picked option.\n\t\t */\n\t\tpickBlock(block) {\n\t\t\tthis.chosenBlock = block || null\n\t\t\tif (block) {\n\t\t\t\tconst declared = this.textBlocks.find((entry) => entry.slug === block.id)\n\t\t\t\tthis.draft = declared?.title || block.label\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Write the drafted note onto this object.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync submit() {\n\t\t\tif (!this.draft.trim() || !this.timelineUrl) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.saving = true\n\t\t\tthis.error = ''\n\t\t\ttry {\n\t\t\t\tconst payload = { visibility: this.draftIsPublic ? 'public' : 'internal' }\n\t\t\t\tif (this.chosenBlock?.id) {\n\t\t\t\t\tpayload.textBlock = this.chosenBlock.id\n\t\t\t\t} else {\n\t\t\t\t\tpayload.message = this.draft\n\t\t\t\t}\n\t\t\t\tawait axios.post(this.timelineUrl, payload)\n\t\t\t\tthis.draft = ''\n\t\t\t\tthis.chosenBlock = null\n\t\t\t\tthis.draftIsPublic = false\n\t\t\t\tawait this.load()\n\t\t\t} catch {\n\t\t\t\tthis.error = t('nextcloud-vue', 'That note could not be saved.')\n\t\t\t} finally {\n\t\t\t\tthis.saving = false\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Read the timeline with the visibility filter, if one is set.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync load() {\n\t\t\tif (!this.timelineUrl) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.loading = true\n\t\t\tthis.error = ''\n\t\t\ttry {\n\t\t\t\tconst params = {}\n\t\t\t\tif (this.visibilityFilter?.id) {\n\t\t\t\t\tparams.visibility = this.visibilityFilter.id\n\t\t\t\t}\n\t\t\t\tconst response = await axios.get(this.timelineUrl, { params })\n\t\t\t\tthis.canManage = response.data?.canManage === true\n\t\t\t\tthis.allEntries = response.data?.results || []\n\t\t\t\tthis.entries = this.applyKindFilter(this.allEntries)\n\t\t\t} catch {\n\t\t\t\tthis.allEntries = []\n\t\t\t\tthis.entries = []\n\t\t\t\tthis.error = t('nextcloud-vue', 'The timeline could not be read. Try again, or ask an administrator to check OpenRegister.')\n\t\t\t} finally {\n\t\t\t\tthis.loading = false\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Show one kind, or every kind for `null`, without reading again.\n\t\t *\n\t\t * @param {string|null} id The kind slug, '' for a note, null for all.\n\t\t */\n\t\tchooseKind(id) {\n\t\t\tthis.kindFilter = id === null ? null : { id }\n\t\t\tthis.entries = this.applyKindFilter(this.allEntries)\n\t\t},\n\n\t\t/**\n\t\t * The kind filter is applied in the reading: the list endpoint does not\n\t\t * read a kind parameter, so sending one would be dropped in silence.\n\t\t *\n\t\t * @param {Array<object>} results The entries as read.\n\t\t * @return {Array<object>} The entries to show.\n\t\t */\n\t\tapplyKindFilter(results) {\n\t\t\tif (!this.kindFilter) {\n\t\t\t\treturn results\n\t\t\t}\n\t\t\tconst wanted = this.kindFilter.id || ''\n\t\t\treturn results.filter((entry) => (entry.kind || '') === wanted)\n\t\t},\n\n\t\t/**\n\t\t * The shown entries as CSV: when, kind, who, visibility and what.\n\t\t *\n\t\t * @return {string} The CSV text.\n\t\t */\n\t\tentriesCsv() {\n\t\t\tconst cell = (value) => `\"${String(value ?? '').replace(/\"/g, '\"\"')}\"`\n\t\t\tconst rows = [[t('nextcloud-vue', 'When'), t('nextcloud-vue', 'Kind'), t('nextcloud-vue', 'Who'), t('nextcloud-vue', 'Visibility'), t('nextcloud-vue', 'Message')]]\n\t\t\tfor (const entry of this.entries) {\n\t\t\t\trows.push([entry.created, this.kindLabel(entry), entry.author, entry.visibility, entry.message])\n\t\t\t}\n\t\t\treturn rows.map((row) => row.map(cell).join(',')).join('\\r\\n')\n\t\t},\n\n\t\t/** Download the shown entries as a CSV file. */\n\t\texportEntries() {\n\t\t\tconst blob = new Blob([this.entriesCsv()], { type: 'text/csv;charset=utf-8' })\n\t\t\tconst url = URL.createObjectURL(blob)\n\t\t\tconst link = document.createElement('a')\n\t\t\tlink.href = url\n\t\t\tlink.download = `${this.content.exportName || 'history'}-${this.objectId || 'record'}.csv`\n\t\t\tdocument.body.appendChild(link)\n\t\t\tlink.click()\n\t\t\tlink.remove()\n\t\t\tURL.revokeObjectURL(url)\n\t\t},\n\n\t\t/** Bring the composer into view and focus its text. */\n\t\tfocusComposer() {\n\t\t\tconst form = this.$refs.composer\n\t\t\tif (!form) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tform.scrollIntoView?.({ behavior: 'smooth', block: 'center' })\n\t\t\tform.querySelector('textarea')?.focus()\n\t\t},\n\n\t\t/**\n\t\t * The label of one entry's kind, falling back to \"Note\".\n\t\t *\n\t\t * @param {object} entry The entry.\n\t\t * @return {string} The label.\n\t\t */\n\t\tkindLabel(entry) {\n\t\t\tif (!entry.kind) {\n\t\t\t\treturn t('nextcloud-vue', 'Note')\n\t\t\t}\n\t\t\tconst declared = this.kinds.find((kind) => kind.slug === entry.kind)\n\t\t\treturn declared?.title || entry.kind\n\t\t},\n\n\t\t/**\n\t\t * One moment in the reader's locale.\n\t\t *\n\t\t * @param {string} value An ISO 8601 stamp.\n\t\t * @return {string} The moment, or the raw value.\n\t\t */\n\t\tmoment(value) {\n\t\t\tif (!value) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tconst parsed = new Date(value)\n\t\t\treturn isNaN(parsed.getTime()) ? value : parsed.toLocaleString()\n\t\t},\n\n\t\tasync togglePin(entry) {\n\t\t\tawait this.patch(entry, { pinned: !entry.pinned })\n\t\t},\n\n\t\tasync closeFollowUp(entry) {\n\t\t\tawait this.patch(entry, { followUp: 'done' })\n\t\t},\n\n\t\t/**\n\t\t * Write one change onto one entry and read the timeline back (pinning\n\t\t * changes the order, so patching in place would look like nothing).\n\t\t *\n\t\t * @param {object} entry The entry.\n\t\t * @param {object} changes The fields to write.\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync patch(entry, changes) {\n\t\t\ttry {\n\t\t\t\tawait axios.patch(`${this.timelineUrl}/${entry.id}`, changes)\n\t\t\t\tawait this.load()\n\t\t\t} catch {\n\t\t\t\tthis.error = t('nextcloud-vue', 'That change could not be saved.')\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * The configured entry actions that apply to one entry (`kinds` limits\n\t\t * an action to entries of those kinds).\n\t\t *\n\t\t * @param {object} entry The entry.\n\t\t * @return {Array<object>} The actions.\n\t\t */\n\t\tactionsFor(entry) {\n\t\t\treturn this.entryActions.filter((action) => !Array.isArray(action.kinds) || action.kinds.includes(entry.kind || ''))\n\t\t},\n\n\t\t/**\n\t\t * Resolve `@objectId` and `@row.<path>` tokens in an action's props.\n\t\t *\n\t\t * @param {object} props The props as declared.\n\t\t * @param {object} entry The entry.\n\t\t * @return {object} The resolved props.\n\t\t */\n\t\tresolveProps(props, entry) {\n\t\t\tconst out = {}\n\t\t\tfor (const [key, value] of Object.entries(props || {})) {\n\t\t\t\tif (value === '@objectId') {\n\t\t\t\t\tout[key] = this.objectId\n\t\t\t\t} else if (typeof value === 'string' && value.startsWith('@row.')) {\n\t\t\t\t\tconst found = readPath(entry, value.slice('@row.'.length))\n\t\t\t\t\tout[key] = found === undefined || found === null ? '' : found\n\t\t\t\t} else {\n\t\t\t\t\tout[key] = value\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn out\n\t\t},\n\n\t\t/**\n\t\t * Open an entry action's modal from the app's registry. On its\n\t\t * `doneEvent` (default `done`) the entry's open follow-up is closed when\n\t\t * the action says so; otherwise the timeline is read again.\n\t\t *\n\t\t * @param {object} action The action.\n\t\t * @param {object} entry The entry.\n\t\t */\n\t\topenAction(action, entry) {\n\t\t\tconst registered = (this.cnRegistry || {})[action.modal]\n\t\t\tconst component = registered && (registered.component || registered)\n\t\t\tif (!component) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn(`[CnTimelineWidget] entry action \"${action.id}\" names modal \"${action.modal}\", which the registry does not hold.`)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst close = () => {\n\t\t\t\tthis.activeModal = null\n\t\t\t}\n\t\t\tconst done = async () => {\n\t\t\t\tthis.activeModal = null\n\t\t\t\tif (action.closesFollowUp === true && entry.followUp === 'open') {\n\t\t\t\t\tawait this.closeFollowUp(entry)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tawait this.load()\n\t\t\t}\n\t\t\tthis.activeModal = {\n\t\t\t\tcomponent,\n\t\t\t\tprops: this.resolveProps(action.props, entry),\n\t\t\t\tlisteners: { [action.doneEvent || 'done']: done, close },\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-timeline-manage__header {\n\tdisplay: flex;\n\talign-items: flex-start;\n\tjustify-content: space-between;\n\tgap: 12px;\n\tmargin-block-end: 16px;\n}\n\n.cn-timeline-manage__heading {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 4px;\n}\n\n.cn-timeline-manage__header-actions {\n\tdisplay: flex;\n\tgap: 8px;\n}\n\n.cn-timeline-manage__title {\n\tmargin: 0;\n\tfont-size: 17px;\n\tfont-weight: 700;\n\tline-height: 1.2;\n}\n\n.cn-timeline-manage__subtitle {\n\tmargin: 0;\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 14px;\n}\n\n.cn-timeline-manage__chips {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\tgap: 8px;\n\tmargin-block-end: 12px;\n}\n\n.cn-timeline-manage__chip {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tgap: 8px;\n\tbox-sizing: border-box;\n\theight: 36px;\n\tpadding: 0 12px;\n\tborder: 1px solid var(--color-border-dark);\n\tborder-radius: 18px;\n\tbackground: var(--color-main-background);\n\tcolor: var(--color-main-text);\n\tfont-size: 14px;\n\tfont-weight: 600;\n\tcursor: pointer;\n}\n\n/* The chosen kind is a filled chip with no outline. */\n.cn-timeline-manage__chip--active {\n\tborder: 0;\n\tbackground: var(--color-main-text);\n\tcolor: var(--color-main-background);\n}\n\n.cn-timeline-manage__chip-count {\n\tpadding: 1px 7px;\n\tborder-radius: 10px;\n\tbackground: var(--color-border);\n\tcolor: var(--color-main-text);\n\tfont-size: 12px;\n}\n\n/* On the filled chip the count is a lighter ink bubble with light text. */\n.cn-timeline-manage__chip--active .cn-timeline-manage__chip-count {\n\tbackground: color-mix(in srgb, var(--color-main-background) 18%, var(--color-main-text));\n\tcolor: var(--color-main-background);\n}\n\n.cn-timeline-manage__count {\n\tmargin: 12px 0 0;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-timeline-manage__composer {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 8px;\n\tmargin-block-start: 24px;\n\tpadding-block-start: 16px;\n\tborder-block-start: 1px solid var(--color-border);\n}\n\n.cn-timeline-manage__composer-title {\n\tmargin: 0;\n\tfont-size: 16px;\n\tfont-weight: bold;\n}\n\n.cn-timeline-manage__composer-hint {\n\tmargin: 0;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-timeline-manage__draft-label {\n\tfont-weight: bold;\n}\n\n.cn-timeline-manage__draft {\n\twidth: 100%;\n\tmin-height: 70px;\n}\n\n.cn-timeline-manage__controls {\n\tdisplay: flex;\n\tgap: 12px;\n\tflex-wrap: wrap;\n\tmargin-block-end: 12px;\n}\n\n.cn-timeline-manage__filter {\n\tmin-width: 200px;\n}\n\n.cn-timeline-manage__list {\n\tlist-style: none;\n\tmargin: 0;\n\tpadding: 0;\n}\n\n.cn-timeline-manage__entry {\n\tborder-block-end: 1px solid var(--color-border);\n\tpadding-block: 12px;\n}\n\n.cn-timeline-manage__entry--pinned {\n\tborder-inline-start: 3px solid var(--color-primary-element);\n\tpadding-inline-start: 8px;\n}\n\n.cn-timeline-manage__head {\n\tdisplay: flex;\n\tgap: 8px;\n\tflex-wrap: wrap;\n\talign-items: baseline;\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 0.9em;\n}\n\n.cn-timeline-manage__kind {\n\tfont-weight: bold;\n\tcolor: var(--color-main-text);\n}\n\n.cn-timeline-manage__badge {\n\tborder: 1px solid var(--color-border);\n\tborder-radius: var(--border-radius);\n\tpadding: 0 6px;\n}\n\n.cn-timeline-manage__badge--open {\n\tborder-color: var(--color-warning);\n\tcolor: var(--color-warning-text);\n}\n\n.cn-timeline-manage__message {\n\tmargin-block: 4px 0;\n\twhite-space: pre-wrap;\n}\n\n.cn-timeline-manage__siblings {\n\tmargin-block: 4px 0;\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 0.9em;\n}\n\n.cn-timeline-manage__actions {\n\tdisplay: flex;\n\tgap: 8px;\n\tmargin-block-start: 4px;\n}\n</style>\n"],"names":["_openBlock","_createElementBlock","_createElementVNode","_toDisplayString","_createBlock","_createVNode","_createTextVNode","_normalizeClass","_Fragment","_renderList"],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@ import script from './CnTimelineWidget.vue2.js';
|
|
|
2
2
|
import { render } from './CnTimelineWidget.vue3.js';
|
|
3
3
|
|
|
4
4
|
script.render = render;
|
|
5
|
-
script.__scopeId = "data-v-
|
|
5
|
+
script.__scopeId = "data-v-7ed4cc4c";
|
|
6
6
|
const __sfc_main = script;
|
|
7
7
|
|
|
8
8
|
export { __sfc_main as default };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { translate, getLanguage } from '@nextcloud/l10n';
|
|
2
2
|
import { NcLoadingIcon, NcNoteCard } from '@nextcloud/vue';
|
|
3
|
+
import __sfc_main from './CnTimelineManage.vue.js';
|
|
3
4
|
import { fieldEvents, listEvents, relatedEvents, auditEvents, timelineEntryEvents, sortEvents } from '../../utils/timelineEvents.js';
|
|
4
5
|
import { userLocale } from '../../utils/userLocale.js';
|
|
5
6
|
|
|
@@ -21,6 +22,12 @@ import { userLocale } from '../../utils/userLocale.js';
|
|
|
21
22
|
* Oldest first by default (`order: 'desc'` flips it). A moment after now is
|
|
22
23
|
* marked upcoming, in words as well as style.
|
|
23
24
|
*
|
|
25
|
+
* `manage: true` swaps the read view for the manage view (CnTimelineManage)
|
|
26
|
+
* over OpenRegister's timeline alone: kind chips, a visibility filter, pin,
|
|
27
|
+
* follow-up, a note composer with standard text blocks, CSV export, and
|
|
28
|
+
* `entryActions` that open a registry modal on an entry. The manage controls
|
|
29
|
+
* are drawn only when the timeline read answers `canManage: true`.
|
|
30
|
+
*
|
|
24
31
|
* ```json
|
|
25
32
|
* { "type": "timeline", "content": {
|
|
26
33
|
* "title": "Timeline",
|
|
@@ -42,6 +49,7 @@ var script = {
|
|
|
42
49
|
name: 'CnTimelineWidget',
|
|
43
50
|
|
|
44
51
|
components: {
|
|
52
|
+
CnTimelineManage: __sfc_main,
|
|
45
53
|
NcLoadingIcon,
|
|
46
54
|
NcNoteCard,
|
|
47
55
|
},
|
|
@@ -70,7 +78,7 @@ var script = {
|
|
|
70
78
|
object: { type: Object, default: null },
|
|
71
79
|
/** Card title override. */
|
|
72
80
|
title: { type: String, default: '' },
|
|
73
|
-
/** Stored widget content: `{ title, fields, related, auditTrail, timeline, order }`. */
|
|
81
|
+
/** Stored widget content: `{ title, fields, related, auditTrail, timeline, order, manage, entryActions, ... }`. */
|
|
74
82
|
content: { type: Object, default: () => ({}) },
|
|
75
83
|
/** OpenRegister API base. */
|
|
76
84
|
apiBase: { type: String, default: '/apps/openregister/api' },
|
|
@@ -119,6 +127,15 @@ var script = {
|
|
|
119
127
|
return this.object || this.ctx.object || this.ctx.objectData || this.fetchedObject || null
|
|
120
128
|
},
|
|
121
129
|
|
|
130
|
+
/**
|
|
131
|
+
* Whether the manage view renders instead of the read view.
|
|
132
|
+
*
|
|
133
|
+
* @return {boolean}
|
|
134
|
+
*/
|
|
135
|
+
manage() {
|
|
136
|
+
return this.content.manage === true
|
|
137
|
+
},
|
|
138
|
+
|
|
122
139
|
resolvedTitle() {
|
|
123
140
|
const raw = this.title || this.content.title || '';
|
|
124
141
|
return raw ? this.translate(raw) : ''
|
|
@@ -260,7 +277,7 @@ var script = {
|
|
|
260
277
|
const register = this.resolvedRegister;
|
|
261
278
|
const schema = this.resolvedSchema;
|
|
262
279
|
const seq = ++this.loadSeq;
|
|
263
|
-
if (!id || !register || !schema) {
|
|
280
|
+
if (!id || !register || !schema || this.manage) {
|
|
264
281
|
return
|
|
265
282
|
}
|
|
266
283
|
const [{ default: axios }, { generateUrl }] = await Promise.all([
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CnTimelineWidget.vue2.js","sources":["../../../../src/components/CnTimelineWidget/CnTimelineWidget.vue"],"sourcesContent":["<!-- SPDX-License-Identifier: EUPL-1.2 -->\n<!-- SPDX-FileCopyrightText: 2026 Conduction B.V. <info@conduction.nl> -->\n<template>\n\t<section class=\"cn-timeline-widget\" data-testid=\"cn-timeline-widget\" :aria-busy=\"loading ? 'true' : 'false'\">\n\t\t<h3 v-if=\"resolvedTitle\" class=\"cn-timeline-widget__title\">\n\t\t\t{{ resolvedTitle }}\n\t\t</h3>\n\n\t\t<div v-if=\"loading && events.length === 0\" class=\"cn-timeline-widget__loading\">\n\t\t\t<NcLoadingIcon :size=\"24\" aria-hidden=\"true\" />\n\t\t\t<span>{{ loadingLabel }}</span>\n\t\t</div>\n\n\t\t<template v-else>\n\t\t\t<!-- A failed read is not an empty history: say which part is missing. -->\n\t\t\t<NcNoteCard v-if=\"failedSources.length > 0\" type=\"warning\" data-testid=\"cn-timeline-widget-error\">\n\t\t\t\t{{ failedText }}\n\t\t\t</NcNoteCard>\n\n\t\t\t<p v-if=\"events.length === 0\" class=\"cn-timeline-widget__empty\" data-testid=\"cn-timeline-widget-empty\">\n\t\t\t\t{{ emptyLabel }}\n\t\t\t</p>\n\n\t\t\t<ol v-else class=\"cn-timeline-widget__list\">\n\t\t\t\t<li\n\t\t\t\t\tv-for=\"event in events\"\n\t\t\t\t\t:key=\"event.id\"\n\t\t\t\t\tclass=\"cn-timeline-widget__event\"\n\t\t\t\t\t:class=\"{ 'cn-timeline-widget__event--upcoming': event.upcoming }\"\n\t\t\t\t\t:data-source=\"event.source\"\n\t\t\t\t\tdata-testid=\"cn-timeline-widget-event\">\n\t\t\t\t\t<span class=\"cn-timeline-widget__dot\" aria-hidden=\"true\" />\n\t\t\t\t\t<div class=\"cn-timeline-widget__body\">\n\t\t\t\t\t\t<time class=\"cn-timeline-widget__when\" :datetime=\"event.at.toISOString()\">\n\t\t\t\t\t\t\t{{ formatMoment(event) }}\n\t\t\t\t\t\t</time>\n\t\t\t\t\t\t<span v-if=\"event.upcoming\" class=\"cn-timeline-widget__badge\">\n\t\t\t\t\t\t\t{{ upcomingLabel }}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<p class=\"cn-timeline-widget__label\">\n\t\t\t\t\t\t\t{{ translate(event.label) }}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t\t<p v-if=\"event.detail\" class=\"cn-timeline-widget__detail\">\n\t\t\t\t\t\t\t{{ event.detail }}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t</div>\n\t\t\t\t</li>\n\t\t\t</ol>\n\t\t</template>\n\t</section>\n</template>\n\n<script>\nimport { getLanguage, translate as t } from '@nextcloud/l10n'\nimport { NcLoadingIcon, NcNoteCard } from '@nextcloud/vue'\nimport { auditEvents, fieldEvents, listEvents, relatedEvents, sortEvents, timelineEntryEvents } from '../../utils/timelineEvents.js'\nimport { userLocale } from '../../utils/userLocale.js'\n\n/**\n * CnTimelineWidget — an object's dated events in time order (`timeline`\n * widget type for detail pages).\n *\n * Generalises dossiq's case timeline. It merges up to four sources, all\n * optional, into one list:\n *\n * - `fields`: the object's own date properties, `[{ field, label }]`. A\n * dotted path reaches metadata, such as `@self.created`.\n * - `related`: related objects, `[{ register?, schema, field, dateField?,\n * label, titleField? }]`. Rows of `schema` whose `field` holds this object's\n * id become events at their `dateField` (default `@self.created`).\n * - `auditTrail: true`: the object's audit trail, one event per change.\n * - `timeline: true`: OpenRegister's timeline of notes, calls and messages.\n *\n * Oldest first by default (`order: 'desc'` flips it). A moment after now is\n * marked upcoming, in words as well as style.\n *\n * ```json\n * { \"type\": \"timeline\", \"content\": {\n * \"title\": \"Timeline\",\n * \"fields\": [\n * { \"field\": \"@self.created\", \"label\": \"Booking created\" },\n * { \"field\": \"depositClearedAt\", \"label\": \"Deposit cleared\" },\n * { \"field\": \"confirmationSentAt\", \"label\": \"Confirmation mail sent\" },\n * { \"field\": \"startsAt\", \"label\": \"Starts\" },\n * { \"field\": \"endsAt\", \"label\": \"Ends\" }\n * ] } }\n * ```\n *\n * The object comes from the detail page's context, like `audit-trail`:\n * explicit props win, then the injects, then `content`.\n *\n * @spec openspec/changes/timeline-widget/specs/timeline-widget/spec.md#requirement-a-timeline-widget-shows-an-objects-dated-events-in-order\n */\nexport default {\n\tname: 'CnTimelineWidget',\n\n\tcomponents: {\n\t\tNcLoadingIcon,\n\t\tNcNoteCard,\n\t},\n\n\tinject: {\n\t\t/** Detail-page object context from CnDetailPage (a ref or a raw bag). */\n\t\tcnObjectContext: { default: null },\n\t\t/** Detail object context holder from CnPageRenderer (`{ value: { objectData, ... } }`). */\n\t\tcnDetailObjectContext: { default: null },\n\t\t/** Consumer translation function; labels are authored in English. */\n\t\tcnTranslate: { default: () => (key) => key },\n\t},\n\n\tprops: {\n\t\t/** Register slug; object context spread as props by CnWidgetGrid. */\n\t\tregister: { type: String, default: '' },\n\t\t/**\n\t\t * Schema slug, or the schema object the detail context supplies.\n\t\t *\n\t\t * @type {string|object}\n\t\t */\n\t\tschema: { type: [String, Object], default: '' },\n\t\t/** The object's id. */\n\t\tobjectId: { type: String, default: '' },\n\t\t/** The object itself, when the host already has it. */\n\t\tobject: { type: Object, default: null },\n\t\t/** Card title override. */\n\t\ttitle: { type: String, default: '' },\n\t\t/** Stored widget content: `{ title, fields, related, auditTrail, timeline, order }`. */\n\t\tcontent: { type: Object, default: () => ({}) },\n\t\t/** OpenRegister API base. */\n\t\tapiBase: { type: String, default: '/apps/openregister/api' },\n\t},\n\n\tdata() {\n\t\treturn {\n\t\t\tloading: false,\n\t\t\trelatedRows: {},\n\t\t\tauditEntries: [],\n\t\t\ttimelineEntries: [],\n\t\t\tfailedSources: [],\n\t\t\tfetchedObject: null,\n\t\t\tloadSeq: 0,\n\t\t}\n\t},\n\n\tcomputed: {\n\t\tctx() {\n\t\t\tconst raw = this.cnObjectContext\n\t\t\tconst inj = raw && (raw.value !== undefined ? raw.value : raw)\n\t\t\tconst holder = this.cnDetailObjectContext && this.cnDetailObjectContext.value\n\t\t\treturn inj || holder || {}\n\t\t},\n\n\t\tresolvedObjectId() {\n\t\t\treturn this.objectId || this.ctx.objectId || this.content.objectId || ''\n\t\t},\n\n\t\tresolvedRegister() {\n\t\t\treturn this.register || this.ctx.register || this.content.register || ''\n\t\t},\n\n\t\tresolvedSchema() {\n\t\t\tconst s = this.schema || this.ctx.schema || this.content.schema || ''\n\t\t\treturn typeof s === 'string' ? s : (s && (s.slug || s.name || s.id)) || ''\n\t\t},\n\n\t\t/**\n\t\t * The object: explicit prop, then the page context, then a fetch of\n\t\t * our own when only the id is known.\n\t\t *\n\t\t * @return {object|null}\n\t\t */\n\t\tresolvedObject() {\n\t\t\treturn this.object || this.ctx.object || this.ctx.objectData || this.fetchedObject || null\n\t\t},\n\n\t\tresolvedTitle() {\n\t\t\tconst raw = this.title || this.content.title || ''\n\t\t\treturn raw ? this.translate(raw) : ''\n\t\t},\n\n\t\tfieldsConfig() {\n\t\t\treturn Array.isArray(this.content.fields) ? this.content.fields : []\n\t\t},\n\n\t\trelatedConfig() {\n\t\t\treturn Array.isArray(this.content.related) ? this.content.related.filter((r) => r && r.schema && r.field) : []\n\t\t},\n\n\t\t/**\n\t\t * Every event from every source, in time order.\n\t\t *\n\t\t * @return {Array<object>}\n\t\t */\n\t\tevents() {\n\t\t\tconst now = new Date()\n\t\t\tconst all = [\n\t\t\t\t...fieldEvents(this.resolvedObject || {}, this.fieldsConfig, now),\n\t\t\t\t...listEvents(this.resolvedObject || {}, this.content.lists, now),\n\t\t\t\t...this.relatedConfig.flatMap((cfg, i) => relatedEvents(this.relatedRows[i] || [], cfg, now)),\n\t\t\t\t...auditEvents(this.auditEntries, this.describeAudit, now),\n\t\t\t\t...timelineEntryEvents(this.timelineEntries, t('nextcloud-vue', 'Note'), now),\n\t\t\t]\n\t\t\treturn sortEvents(all, this.content.order === 'desc' ? 'desc' : 'asc')\n\t\t},\n\n\t\t/**\n\t\t * A signature of what to fetch, so a change refetches once.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\tloadKey() {\n\t\t\treturn JSON.stringify({\n\t\t\t\tid: this.resolvedObjectId,\n\t\t\t\tregister: this.resolvedRegister,\n\t\t\t\tschema: this.resolvedSchema,\n\t\t\t\trelated: this.relatedConfig,\n\t\t\t\taudit: this.content.auditTrail === true,\n\t\t\t\ttimeline: this.content.timeline === true,\n\t\t\t\tneedObject: this.fieldsConfig.length > 0 && !(this.object || this.ctx.object || this.ctx.objectData),\n\t\t\t})\n\t\t},\n\n\t\tfailedText() {\n\t\t\treturn t('nextcloud-vue', 'Part of the timeline could not load: {parts}.', {\n\t\t\t\tparts: this.failedSources.map((s) => this.sourceName(s)).join(', '),\n\t\t\t})\n\t\t},\n\n\t\tloadingLabel() {\n\t\t\treturn t('nextcloud-vue', 'Loading…')\n\t\t},\n\n\t\temptyLabel() {\n\t\t\treturn t('nextcloud-vue', 'Nothing has happened yet.')\n\t\t},\n\n\t\tupcomingLabel() {\n\t\t\treturn t('nextcloud-vue', 'Upcoming')\n\t\t},\n\t},\n\n\twatch: {\n\t\tloadKey: {\n\t\t\timmediate: true,\n\t\t\thandler() {\n\t\t\t\tthis.load()\n\t\t\t},\n\t\t},\n\t},\n\n\tmethods: {\n\t\ttranslate(text) {\n\t\t\treturn text ? this.cnTranslate(text) : ''\n\t\t},\n\n\t\tsourceName(source) {\n\t\t\tif (source === 'audit') {\n\t\t\t\treturn t('nextcloud-vue', 'changes')\n\t\t\t}\n\t\t\tif (source === 'timeline') {\n\t\t\t\treturn t('nextcloud-vue', 'notes and messages')\n\t\t\t}\n\t\t\tif (source === 'object') {\n\t\t\t\treturn t('nextcloud-vue', 'dates')\n\t\t\t}\n\t\t\treturn t('nextcloud-vue', 'related items')\n\t\t},\n\n\t\t/**\n\t\t * The label of an audit event, from its action and who did it.\n\t\t *\n\t\t * @param {string} action The audit action (create, update, delete).\n\t\t * @param {string} actor Who did it.\n\t\t * @return {string}\n\t\t */\n\t\tdescribeAudit(action, actor) {\n\t\t\tconst known = {\n\t\t\t\tcreate: t('nextcloud-vue', 'Created'),\n\t\t\t\tupdate: t('nextcloud-vue', 'Updated'),\n\t\t\t\tdelete: t('nextcloud-vue', 'Deleted'),\n\t\t\t}\n\t\t\tconst what = known[action] || action || t('nextcloud-vue', 'Changed')\n\t\t\treturn actor ? t('nextcloud-vue', '{action} by {actor}', { action: what, actor }) : what\n\t\t},\n\n\t\t/**\n\t\t * Show a moment in the reader's language: a date for a calendar day,\n\t\t * date and time otherwise.\n\t\t *\n\t\t * @param {object} event The event.\n\t\t * @return {string}\n\t\t */\n\t\tformatMoment(event) {\n\t\t\tconst locale = (typeof getLanguage === 'function' && getLanguage()) || undefined\n\t\t\tconst options = event.dateOnly\n\t\t\t\t? { dateStyle: 'medium' }\n\t\t\t\t: { dateStyle: 'medium', timeStyle: 'short' }\n\t\t\ttry {\n\t\t\t\treturn new Intl.DateTimeFormat(locale, options).format(event.at)\n\t\t\t} catch {\n\t\t\t\treturn event.at.toLocaleString(userLocale())\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Fetch every configured source. Each one fails on its own, so one\n\t\t * unreachable source never hides the others.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t * @spec openspec/changes/timeline-widget/specs/timeline-widget/spec.md#requirement-a-timeline-widget-shows-an-objects-dated-events-in-order\n\t\t */\n\t\tasync load() {\n\t\t\tconst id = this.resolvedObjectId\n\t\t\tconst register = this.resolvedRegister\n\t\t\tconst schema = this.resolvedSchema\n\t\t\tconst seq = ++this.loadSeq\n\t\t\tif (!id || !register || !schema) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst [{ default: axios }, { generateUrl }] = await Promise.all([\n\t\t\t\timport('@nextcloud/axios'),\n\t\t\t\timport('@nextcloud/router'),\n\t\t\t])\n\t\t\tconst base = `${this.apiBase}/objects/${register}/${schema}/${id}`\n\t\t\tconst failed = []\n\t\t\tconst jobs = []\n\n\t\t\tif (this.fieldsConfig.length > 0 && !(this.object || this.ctx.object || this.ctx.objectData)) {\n\t\t\t\tjobs.push(axios.get(generateUrl(base))\n\t\t\t\t\t.then((r) => {\n\t\t\t\t\t\tthis.fetchedObject = (r && r.data) || null\n\t\t\t\t\t})\n\t\t\t\t\t.catch(() => failed.push('object')))\n\t\t\t}\n\n\t\t\tconst rows = {}\n\t\t\tthis.relatedConfig.forEach((cfg, i) => {\n\t\t\t\tconst url = generateUrl(`${this.apiBase}/objects/${cfg.register || register}/${cfg.schema}`)\n\t\t\t\tjobs.push(axios.get(url, { params: { [cfg.field]: id, _limit: cfg.limit || 50 } })\n\t\t\t\t\t.then((r) => {\n\t\t\t\t\t\tconst data = r && r.data\n\t\t\t\t\t\trows[i] = (data && (data.results || data)) || []\n\t\t\t\t\t})\n\t\t\t\t\t.catch(() => {\n\t\t\t\t\t\trows[i] = []\n\t\t\t\t\t\tif (!failed.includes('related')) {\n\t\t\t\t\t\t\tfailed.push('related')\n\t\t\t\t\t\t}\n\t\t\t\t\t}))\n\t\t\t})\n\n\t\t\tif (this.content.auditTrail === true) {\n\t\t\t\tjobs.push(axios.get(generateUrl(`${base}/audit-trails`), { params: { limit: this.content.auditLimit || 50 } })\n\t\t\t\t\t.then((r) => {\n\t\t\t\t\t\tconst data = r && r.data\n\t\t\t\t\t\tthis.auditEntries = (data && (data.results || data)) || []\n\t\t\t\t\t})\n\t\t\t\t\t.catch(() => {\n\t\t\t\t\t\tthis.auditEntries = []\n\t\t\t\t\t\tfailed.push('audit')\n\t\t\t\t\t}))\n\t\t\t}\n\n\t\t\tif (this.content.timeline === true) {\n\t\t\t\tjobs.push(axios.get(generateUrl(`${base}/timeline`))\n\t\t\t\t\t.then((r) => {\n\t\t\t\t\t\tconst data = r && r.data\n\t\t\t\t\t\tthis.timelineEntries = (data && (data.results || data)) || []\n\t\t\t\t\t})\n\t\t\t\t\t.catch(() => {\n\t\t\t\t\t\tthis.timelineEntries = []\n\t\t\t\t\t\tfailed.push('timeline')\n\t\t\t\t\t}))\n\t\t\t}\n\n\t\t\tif (jobs.length === 0) {\n\t\t\t\tthis.failedSources = []\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.loading = true\n\t\t\tawait Promise.all(jobs)\n\t\t\tif (seq !== this.loadSeq) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.relatedRows = rows\n\t\t\tthis.failedSources = failed\n\t\t\tthis.loading = false\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-timeline-widget {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 8px;\n}\n\n.cn-timeline-widget__title {\n\tmargin: 0;\n\tfont-size: var(--font-size-large, 1.1em);\n}\n\n.cn-timeline-widget__loading {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 8px;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-timeline-widget__empty {\n\tmargin: 0;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-timeline-widget__list {\n\tmargin: 0;\n\tpadding: 0;\n\tlist-style: none;\n}\n\n.cn-timeline-widget__event {\n\tposition: relative;\n\tdisplay: flex;\n\tgap: 12px;\n\tpadding-block-end: 12px;\n}\n\n/* The line between dots: drawn from each dot down to the next event. */\n.cn-timeline-widget__event:not(:last-child)::before {\n\tcontent: '';\n\tposition: absolute;\n\tinset-block: 14px 0;\n\tinset-inline-start: 5px;\n\tborder-inline-start: 2px solid var(--color-border-dark);\n}\n\n.cn-timeline-widget__dot {\n\tflex: 0 0 auto;\n\twidth: 12px;\n\theight: 12px;\n\tmargin-block-start: 4px;\n\tborder-radius: 50%;\n\tbackground-color: var(--color-primary-element);\n}\n\n/* Upcoming: a hollow dot, plus the word \"Upcoming\" beside the date. */\n.cn-timeline-widget__event--upcoming .cn-timeline-widget__dot {\n\tbox-sizing: border-box;\n\tborder: 2px solid var(--color-primary-element);\n\tbackground-color: var(--color-main-background);\n}\n\n.cn-timeline-widget__body {\n\tmin-width: 0;\n}\n\n.cn-timeline-widget__when {\n\tfont-size: var(--font-size-small, 13px);\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-timeline-widget__badge {\n\tmargin-inline-start: 8px;\n\tfont-size: var(--font-size-small, 13px);\n\tfont-weight: bold;\n\tcolor: var(--color-main-text);\n}\n\n.cn-timeline-widget__label {\n\tmargin: 0;\n\tfont-weight: bold;\n}\n\n.cn-timeline-widget__detail {\n\tmargin: 0;\n\toverflow-wrap: anywhere;\n}\n</style>\n"],"names":["t"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CnTimelineWidget.vue2.js","sources":["../../../../src/components/CnTimelineWidget/CnTimelineWidget.vue"],"sourcesContent":["<!-- SPDX-License-Identifier: EUPL-1.2 -->\n<!-- SPDX-FileCopyrightText: 2026 Conduction B.V. <info@conduction.nl> -->\n<template>\n\t<CnTimelineManage v-if=\"manage\"\n\t\t:register=\"resolvedRegister\"\n\t\t:schema=\"resolvedSchema\"\n\t\t:objectId=\"resolvedObjectId\"\n\t\t:apiBase=\"apiBase\"\n\t\t:content=\"content\" />\n\t<section v-else\n\t\tclass=\"cn-timeline-widget\"\n\t\tdata-testid=\"cn-timeline-widget\"\n\t\t:aria-busy=\"loading ? 'true' : 'false'\">\n\t\t<h3 v-if=\"resolvedTitle\" class=\"cn-timeline-widget__title\">\n\t\t\t{{ resolvedTitle }}\n\t\t</h3>\n\n\t\t<div v-if=\"loading && events.length === 0\" class=\"cn-timeline-widget__loading\">\n\t\t\t<NcLoadingIcon :size=\"24\" aria-hidden=\"true\" />\n\t\t\t<span>{{ loadingLabel }}</span>\n\t\t</div>\n\n\t\t<template v-else>\n\t\t\t<!-- A failed read is not an empty history: say which part is missing. -->\n\t\t\t<NcNoteCard v-if=\"failedSources.length > 0\" type=\"warning\" data-testid=\"cn-timeline-widget-error\">\n\t\t\t\t{{ failedText }}\n\t\t\t</NcNoteCard>\n\n\t\t\t<p v-if=\"events.length === 0\" class=\"cn-timeline-widget__empty\" data-testid=\"cn-timeline-widget-empty\">\n\t\t\t\t{{ emptyLabel }}\n\t\t\t</p>\n\n\t\t\t<ol v-else class=\"cn-timeline-widget__list\">\n\t\t\t\t<li\n\t\t\t\t\tv-for=\"event in events\"\n\t\t\t\t\t:key=\"event.id\"\n\t\t\t\t\tclass=\"cn-timeline-widget__event\"\n\t\t\t\t\t:class=\"{ 'cn-timeline-widget__event--upcoming': event.upcoming }\"\n\t\t\t\t\t:data-source=\"event.source\"\n\t\t\t\t\tdata-testid=\"cn-timeline-widget-event\">\n\t\t\t\t\t<span class=\"cn-timeline-widget__dot\" aria-hidden=\"true\" />\n\t\t\t\t\t<div class=\"cn-timeline-widget__body\">\n\t\t\t\t\t\t<time class=\"cn-timeline-widget__when\" :datetime=\"event.at.toISOString()\">\n\t\t\t\t\t\t\t{{ formatMoment(event) }}\n\t\t\t\t\t\t</time>\n\t\t\t\t\t\t<span v-if=\"event.upcoming\" class=\"cn-timeline-widget__badge\">\n\t\t\t\t\t\t\t{{ upcomingLabel }}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<p class=\"cn-timeline-widget__label\">\n\t\t\t\t\t\t\t{{ translate(event.label) }}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t\t<p v-if=\"event.detail\" class=\"cn-timeline-widget__detail\">\n\t\t\t\t\t\t\t{{ event.detail }}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t</div>\n\t\t\t\t</li>\n\t\t\t</ol>\n\t\t</template>\n\t</section>\n</template>\n\n<script>\nimport { getLanguage, translate as t } from '@nextcloud/l10n'\nimport { NcLoadingIcon, NcNoteCard } from '@nextcloud/vue'\nimport CnTimelineManage from './CnTimelineManage.vue'\nimport { auditEvents, fieldEvents, listEvents, relatedEvents, sortEvents, timelineEntryEvents } from '../../utils/timelineEvents.js'\nimport { userLocale } from '../../utils/userLocale.js'\n\n/**\n * CnTimelineWidget — an object's dated events in time order (`timeline`\n * widget type for detail pages).\n *\n * Generalises dossiq's case timeline. It merges up to four sources, all\n * optional, into one list:\n *\n * - `fields`: the object's own date properties, `[{ field, label }]`. A\n * dotted path reaches metadata, such as `@self.created`.\n * - `related`: related objects, `[{ register?, schema, field, dateField?,\n * label, titleField? }]`. Rows of `schema` whose `field` holds this object's\n * id become events at their `dateField` (default `@self.created`).\n * - `auditTrail: true`: the object's audit trail, one event per change.\n * - `timeline: true`: OpenRegister's timeline of notes, calls and messages.\n *\n * Oldest first by default (`order: 'desc'` flips it). A moment after now is\n * marked upcoming, in words as well as style.\n *\n * `manage: true` swaps the read view for the manage view (CnTimelineManage)\n * over OpenRegister's timeline alone: kind chips, a visibility filter, pin,\n * follow-up, a note composer with standard text blocks, CSV export, and\n * `entryActions` that open a registry modal on an entry. The manage controls\n * are drawn only when the timeline read answers `canManage: true`.\n *\n * ```json\n * { \"type\": \"timeline\", \"content\": {\n * \"title\": \"Timeline\",\n * \"fields\": [\n * { \"field\": \"@self.created\", \"label\": \"Booking created\" },\n * { \"field\": \"depositClearedAt\", \"label\": \"Deposit cleared\" },\n * { \"field\": \"confirmationSentAt\", \"label\": \"Confirmation mail sent\" },\n * { \"field\": \"startsAt\", \"label\": \"Starts\" },\n * { \"field\": \"endsAt\", \"label\": \"Ends\" }\n * ] } }\n * ```\n *\n * The object comes from the detail page's context, like `audit-trail`:\n * explicit props win, then the injects, then `content`.\n *\n * @spec openspec/changes/timeline-widget/specs/timeline-widget/spec.md#requirement-a-timeline-widget-shows-an-objects-dated-events-in-order\n */\nexport default {\n\tname: 'CnTimelineWidget',\n\n\tcomponents: {\n\t\tCnTimelineManage,\n\t\tNcLoadingIcon,\n\t\tNcNoteCard,\n\t},\n\n\tinject: {\n\t\t/** Detail-page object context from CnDetailPage (a ref or a raw bag). */\n\t\tcnObjectContext: { default: null },\n\t\t/** Detail object context holder from CnPageRenderer (`{ value: { objectData, ... } }`). */\n\t\tcnDetailObjectContext: { default: null },\n\t\t/** Consumer translation function; labels are authored in English. */\n\t\tcnTranslate: { default: () => (key) => key },\n\t},\n\n\tprops: {\n\t\t/** Register slug; object context spread as props by CnWidgetGrid. */\n\t\tregister: { type: String, default: '' },\n\t\t/**\n\t\t * Schema slug, or the schema object the detail context supplies.\n\t\t *\n\t\t * @type {string|object}\n\t\t */\n\t\tschema: { type: [String, Object], default: '' },\n\t\t/** The object's id. */\n\t\tobjectId: { type: String, default: '' },\n\t\t/** The object itself, when the host already has it. */\n\t\tobject: { type: Object, default: null },\n\t\t/** Card title override. */\n\t\ttitle: { type: String, default: '' },\n\t\t/** Stored widget content: `{ title, fields, related, auditTrail, timeline, order, manage, entryActions, ... }`. */\n\t\tcontent: { type: Object, default: () => ({}) },\n\t\t/** OpenRegister API base. */\n\t\tapiBase: { type: String, default: '/apps/openregister/api' },\n\t},\n\n\tdata() {\n\t\treturn {\n\t\t\tloading: false,\n\t\t\trelatedRows: {},\n\t\t\tauditEntries: [],\n\t\t\ttimelineEntries: [],\n\t\t\tfailedSources: [],\n\t\t\tfetchedObject: null,\n\t\t\tloadSeq: 0,\n\t\t}\n\t},\n\n\tcomputed: {\n\t\tctx() {\n\t\t\tconst raw = this.cnObjectContext\n\t\t\tconst inj = raw && (raw.value !== undefined ? raw.value : raw)\n\t\t\tconst holder = this.cnDetailObjectContext && this.cnDetailObjectContext.value\n\t\t\treturn inj || holder || {}\n\t\t},\n\n\t\tresolvedObjectId() {\n\t\t\treturn this.objectId || this.ctx.objectId || this.content.objectId || ''\n\t\t},\n\n\t\tresolvedRegister() {\n\t\t\treturn this.register || this.ctx.register || this.content.register || ''\n\t\t},\n\n\t\tresolvedSchema() {\n\t\t\tconst s = this.schema || this.ctx.schema || this.content.schema || ''\n\t\t\treturn typeof s === 'string' ? s : (s && (s.slug || s.name || s.id)) || ''\n\t\t},\n\n\t\t/**\n\t\t * The object: explicit prop, then the page context, then a fetch of\n\t\t * our own when only the id is known.\n\t\t *\n\t\t * @return {object|null}\n\t\t */\n\t\tresolvedObject() {\n\t\t\treturn this.object || this.ctx.object || this.ctx.objectData || this.fetchedObject || null\n\t\t},\n\n\t\t/**\n\t\t * Whether the manage view renders instead of the read view.\n\t\t *\n\t\t * @return {boolean}\n\t\t */\n\t\tmanage() {\n\t\t\treturn this.content.manage === true\n\t\t},\n\n\t\tresolvedTitle() {\n\t\t\tconst raw = this.title || this.content.title || ''\n\t\t\treturn raw ? this.translate(raw) : ''\n\t\t},\n\n\t\tfieldsConfig() {\n\t\t\treturn Array.isArray(this.content.fields) ? this.content.fields : []\n\t\t},\n\n\t\trelatedConfig() {\n\t\t\treturn Array.isArray(this.content.related) ? this.content.related.filter((r) => r && r.schema && r.field) : []\n\t\t},\n\n\t\t/**\n\t\t * Every event from every source, in time order.\n\t\t *\n\t\t * @return {Array<object>}\n\t\t */\n\t\tevents() {\n\t\t\tconst now = new Date()\n\t\t\tconst all = [\n\t\t\t\t...fieldEvents(this.resolvedObject || {}, this.fieldsConfig, now),\n\t\t\t\t...listEvents(this.resolvedObject || {}, this.content.lists, now),\n\t\t\t\t...this.relatedConfig.flatMap((cfg, i) => relatedEvents(this.relatedRows[i] || [], cfg, now)),\n\t\t\t\t...auditEvents(this.auditEntries, this.describeAudit, now),\n\t\t\t\t...timelineEntryEvents(this.timelineEntries, t('nextcloud-vue', 'Note'), now),\n\t\t\t]\n\t\t\treturn sortEvents(all, this.content.order === 'desc' ? 'desc' : 'asc')\n\t\t},\n\n\t\t/**\n\t\t * A signature of what to fetch, so a change refetches once.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\tloadKey() {\n\t\t\treturn JSON.stringify({\n\t\t\t\tid: this.resolvedObjectId,\n\t\t\t\tregister: this.resolvedRegister,\n\t\t\t\tschema: this.resolvedSchema,\n\t\t\t\trelated: this.relatedConfig,\n\t\t\t\taudit: this.content.auditTrail === true,\n\t\t\t\ttimeline: this.content.timeline === true,\n\t\t\t\tneedObject: this.fieldsConfig.length > 0 && !(this.object || this.ctx.object || this.ctx.objectData),\n\t\t\t})\n\t\t},\n\n\t\tfailedText() {\n\t\t\treturn t('nextcloud-vue', 'Part of the timeline could not load: {parts}.', {\n\t\t\t\tparts: this.failedSources.map((s) => this.sourceName(s)).join(', '),\n\t\t\t})\n\t\t},\n\n\t\tloadingLabel() {\n\t\t\treturn t('nextcloud-vue', 'Loading…')\n\t\t},\n\n\t\temptyLabel() {\n\t\t\treturn t('nextcloud-vue', 'Nothing has happened yet.')\n\t\t},\n\n\t\tupcomingLabel() {\n\t\t\treturn t('nextcloud-vue', 'Upcoming')\n\t\t},\n\t},\n\n\twatch: {\n\t\tloadKey: {\n\t\t\timmediate: true,\n\t\t\thandler() {\n\t\t\t\tthis.load()\n\t\t\t},\n\t\t},\n\t},\n\n\tmethods: {\n\t\ttranslate(text) {\n\t\t\treturn text ? this.cnTranslate(text) : ''\n\t\t},\n\n\t\tsourceName(source) {\n\t\t\tif (source === 'audit') {\n\t\t\t\treturn t('nextcloud-vue', 'changes')\n\t\t\t}\n\t\t\tif (source === 'timeline') {\n\t\t\t\treturn t('nextcloud-vue', 'notes and messages')\n\t\t\t}\n\t\t\tif (source === 'object') {\n\t\t\t\treturn t('nextcloud-vue', 'dates')\n\t\t\t}\n\t\t\treturn t('nextcloud-vue', 'related items')\n\t\t},\n\n\t\t/**\n\t\t * The label of an audit event, from its action and who did it.\n\t\t *\n\t\t * @param {string} action The audit action (create, update, delete).\n\t\t * @param {string} actor Who did it.\n\t\t * @return {string}\n\t\t */\n\t\tdescribeAudit(action, actor) {\n\t\t\tconst known = {\n\t\t\t\tcreate: t('nextcloud-vue', 'Created'),\n\t\t\t\tupdate: t('nextcloud-vue', 'Updated'),\n\t\t\t\tdelete: t('nextcloud-vue', 'Deleted'),\n\t\t\t}\n\t\t\tconst what = known[action] || action || t('nextcloud-vue', 'Changed')\n\t\t\treturn actor ? t('nextcloud-vue', '{action} by {actor}', { action: what, actor }) : what\n\t\t},\n\n\t\t/**\n\t\t * Show a moment in the reader's language: a date for a calendar day,\n\t\t * date and time otherwise.\n\t\t *\n\t\t * @param {object} event The event.\n\t\t * @return {string}\n\t\t */\n\t\tformatMoment(event) {\n\t\t\tconst locale = (typeof getLanguage === 'function' && getLanguage()) || undefined\n\t\t\tconst options = event.dateOnly\n\t\t\t\t? { dateStyle: 'medium' }\n\t\t\t\t: { dateStyle: 'medium', timeStyle: 'short' }\n\t\t\ttry {\n\t\t\t\treturn new Intl.DateTimeFormat(locale, options).format(event.at)\n\t\t\t} catch {\n\t\t\t\treturn event.at.toLocaleString(userLocale())\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Fetch every configured source. Each one fails on its own, so one\n\t\t * unreachable source never hides the others.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t * @spec openspec/changes/timeline-widget/specs/timeline-widget/spec.md#requirement-a-timeline-widget-shows-an-objects-dated-events-in-order\n\t\t */\n\t\tasync load() {\n\t\t\tconst id = this.resolvedObjectId\n\t\t\tconst register = this.resolvedRegister\n\t\t\tconst schema = this.resolvedSchema\n\t\t\tconst seq = ++this.loadSeq\n\t\t\tif (!id || !register || !schema || this.manage) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst [{ default: axios }, { generateUrl }] = await Promise.all([\n\t\t\t\timport('@nextcloud/axios'),\n\t\t\t\timport('@nextcloud/router'),\n\t\t\t])\n\t\t\tconst base = `${this.apiBase}/objects/${register}/${schema}/${id}`\n\t\t\tconst failed = []\n\t\t\tconst jobs = []\n\n\t\t\tif (this.fieldsConfig.length > 0 && !(this.object || this.ctx.object || this.ctx.objectData)) {\n\t\t\t\tjobs.push(axios.get(generateUrl(base))\n\t\t\t\t\t.then((r) => {\n\t\t\t\t\t\tthis.fetchedObject = (r && r.data) || null\n\t\t\t\t\t})\n\t\t\t\t\t.catch(() => failed.push('object')))\n\t\t\t}\n\n\t\t\tconst rows = {}\n\t\t\tthis.relatedConfig.forEach((cfg, i) => {\n\t\t\t\tconst url = generateUrl(`${this.apiBase}/objects/${cfg.register || register}/${cfg.schema}`)\n\t\t\t\tjobs.push(axios.get(url, { params: { [cfg.field]: id, _limit: cfg.limit || 50 } })\n\t\t\t\t\t.then((r) => {\n\t\t\t\t\t\tconst data = r && r.data\n\t\t\t\t\t\trows[i] = (data && (data.results || data)) || []\n\t\t\t\t\t})\n\t\t\t\t\t.catch(() => {\n\t\t\t\t\t\trows[i] = []\n\t\t\t\t\t\tif (!failed.includes('related')) {\n\t\t\t\t\t\t\tfailed.push('related')\n\t\t\t\t\t\t}\n\t\t\t\t\t}))\n\t\t\t})\n\n\t\t\tif (this.content.auditTrail === true) {\n\t\t\t\tjobs.push(axios.get(generateUrl(`${base}/audit-trails`), { params: { limit: this.content.auditLimit || 50 } })\n\t\t\t\t\t.then((r) => {\n\t\t\t\t\t\tconst data = r && r.data\n\t\t\t\t\t\tthis.auditEntries = (data && (data.results || data)) || []\n\t\t\t\t\t})\n\t\t\t\t\t.catch(() => {\n\t\t\t\t\t\tthis.auditEntries = []\n\t\t\t\t\t\tfailed.push('audit')\n\t\t\t\t\t}))\n\t\t\t}\n\n\t\t\tif (this.content.timeline === true) {\n\t\t\t\tjobs.push(axios.get(generateUrl(`${base}/timeline`))\n\t\t\t\t\t.then((r) => {\n\t\t\t\t\t\tconst data = r && r.data\n\t\t\t\t\t\tthis.timelineEntries = (data && (data.results || data)) || []\n\t\t\t\t\t})\n\t\t\t\t\t.catch(() => {\n\t\t\t\t\t\tthis.timelineEntries = []\n\t\t\t\t\t\tfailed.push('timeline')\n\t\t\t\t\t}))\n\t\t\t}\n\n\t\t\tif (jobs.length === 0) {\n\t\t\t\tthis.failedSources = []\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.loading = true\n\t\t\tawait Promise.all(jobs)\n\t\t\tif (seq !== this.loadSeq) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.relatedRows = rows\n\t\t\tthis.failedSources = failed\n\t\t\tthis.loading = false\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-timeline-widget {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 8px;\n}\n\n.cn-timeline-widget__title {\n\tmargin: 0;\n\tfont-size: var(--font-size-large, 1.1em);\n}\n\n.cn-timeline-widget__loading {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 8px;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-timeline-widget__empty {\n\tmargin: 0;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-timeline-widget__list {\n\tmargin: 0;\n\tpadding: 0;\n\tlist-style: none;\n}\n\n.cn-timeline-widget__event {\n\tposition: relative;\n\tdisplay: flex;\n\tgap: 12px;\n\tpadding-block-end: 12px;\n}\n\n/* The line between dots: drawn from each dot down to the next event. */\n.cn-timeline-widget__event:not(:last-child)::before {\n\tcontent: '';\n\tposition: absolute;\n\tinset-block: 14px 0;\n\tinset-inline-start: 5px;\n\tborder-inline-start: 2px solid var(--color-border-dark);\n}\n\n.cn-timeline-widget__dot {\n\tflex: 0 0 auto;\n\twidth: 12px;\n\theight: 12px;\n\tmargin-block-start: 4px;\n\tborder-radius: 50%;\n\tbackground-color: var(--color-primary-element);\n}\n\n/* Upcoming: a hollow dot, plus the word \"Upcoming\" beside the date. */\n.cn-timeline-widget__event--upcoming .cn-timeline-widget__dot {\n\tbox-sizing: border-box;\n\tborder: 2px solid var(--color-primary-element);\n\tbackground-color: var(--color-main-background);\n}\n\n.cn-timeline-widget__body {\n\tmin-width: 0;\n}\n\n.cn-timeline-widget__when {\n\tfont-size: var(--font-size-small, 13px);\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-timeline-widget__badge {\n\tmargin-inline-start: 8px;\n\tfont-size: var(--font-size-small, 13px);\n\tfont-weight: bold;\n\tcolor: var(--color-main-text);\n}\n\n.cn-timeline-widget__label {\n\tmargin: 0;\n\tfont-weight: bold;\n}\n\n.cn-timeline-widget__detail {\n\tmargin: 0;\n\toverflow-wrap: anywhere;\n}\n</style>\n"],"names":["CnTimelineManage","t"],"mappings":"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"}
|