@conduction/nextcloud-vue 2.98.0 → 2.100.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.
Files changed (141) hide show
  1. package/dist/esm/components/CnActionsMenu/CnActionsMenu.vue2.js +12 -0
  2. package/dist/esm/components/CnActionsMenu/CnActionsMenu.vue2.js.map +1 -1
  3. package/dist/esm/components/CnActionsMenu/CnActionsMenu.vue3.js +11 -2
  4. package/dist/esm/components/CnActionsMenu/CnActionsMenu.vue3.js.map +1 -1
  5. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue.js +1 -1
  6. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue2.js +6 -1
  7. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue2.js.map +1 -1
  8. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue3.js +2 -1
  9. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue3.js.map +1 -1
  10. package/dist/esm/components/CnBreadcrumbs/CnBreadcrumbs.vue.js +1 -1
  11. package/dist/esm/components/CnBreadcrumbs/CnBreadcrumbs.vue2.js.map +1 -1
  12. package/dist/esm/components/CnBreadcrumbs/CnBreadcrumbs.vue3.js +1 -1
  13. package/dist/esm/components/CnBreadcrumbs/CnBreadcrumbs.vue3.js.map +1 -1
  14. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +25 -8
  15. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
  16. package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js +7 -4
  17. package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
  18. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue.js +1 -1
  19. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js +11 -8
  20. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js.map +1 -1
  21. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js +13 -4
  22. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js.map +1 -1
  23. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue.js +1 -1
  24. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js +54 -3
  25. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js.map +1 -1
  26. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue3.js +16 -2
  27. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue3.js.map +1 -1
  28. package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue.js +1 -1
  29. package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue2.js +42 -7
  30. package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue2.js.map +1 -1
  31. package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue3.js +121 -57
  32. package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue3.js.map +1 -1
  33. package/dist/esm/components/CnFlowsPage/CnFlowEditorPage.vue2.js +10 -0
  34. package/dist/esm/components/CnFlowsPage/CnFlowEditorPage.vue2.js.map +1 -1
  35. package/dist/esm/components/CnFlowsPage/CnFlowEditorPage.vue3.js +2 -1
  36. package/dist/esm/components/CnFlowsPage/CnFlowEditorPage.vue3.js.map +1 -1
  37. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +136 -7
  38. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
  39. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
  40. package/dist/esm/components/CnOrderedListField/CnOrderedListField.vue.js +1 -1
  41. package/dist/esm/components/CnOrderedListField/CnOrderedListField.vue2.js +26 -7
  42. package/dist/esm/components/CnOrderedListField/CnOrderedListField.vue2.js.map +1 -1
  43. package/dist/esm/components/CnOrderedListField/CnOrderedListField.vue3.js +78 -17
  44. package/dist/esm/components/CnOrderedListField/CnOrderedListField.vue3.js.map +1 -1
  45. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue.js +1 -1
  46. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js +68 -7
  47. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js.map +1 -1
  48. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js +256 -240
  49. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js.map +1 -1
  50. package/dist/esm/components/CnSettingsField/CnSettingsField.vue.js +9 -0
  51. package/dist/esm/components/CnSettingsField/CnSettingsField.vue.js.map +1 -0
  52. package/dist/esm/components/CnSettingsField/CnSettingsField.vue2.js +265 -0
  53. package/dist/esm/components/CnSettingsField/CnSettingsField.vue2.js.map +1 -0
  54. package/dist/esm/components/CnSettingsField/CnSettingsField.vue3.js +191 -0
  55. package/dist/esm/components/CnSettingsField/CnSettingsField.vue3.js.map +1 -0
  56. package/dist/esm/components/CnSettingsFieldsSection/CnSettingsFieldsSection.vue.js +9 -0
  57. package/dist/esm/components/CnSettingsFieldsSection/CnSettingsFieldsSection.vue.js.map +1 -0
  58. package/dist/esm/components/CnSettingsFieldsSection/CnSettingsFieldsSection.vue2.js +537 -0
  59. package/dist/esm/components/CnSettingsFieldsSection/CnSettingsFieldsSection.vue2.js.map +1 -0
  60. package/dist/esm/components/CnSettingsFieldsSection/CnSettingsFieldsSection.vue3.js +99 -0
  61. package/dist/esm/components/CnSettingsFieldsSection/CnSettingsFieldsSection.vue3.js.map +1 -0
  62. package/dist/esm/components/CnSettingsPage/CnSettingsPage.vue.js +1 -1
  63. package/dist/esm/components/CnSettingsPage/CnSettingsPage.vue2.js +18 -70
  64. package/dist/esm/components/CnSettingsPage/CnSettingsPage.vue2.js.map +1 -1
  65. package/dist/esm/components/CnSettingsPage/CnSettingsPage.vue3.js +6 -44
  66. package/dist/esm/components/CnSettingsPage/CnSettingsPage.vue3.js.map +1 -1
  67. package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue.js +1 -1
  68. package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue2.js +16 -2
  69. package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue2.js.map +1 -1
  70. package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue3.js +40 -25
  71. package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue3.js.map +1 -1
  72. package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js +1 -0
  73. package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js.map +1 -1
  74. package/dist/esm/components/CnWizardDialog/CnWizardDialog.vue.js +1 -1
  75. package/dist/esm/components/CnWizardDialog/CnWizardDialog.vue2.js +7 -7
  76. package/dist/esm/components/CnWizardDialog/CnWizardDialog.vue2.js.map +1 -1
  77. package/dist/esm/components/CnWizardDialog/CnWizardDialog.vue3.js.map +1 -1
  78. package/dist/esm/components/CnWorkingCalendarWidget/CnWorkingCalendarWidget.vue.js +9 -0
  79. package/dist/esm/components/CnWorkingCalendarWidget/CnWorkingCalendarWidget.vue.js.map +1 -0
  80. package/dist/esm/components/CnWorkingCalendarWidget/CnWorkingCalendarWidget.vue2.js +472 -0
  81. package/dist/esm/components/CnWorkingCalendarWidget/CnWorkingCalendarWidget.vue2.js.map +1 -0
  82. package/dist/esm/components/CnWorkingCalendarWidget/CnWorkingCalendarWidget.vue3.js +231 -0
  83. package/dist/esm/components/CnWorkingCalendarWidget/CnWorkingCalendarWidget.vue3.js.map +1 -0
  84. package/dist/esm/components/CnWorkingCalendarWidget/index.js +27 -0
  85. package/dist/esm/components/CnWorkingCalendarWidget/index.js.map +1 -0
  86. package/dist/esm/composables/useFlowStore.js +2 -1
  87. package/dist/esm/composables/useFlowStore.js.map +1 -1
  88. package/dist/esm/index.js +3 -0
  89. package/dist/esm/index.js.map +1 -1
  90. package/dist/esm/l10n/en.json.js +101 -1
  91. package/dist/esm/l10n/en.json.js.map +1 -1
  92. package/dist/esm/l10n/nl.json.js +115 -1
  93. package/dist/esm/l10n/nl.json.js.map +1 -1
  94. package/dist/esm/library-style.js +1 -1
  95. package/dist/esm/nextcloud-vue.css +999 -233
  96. package/dist/esm/utils/libraryWidgetKeys.js +1 -0
  97. package/dist/esm/utils/libraryWidgetKeys.js.map +1 -1
  98. package/dist/esm/utils/validateManifestV2.compiled.js +3 -3
  99. package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
  100. package/dist/esm/utils/workingCalendarMonth.js +85 -0
  101. package/dist/esm/utils/workingCalendarMonth.js.map +1 -0
  102. package/dist/nextcloud-vue.cjs.js +10314 -7778
  103. package/dist/nextcloud-vue.cjs.js.map +2 -2
  104. package/dist/nextcloud-vue.css +999 -233
  105. package/l10n/en.json +101 -1
  106. package/l10n/nl.json +115 -1
  107. package/package.json +1 -1
  108. package/src/components/CnActionsMenu/CnActionsMenu.vue +14 -1
  109. package/src/components/CnAdminSettingsShell/CnAdminSettingsShell.vue +7 -1
  110. package/src/components/CnBreadcrumbs/CnBreadcrumbs.vue +1 -0
  111. package/src/components/CnDetailPage/CnDetailPage.vue +29 -9
  112. package/src/components/CnDetailWidgetHost/CnDetailWidgetHost.vue +13 -4
  113. package/src/components/CnFactsWidget/CnFactsWidget.vue +65 -3
  114. package/src/components/CnFlowsPage/CnFlowBoard.vue +77 -2
  115. package/src/components/CnFlowsPage/CnFlowEditorPage.vue +11 -0
  116. package/src/components/CnIndexPage/CnIndexPage.vue +136 -7
  117. package/src/components/CnOrderedListField/CnOrderedListField.vue +81 -9
  118. package/src/components/CnRecordListWidget/CnRecordListWidget.vue +114 -7
  119. package/src/components/CnSettingsField/CnSettingsField.vue +449 -0
  120. package/src/components/CnSettingsField/index.js +4 -0
  121. package/src/components/CnSettingsFieldsSection/CnSettingsFieldsSection.vue +642 -0
  122. package/src/components/CnSettingsFieldsSection/index.js +4 -0
  123. package/src/components/CnSettingsPage/CnSettingsPage.vue +6 -86
  124. package/src/components/CnSetupWizard/CnSetupWizard.vue +37 -3
  125. package/src/components/CnWidgetGrid/registerDashboardWidgets.js +1 -0
  126. package/src/components/CnWizardDialog/CnWizardDialog.vue +7 -7
  127. package/src/components/CnWorkingCalendarWidget/CnWorkingCalendarWidget.vue +725 -0
  128. package/src/components/CnWorkingCalendarWidget/index.js +26 -0
  129. package/src/components/index.js +3 -0
  130. package/src/composables/useFlowStore.js +2 -1
  131. package/src/css/badge.css +32 -16
  132. package/src/css/detail-page.css +15 -0
  133. package/src/css/dialog.css +48 -0
  134. package/src/css/look-board-detail.css +80 -8
  135. package/src/css/look-board-index.css +52 -8
  136. package/src/css/look-board.css +301 -1
  137. package/src/index.js +3 -0
  138. package/src/schemas/app-manifest-v2.schema.json +25 -1
  139. package/src/utils/libraryWidgetKeys.js +1 -0
  140. package/src/utils/validateManifestV2.compiled.js +3 -3
  141. package/src/utils/workingCalendarMonth.js +82 -0
@@ -0,0 +1,472 @@
1
+ import { getCurrentUser } from '@nextcloud/auth';
2
+ import axios__default from '@nextcloud/axios';
3
+ import { translate } from '@nextcloud/l10n';
4
+ import { generateUrl } from '@nextcloud/router';
5
+ import { NcButton, NcLoadingIcon } from '@nextcloud/vue';
6
+ import ChevronLeft from 'vue-material-design-icons/ChevronLeft.vue';
7
+ import ChevronRight from 'vue-material-design-icons/ChevronRight.vue';
8
+ import { fetchReferenceObjects } from '../../utils/boardReferenceColumns.js';
9
+ import { resolveFilterTokens, hasUnresolvedTokens } from '../../utils/resolveFilterTokens.js';
10
+ import { userLocale } from '../../utils/userLocale.js';
11
+ import { normaliseExceptions, buildMonth, isoDate } from '../../utils/workingCalendarMonth.js';
12
+
13
+ const OBJECT_API = '/apps/openregister/api/objects';
14
+ const PREVIEW_URL = '/apps/openregister/api/flow-timers/calendars/preview';
15
+
16
+ let instanceCounter = 0;
17
+
18
+ /**
19
+ * The id of an object, wherever OpenRegister carries it.
20
+ *
21
+ * @param {object|null} object The object.
22
+ * @return {string} The id, or ''.
23
+ */
24
+ function idOf(object) {
25
+ return String(object?.id ?? object?.['@self']?.id ?? object?.uuid ?? '')
26
+ }
27
+
28
+ /**
29
+ * Today as `YYYY-MM-DD`, in local time.
30
+ *
31
+ * @return {string} The date.
32
+ */
33
+ function todayIso() {
34
+ const now = new Date();
35
+ return isoDate(now.getFullYear(), now.getMonth(), now.getDate())
36
+ }
37
+
38
+ /**
39
+ * CnWorkingCalendarWidget — the `working-calendar` widget: one month of a
40
+ * working calendar kept as an OpenRegister object (board
41
+ * DqInstellingenAlgemeen, "Werkdagen en feestdagen").
42
+ *
43
+ * The grid runs Monday to Sunday. Weekdays the calendar does not work are
44
+ * grey; the dates it is closed on are red, with their name on hover and in
45
+ * the day's label. The closures are not computed here: the widget asks
46
+ * OpenRegister's calendar preview (`/api/flow-timers/calendars/preview`) for
47
+ * the year shown, which expands the calendar's rules and its exceptions.
48
+ *
49
+ * "Add day" appends `{ date, name }` to the object's `exceptions` with one
50
+ * update through the object API, under the reader's own rights; it shows for
51
+ * administrators, and the server decides. The preview is administrators-only
52
+ * too; for anyone else the widget shows the stored exceptions and says the
53
+ * holidays could not be read.
54
+ *
55
+ * ```json
56
+ * {
57
+ * "type": "working-calendar",
58
+ * "content": {
59
+ * "calendar": { "register": "flow-timers", "schema": "working-calendar", "filter": { "slug": "default" } }
60
+ * }
61
+ * }
62
+ * ```
63
+ *
64
+ * Keyboard: the days form a grid with one tab stop; the arrow keys move a
65
+ * day or a week, Home and End to the start and end of the week, Page Up and
66
+ * Page Down a month. Enter on a day opens Add day for that date.
67
+ */
68
+ var script = {
69
+ name: 'CnWorkingCalendarWidget',
70
+
71
+ components: { ChevronLeft, ChevronRight, NcButton, NcLoadingIcon },
72
+
73
+ inject: {
74
+ /** The page's workspace values, for `@workspace.<key>` tokens in the filter. */
75
+ cnWorkspaceContext: { default: null },
76
+ /** The host's translate, for the manifest's texts. */
77
+ cnTranslate: { default: () => (key) => key },
78
+ },
79
+
80
+ props: {
81
+ /**
82
+ * The widget config: `{ calendar: { register, schema, id? | filter? },
83
+ * previewUrl?, editable?, emptyText? }`.
84
+ *
85
+ * @type {object}
86
+ */
87
+ content: {
88
+ type: Object,
89
+ default: () => ({}),
90
+ },
91
+
92
+ /** The bound record's id, for `@objectId` in the filter. */
93
+ objectId: {
94
+ type: [String, Number],
95
+ default: '',
96
+ },
97
+
98
+ /** The bound record, for `@object.<field>` in the filter. */
99
+ objectData: {
100
+ type: Object,
101
+ default: null,
102
+ },
103
+ },
104
+
105
+ data() {
106
+ instanceCounter += 1;
107
+ const now = new Date();
108
+ return {
109
+ uid: `cn-working-calendar-${instanceCounter}`,
110
+ loading: false,
111
+ error: '',
112
+ calendar: null,
113
+ previews: {},
114
+ previewFailed: false,
115
+ year: now.getFullYear(),
116
+ month: now.getMonth(),
117
+ focusDate: todayIso(),
118
+ adding: false,
119
+ newDate: '',
120
+ newName: '',
121
+ saving: false,
122
+ saveError: '',
123
+ liveText: '',
124
+ }
125
+ },
126
+
127
+ computed: {
128
+ /** @return {{register: string, schema: string, id: string, filter: (object|null)}|null} The calendar source, tokens resolved, or null while unresolved. */
129
+ source() {
130
+ const c = this.content?.calendar;
131
+ if (!c || !c.register || !c.schema) {
132
+ return null
133
+ }
134
+ const unwrap = (v) => (v && typeof v === 'object' && 'value' in v ? v.value : v);
135
+ const ctx = { objectId: this.objectId || null, object: this.objectData, workspace: unwrap(this.cnWorkspaceContext) || {} };
136
+ const filter = c.filter && typeof c.filter === 'object' ? resolveFilterTokens(c.filter, ctx) : null;
137
+ if (filter && hasUnresolvedTokens(filter)) {
138
+ return null
139
+ }
140
+ return { register: String(c.register), schema: String(c.schema), id: c.id ? String(c.id) : '', filter }
141
+ },
142
+
143
+ /** @return {string} A key of the source, to read it again when it changes. */
144
+ sourceKey() {
145
+ return this.source ? JSON.stringify(this.source) : ''
146
+ },
147
+
148
+ /** @return {boolean} Whether Add day shows: administrators, unless the manifest turns it off. */
149
+ editable() {
150
+ return this.content?.editable !== false && Boolean(getCurrentUser()?.isAdmin)
151
+ },
152
+
153
+ /** @return {number[]} The ISO weekdays that work. */
154
+ workingWeekdays() {
155
+ const days = this.calendar?.workingWeekdays;
156
+ return Array.isArray(days) ? days.map((d) => Number(d)) : [1, 2, 3, 4, 5]
157
+ },
158
+
159
+ /** @return {Array<{date: string, name: string}>} The stored exceptions. */
160
+ exceptions() {
161
+ return normaliseExceptions(this.calendar?.exceptions)
162
+ },
163
+
164
+ /**
165
+ * The closed dates of the year shown: the preview's, each marked as an
166
+ * exception when the calendar lists it, else as a holiday; without a
167
+ * preview, the stored exceptions.
168
+ *
169
+ * @return {Map<string, {name: string, kind: string}>}
170
+ * @spec openspec/changes/working-calendar-widget/specs/working-calendar-widget/spec.md#requirement-a-working-calendar-shows-a-month
171
+ */
172
+ closures() {
173
+ const own = new Set(this.exceptions.map((e) => e.date));
174
+ const map = new Map();
175
+ const preview = this.previews[this.year];
176
+ for (const entry of Array.isArray(preview) ? preview : []) {
177
+ if (entry && typeof entry.date === 'string') {
178
+ map.set(entry.date, { name: String(entry.name || ''), kind: own.has(entry.date) ? 'exception' : 'holiday' });
179
+ }
180
+ }
181
+ for (const e of this.exceptions) {
182
+ if (!map.has(e.date)) {
183
+ map.set(e.date, { name: e.name, kind: 'exception' });
184
+ }
185
+ }
186
+ return map
187
+ },
188
+
189
+ /** @return {Array<Array<object|null>>} The weeks of the month shown. */
190
+ weeks() {
191
+ return buildMonth(this.year, this.month, { workingWeekdays: this.workingWeekdays, closures: this.closures, today: todayIso() })
192
+ },
193
+
194
+ /** @return {Array<{short: string, long: string}>} Monday to Sunday in the user's language. */
195
+ weekdayNames() {
196
+ const short = new Intl.DateTimeFormat(userLocale(), { weekday: 'short' });
197
+ const long = new Intl.DateTimeFormat(userLocale(), { weekday: 'long' });
198
+ return Array.from({ length: 7 }, (_v, i) => {
199
+ const day = new Date(Date.UTC(2024, 0, 1 + i, 12));
200
+ return { short: short.format(day).replace(/\.$/, ''), long: long.format(day) }
201
+ })
202
+ },
203
+
204
+ /** @return {string} "December 2026" in the user's language. */
205
+ monthTitle() {
206
+ const text = new Intl.DateTimeFormat(userLocale(), { month: 'long', year: 'numeric' }).format(new Date(this.year, this.month, 15));
207
+ return text.charAt(0).toUpperCase() + text.slice(1)
208
+ },
209
+
210
+ /** @return {string} Why holidays are missing, or ''. */
211
+ previewNote() {
212
+ return this.previewFailed ? translate('nextcloud-vue', 'Holidays could not be read. Only the days added by hand are shown.') : ''
213
+ },
214
+
215
+ loadingLabel: () => translate('nextcloud-vue', 'Loading …'),
216
+ previousMonthLabel: () => translate('nextcloud-vue', 'Previous month'),
217
+ nextMonthLabel: () => translate('nextcloud-vue', 'Next month'),
218
+ addLabel: () => translate('nextcloud-vue', 'Add day'),
219
+ dateLabel: () => translate('nextcloud-vue', 'Date'),
220
+ nameLabel: () => translate('nextcloud-vue', 'Name'),
221
+ cancelLabel: () => translate('nextcloud-vue', 'Cancel'),
222
+ saveLabel: () => translate('nextcloud-vue', 'Save'),
223
+
224
+ /** @return {string} The empty-state text. */
225
+ emptyLabel() {
226
+ return this.content?.emptyText ? this.translate(this.content.emptyText) : translate('nextcloud-vue', 'No working calendar found.')
227
+ },
228
+ },
229
+
230
+ watch: {
231
+ sourceKey: {
232
+ handler() {
233
+ this.load();
234
+ },
235
+
236
+ immediate: true,
237
+ },
238
+
239
+ year() {
240
+ this.loadPreview();
241
+ },
242
+ },
243
+
244
+ methods: {
245
+ /**
246
+ * The host's translate, or the text unchanged.
247
+ *
248
+ * @param {string} text The text.
249
+ * @return {string} The translation.
250
+ */
251
+ translate(text) {
252
+ return typeof this.cnTranslate === 'function' ? this.cnTranslate(text) : text
253
+ },
254
+
255
+ /** @return {string} The calendar object's API URL. */
256
+ objectUrl() {
257
+ const s = this.source;
258
+ const id = idOf(this.calendar) || s.id;
259
+ return generateUrl(`${OBJECT_API}/${encodeURIComponent(s.register)}/${encodeURIComponent(s.schema)}/${encodeURIComponent(id)}`)
260
+ },
261
+
262
+ /**
263
+ * Read the calendar object, then the closures of the year shown.
264
+ *
265
+ * @return {Promise<void>}
266
+ */
267
+ async load() {
268
+ const key = this.sourceKey;
269
+ if (key === '') {
270
+ return
271
+ }
272
+ this.loading = true;
273
+ this.error = '';
274
+ try {
275
+ const s = this.source;
276
+ let calendar = null;
277
+ if (s.id) {
278
+ const response = await axios__default.get(generateUrl(`${OBJECT_API}/${encodeURIComponent(s.register)}/${encodeURIComponent(s.schema)}/${encodeURIComponent(s.id)}`));
279
+ calendar = response?.data || null;
280
+ } else {
281
+ const found = await fetchReferenceObjects({ register: s.register, schema: s.schema, filter: s.filter || {}, limit: 1 });
282
+ calendar = found[0] || null;
283
+ }
284
+ if (key !== this.sourceKey) {
285
+ return
286
+ }
287
+ this.calendar = calendar;
288
+ this.previews = {};
289
+ if (calendar) {
290
+ await this.loadPreview();
291
+ }
292
+ } catch {
293
+ this.error = translate('nextcloud-vue', 'The working calendar could not be loaded.');
294
+ } finally {
295
+ this.loading = false;
296
+ }
297
+ },
298
+
299
+ /**
300
+ * Ask the calendar preview for the closed dates of the year shown,
301
+ * once per year.
302
+ *
303
+ * @return {Promise<void>}
304
+ * @spec openspec/changes/working-calendar-widget/specs/working-calendar-widget/spec.md#requirement-a-working-calendar-shows-a-month
305
+ */
306
+ async loadPreview() {
307
+ const year = this.year;
308
+ if (!this.calendar || this.previews[year]) {
309
+ return
310
+ }
311
+ try {
312
+ const url = generateUrl(this.content?.previewUrl || PREVIEW_URL);
313
+ const response = await axios__default.post(url, { calendar: this.calendar, year });
314
+ const dates = Array.isArray(response?.data?.dates) ? response.data.dates : [];
315
+ this.previews = { ...this.previews, [year]: dates };
316
+ this.previewFailed = false;
317
+ } catch {
318
+ this.previewFailed = true;
319
+ }
320
+ },
321
+
322
+ /**
323
+ * Show another month, keeping focus on the same day where it exists.
324
+ *
325
+ * @param {number} delta Months to move.
326
+ * @return {void}
327
+ */
328
+ shiftMonth(delta) {
329
+ const date = new Date(this.year, this.month + delta, 1);
330
+ this.year = date.getFullYear();
331
+ this.month = date.getMonth();
332
+ const day = Math.min(Number(this.focusDate.slice(8, 10)) || 1, new Date(this.year, this.month + 1, 0).getDate());
333
+ this.focusDate = isoDate(this.year, this.month, day);
334
+ this.liveText = this.monthTitle;
335
+ },
336
+
337
+ /**
338
+ * A day's accessible label: the full date, whether it works, and the
339
+ * closure's name.
340
+ *
341
+ * @param {object} slot The day.
342
+ * @return {string} The label.
343
+ */
344
+ dayLabel(slot) {
345
+ const [y, m, d] = slot.date.split('-').map(Number);
346
+ const date = new Intl.DateTimeFormat(userLocale(), { weekday: 'long', day: 'numeric', month: 'long', year: 'numeric' }).format(new Date(y, m - 1, d));
347
+ if (slot.closure) {
348
+ const name = this.closureName(slot.closure);
349
+ return name
350
+ ? translate('nextcloud-vue', '{date}, closed: {name}', { date, name })
351
+ : translate('nextcloud-vue', '{date}, closed', { date })
352
+ }
353
+ return slot.working ? translate('nextcloud-vue', '{date}, working day', { date }) : translate('nextcloud-vue', '{date}, not a working day', { date })
354
+ },
355
+
356
+ /**
357
+ * A closure's name, with a fallback for an unnamed added day.
358
+ *
359
+ * @param {{name: string, kind: string}} closure The closure.
360
+ * @return {string} The name.
361
+ */
362
+ closureName(closure) {
363
+ if (closure.name) {
364
+ return this.translate(closure.name)
365
+ }
366
+ return closure.kind === 'exception' ? translate('nextcloud-vue', 'Day added by hand') : ''
367
+ },
368
+
369
+ /**
370
+ * Open Add day, with a date filled in.
371
+ *
372
+ * @param {string} [date] The date.
373
+ * @return {void}
374
+ */
375
+ openAdd(date) {
376
+ this.newDate = date || this.focusDate || '';
377
+ this.newName = '';
378
+ this.saveError = '';
379
+ this.adding = true;
380
+ this.$nextTick(() => this.$refs.dateInput?.focus?.());
381
+ },
382
+
383
+ /**
384
+ * A click on a day: open Add day for it when the reader may edit.
385
+ *
386
+ * @param {object} slot The day.
387
+ * @return {void}
388
+ */
389
+ onDayClick(slot) {
390
+ this.focusDate = slot.date;
391
+ if (this.editable) {
392
+ this.openAdd(slot.date);
393
+ }
394
+ },
395
+
396
+ /**
397
+ * Append the new day to the calendar's exceptions with one update,
398
+ * under the reader's rights, then read the closures again.
399
+ *
400
+ * @return {Promise<void>}
401
+ * @spec openspec/changes/working-calendar-widget/specs/working-calendar-widget/spec.md#requirement-a-day-can-be-added-to-the-calendar
402
+ */
403
+ async saveDay() {
404
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(this.newDate) || !this.calendar) {
405
+ return
406
+ }
407
+ this.saving = true;
408
+ this.saveError = '';
409
+ try {
410
+ const stored = Array.isArray(this.calendar.exceptions) ? this.calendar.exceptions : [];
411
+ const name = this.newName.trim();
412
+ const exceptions = [...stored.filter((e) => (typeof e === 'string' ? e : e?.date) !== this.newDate), name ? { date: this.newDate, name } : { date: this.newDate }];
413
+ const response = await axios__default.patch(this.objectUrl(), { exceptions });
414
+ this.calendar = { ...this.calendar, ...(response?.data && typeof response.data === 'object' ? response.data : {}), exceptions };
415
+ const year = Number(this.newDate.slice(0, 4));
416
+ const { [year]: _stale, ...rest } = this.previews;
417
+ this.previews = rest;
418
+ const [y, m] = this.newDate.split('-').map(Number);
419
+ this.year = y;
420
+ this.month = m - 1;
421
+ this.focusDate = this.newDate;
422
+ await this.loadPreview();
423
+ this.adding = false;
424
+ this.liveText = translate('nextcloud-vue', 'Day added.');
425
+ } catch (e) {
426
+ this.saveError = e?.response?.status === 403
427
+ ? translate('nextcloud-vue', 'Only an administrator can change the working calendar.')
428
+ : translate('nextcloud-vue', 'The day could not be added. Try again.');
429
+ } finally {
430
+ this.saving = false;
431
+ }
432
+ },
433
+
434
+ /**
435
+ * Arrow keys, Home / End and Page Up / Down move focus across the days.
436
+ *
437
+ * @param {KeyboardEvent} event The key event.
438
+ * @return {void}
439
+ */
440
+ onKeydown(event) {
441
+ const moves = { ArrowLeft: -1, ArrowRight: 1, ArrowUp: -7, ArrowDown: 7 };
442
+ const [y, m, d] = (this.focusDate || todayIso()).split('-').map(Number);
443
+ let target;
444
+ if (event.key in moves) {
445
+ target = new Date(y, m - 1, d + moves[event.key]);
446
+ } else if (event.key === 'Home' || event.key === 'End') {
447
+ const weekday = (new Date(y, m - 1, d).getDay() + 6) % 7;
448
+ target = new Date(y, m - 1, d + (event.key === 'Home' ? -weekday : 6 - weekday));
449
+ } else if (event.key === 'PageUp' || event.key === 'PageDown') {
450
+ target = new Date(y, m - 1 + (event.key === 'PageUp' ? -1 : 1), 1);
451
+ target.setDate(Math.min(d, new Date(target.getFullYear(), target.getMonth() + 1, 0).getDate()));
452
+ } else if ((event.key === 'Enter' || event.key === ' ') && this.editable) {
453
+ event.preventDefault();
454
+ this.openAdd(this.focusDate);
455
+ return
456
+ } else {
457
+ return
458
+ }
459
+ event.preventDefault();
460
+ this.focusDate = isoDate(target.getFullYear(), target.getMonth(), target.getDate());
461
+ if (target.getFullYear() !== this.year || target.getMonth() !== this.month) {
462
+ this.year = target.getFullYear();
463
+ this.month = target.getMonth();
464
+ this.liveText = this.monthTitle;
465
+ }
466
+ this.$nextTick(() => this.$el.querySelector?.(`[data-date="${this.focusDate}"]`)?.focus?.());
467
+ },
468
+ },
469
+ };
470
+
471
+ export { script as default };
472
+ //# sourceMappingURL=CnWorkingCalendarWidget.vue2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CnWorkingCalendarWidget.vue2.js","sources":["../../../../src/components/CnWorkingCalendarWidget/CnWorkingCalendarWidget.vue"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n<template>\n\t<div class=\"cn-working-calendar\" data-testid=\"cn-working-calendar\">\n\t\t<p v-if=\"error\"\n\t\t\tclass=\"cn-working-calendar__error\"\n\t\t\trole=\"alert\"\n\t\t\tdata-testid=\"cn-working-calendar-error\">\n\t\t\t{{ error }}\n\t\t</p>\n\t\t<div v-else-if=\"loading && !calendar\" class=\"cn-working-calendar__loading\">\n\t\t\t<NcLoadingIcon :size=\"20\" :name=\"loadingLabel\" />\n\t\t</div>\n\t\t<template v-else-if=\"calendar\">\n\t\t\t<div class=\"cn-working-calendar__head\">\n\t\t\t\t<NcButton\n\t\t\t\t\tvariant=\"tertiary\"\n\t\t\t\t\t:aria-label=\"previousMonthLabel\"\n\t\t\t\t\tdata-testid=\"cn-working-calendar-previous\"\n\t\t\t\t\t@click=\"shiftMonth(-1)\">\n\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t<ChevronLeft :size=\"20\" />\n\t\t\t\t\t</template>\n\t\t\t\t</NcButton>\n\t\t\t\t<strong :id=\"`${uid}-title`\" class=\"cn-working-calendar__title\" data-testid=\"cn-working-calendar-title\">{{ monthTitle }}</strong>\n\t\t\t\t<NcButton\n\t\t\t\t\tvariant=\"tertiary\"\n\t\t\t\t\t:aria-label=\"nextMonthLabel\"\n\t\t\t\t\tdata-testid=\"cn-working-calendar-next\"\n\t\t\t\t\t@click=\"shiftMonth(1)\">\n\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t<ChevronRight :size=\"20\" />\n\t\t\t\t\t</template>\n\t\t\t\t</NcButton>\n\t\t\t\t<NcButton\n\t\t\t\t\tv-if=\"editable\"\n\t\t\t\t\tclass=\"cn-working-calendar__add\"\n\t\t\t\t\tvariant=\"secondary\"\n\t\t\t\t\tdata-testid=\"cn-working-calendar-add\"\n\t\t\t\t\t@click=\"openAdd()\">\n\t\t\t\t\t{{ addLabel }}\n\t\t\t\t</NcButton>\n\t\t\t</div>\n\t\t\t<p v-if=\"previewNote\" class=\"cn-working-calendar__note\" data-testid=\"cn-working-calendar-note\">\n\t\t\t\t{{ previewNote }}\n\t\t\t</p>\n\t\t\t<span class=\"cn-working-calendar__live\" aria-live=\"polite\">{{ liveText }}</span>\n\n\t\t\t<div\n\t\t\t\trole=\"grid\"\n\t\t\t\tclass=\"cn-working-calendar__grid\"\n\t\t\t\t:aria-labelledby=\"`${uid}-title`\"\n\t\t\t\tdata-testid=\"cn-working-calendar-grid\"\n\t\t\t\t@keydown=\"onKeydown\">\n\t\t\t\t<div role=\"row\" class=\"cn-working-calendar__row\">\n\t\t\t\t\t<span\n\t\t\t\t\t\tv-for=\"name in weekdayNames\"\n\t\t\t\t\t\t:key=\"name.long\"\n\t\t\t\t\t\trole=\"columnheader\"\n\t\t\t\t\t\tclass=\"cn-working-calendar__weekday\"\n\t\t\t\t\t\t:aria-label=\"name.long\">{{ name.short }}</span>\n\t\t\t\t</div>\n\t\t\t\t<div\n\t\t\t\t\tv-for=\"(week, w) in weeks\"\n\t\t\t\t\t:key=\"w\"\n\t\t\t\t\trole=\"row\"\n\t\t\t\t\tclass=\"cn-working-calendar__row\">\n\t\t\t\t\t<template v-for=\"(slot, d) in week\">\n\t\t\t\t\t\t<span v-if=\"!slot\"\n\t\t\t\t\t\t\t:key=\"`empty-${w}-${d}`\"\n\t\t\t\t\t\t\trole=\"gridcell\"\n\t\t\t\t\t\t\tclass=\"cn-working-calendar__blank\" />\n\t\t\t\t\t\t<span\n\t\t\t\t\t\t\tv-else\n\t\t\t\t\t\t\t:key=\"slot.date\"\n\t\t\t\t\t\t\trole=\"gridcell\"\n\t\t\t\t\t\t\tclass=\"cn-working-calendar__day\"\n\t\t\t\t\t\t\t:class=\"{\n\t\t\t\t\t\t\t\t'cn-working-calendar__day--off': !slot.working && !slot.closure,\n\t\t\t\t\t\t\t\t'cn-working-calendar__day--closed': slot.closure,\n\t\t\t\t\t\t\t\t'cn-working-calendar__day--today': slot.today,\n\t\t\t\t\t\t\t}\"\n\t\t\t\t\t\t\t:tabindex=\"slot.date === focusDate ? 0 : -1\"\n\t\t\t\t\t\t\t:aria-label=\"dayLabel(slot)\"\n\t\t\t\t\t\t\t:aria-current=\"slot.today ? 'date' : null\"\n\t\t\t\t\t\t\t:title=\"slot.closure ? closureName(slot.closure) : null\"\n\t\t\t\t\t\t\t:data-date=\"slot.date\"\n\t\t\t\t\t\t\tdata-testid=\"cn-working-calendar-day\"\n\t\t\t\t\t\t\t@click=\"onDayClick(slot)\"\n\t\t\t\t\t\t\t@focus=\"focusDate = slot.date\">{{ slot.day }}</span>\n\t\t\t\t\t</template>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<form\n\t\t\t\tv-if=\"adding\"\n\t\t\t\tclass=\"cn-working-calendar__form\"\n\t\t\t\tdata-testid=\"cn-working-calendar-form\"\n\t\t\t\t@submit.prevent=\"saveDay\">\n\t\t\t\t<label class=\"cn-working-calendar__field\">\n\t\t\t\t\t{{ dateLabel }}\n\t\t\t\t\t<input\n\t\t\t\t\t\tref=\"dateInput\"\n\t\t\t\t\t\tv-model=\"newDate\"\n\t\t\t\t\t\ttype=\"date\"\n\t\t\t\t\t\trequired\n\t\t\t\t\t\tdata-testid=\"cn-working-calendar-date\">\n\t\t\t\t</label>\n\t\t\t\t<label class=\"cn-working-calendar__field\">\n\t\t\t\t\t{{ nameLabel }}\n\t\t\t\t\t<input\n\t\t\t\t\t\tv-model=\"newName\"\n\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\tdata-testid=\"cn-working-calendar-name\">\n\t\t\t\t</label>\n\t\t\t\t<div class=\"cn-working-calendar__form-actions\">\n\t\t\t\t\t<NcButton variant=\"tertiary\" data-testid=\"cn-working-calendar-cancel\" @click=\"adding = false\">\n\t\t\t\t\t\t{{ cancelLabel }}\n\t\t\t\t\t</NcButton>\n\t\t\t\t\t<NcButton\n\t\t\t\t\t\tvariant=\"primary\"\n\t\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\t\t:disabled=\"saving || !newDate\"\n\t\t\t\t\t\tdata-testid=\"cn-working-calendar-save\">\n\t\t\t\t\t\t{{ saveLabel }}\n\t\t\t\t\t</NcButton>\n\t\t\t\t</div>\n\t\t\t\t<p v-if=\"saveError\"\n\t\t\t\t\tclass=\"cn-working-calendar__error\"\n\t\t\t\t\trole=\"alert\"\n\t\t\t\t\tdata-testid=\"cn-working-calendar-save-error\">\n\t\t\t\t\t{{ saveError }}\n\t\t\t\t</p>\n\t\t\t</form>\n\t\t</template>\n\t\t<p v-else class=\"cn-working-calendar__note\" data-testid=\"cn-working-calendar-empty\">\n\t\t\t{{ emptyLabel }}\n\t\t</p>\n\t</div>\n</template>\n\n<script>\nimport { getCurrentUser } from '@nextcloud/auth'\nimport axios from '@nextcloud/axios'\nimport { translate as t } from '@nextcloud/l10n'\nimport { generateUrl } from '@nextcloud/router'\nimport { NcButton, NcLoadingIcon } from '@nextcloud/vue'\nimport ChevronLeft from 'vue-material-design-icons/ChevronLeft.vue'\nimport ChevronRight from 'vue-material-design-icons/ChevronRight.vue'\nimport { fetchReferenceObjects } from '../../utils/boardReferenceColumns.js'\nimport { hasUnresolvedTokens, resolveFilterTokens } from '../../utils/resolveFilterTokens.js'\nimport { userLocale } from '../../utils/userLocale.js'\nimport { buildMonth, isoDate, normaliseExceptions } from '../../utils/workingCalendarMonth.js'\n\nconst OBJECT_API = '/apps/openregister/api/objects'\nconst PREVIEW_URL = '/apps/openregister/api/flow-timers/calendars/preview'\n\nlet instanceCounter = 0\n\n/**\n * The id of an object, wherever OpenRegister carries it.\n *\n * @param {object|null} object The object.\n * @return {string} The id, or ''.\n */\nfunction idOf(object) {\n\treturn String(object?.id ?? object?.['@self']?.id ?? object?.uuid ?? '')\n}\n\n/**\n * Today as `YYYY-MM-DD`, in local time.\n *\n * @return {string} The date.\n */\nfunction todayIso() {\n\tconst now = new Date()\n\treturn isoDate(now.getFullYear(), now.getMonth(), now.getDate())\n}\n\n/**\n * CnWorkingCalendarWidget — the `working-calendar` widget: one month of a\n * working calendar kept as an OpenRegister object (board\n * DqInstellingenAlgemeen, \"Werkdagen en feestdagen\").\n *\n * The grid runs Monday to Sunday. Weekdays the calendar does not work are\n * grey; the dates it is closed on are red, with their name on hover and in\n * the day's label. The closures are not computed here: the widget asks\n * OpenRegister's calendar preview (`/api/flow-timers/calendars/preview`) for\n * the year shown, which expands the calendar's rules and its exceptions.\n *\n * \"Add day\" appends `{ date, name }` to the object's `exceptions` with one\n * update through the object API, under the reader's own rights; it shows for\n * administrators, and the server decides. The preview is administrators-only\n * too; for anyone else the widget shows the stored exceptions and says the\n * holidays could not be read.\n *\n * ```json\n * {\n * \"type\": \"working-calendar\",\n * \"content\": {\n * \"calendar\": { \"register\": \"flow-timers\", \"schema\": \"working-calendar\", \"filter\": { \"slug\": \"default\" } }\n * }\n * }\n * ```\n *\n * Keyboard: the days form a grid with one tab stop; the arrow keys move a\n * day or a week, Home and End to the start and end of the week, Page Up and\n * Page Down a month. Enter on a day opens Add day for that date.\n */\nexport default {\n\tname: 'CnWorkingCalendarWidget',\n\n\tcomponents: { ChevronLeft, ChevronRight, NcButton, NcLoadingIcon },\n\n\tinject: {\n\t\t/** The page's workspace values, for `@workspace.<key>` tokens in the filter. */\n\t\tcnWorkspaceContext: { default: null },\n\t\t/** The host's translate, for the manifest's texts. */\n\t\tcnTranslate: { default: () => (key) => key },\n\t},\n\n\tprops: {\n\t\t/**\n\t\t * The widget config: `{ calendar: { register, schema, id? | filter? },\n\t\t * previewUrl?, editable?, emptyText? }`.\n\t\t *\n\t\t * @type {object}\n\t\t */\n\t\tcontent: {\n\t\t\ttype: Object,\n\t\t\tdefault: () => ({}),\n\t\t},\n\n\t\t/** The bound record's id, for `@objectId` in the filter. */\n\t\tobjectId: {\n\t\t\ttype: [String, Number],\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** The bound record, for `@object.<field>` in the filter. */\n\t\tobjectData: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\t},\n\n\tdata() {\n\t\tinstanceCounter += 1\n\t\tconst now = new Date()\n\t\treturn {\n\t\t\tuid: `cn-working-calendar-${instanceCounter}`,\n\t\t\tloading: false,\n\t\t\terror: '',\n\t\t\tcalendar: null,\n\t\t\tpreviews: {},\n\t\t\tpreviewFailed: false,\n\t\t\tyear: now.getFullYear(),\n\t\t\tmonth: now.getMonth(),\n\t\t\tfocusDate: todayIso(),\n\t\t\tadding: false,\n\t\t\tnewDate: '',\n\t\t\tnewName: '',\n\t\t\tsaving: false,\n\t\t\tsaveError: '',\n\t\t\tliveText: '',\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/** @return {{register: string, schema: string, id: string, filter: (object|null)}|null} The calendar source, tokens resolved, or null while unresolved. */\n\t\tsource() {\n\t\t\tconst c = this.content?.calendar\n\t\t\tif (!c || !c.register || !c.schema) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst unwrap = (v) => (v && typeof v === 'object' && 'value' in v ? v.value : v)\n\t\t\tconst ctx = { objectId: this.objectId || null, object: this.objectData, workspace: unwrap(this.cnWorkspaceContext) || {} }\n\t\t\tconst filter = c.filter && typeof c.filter === 'object' ? resolveFilterTokens(c.filter, ctx) : null\n\t\t\tif (filter && hasUnresolvedTokens(filter)) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn { register: String(c.register), schema: String(c.schema), id: c.id ? String(c.id) : '', filter }\n\t\t},\n\n\t\t/** @return {string} A key of the source, to read it again when it changes. */\n\t\tsourceKey() {\n\t\t\treturn this.source ? JSON.stringify(this.source) : ''\n\t\t},\n\n\t\t/** @return {boolean} Whether Add day shows: administrators, unless the manifest turns it off. */\n\t\teditable() {\n\t\t\treturn this.content?.editable !== false && Boolean(getCurrentUser()?.isAdmin)\n\t\t},\n\n\t\t/** @return {number[]} The ISO weekdays that work. */\n\t\tworkingWeekdays() {\n\t\t\tconst days = this.calendar?.workingWeekdays\n\t\t\treturn Array.isArray(days) ? days.map((d) => Number(d)) : [1, 2, 3, 4, 5]\n\t\t},\n\n\t\t/** @return {Array<{date: string, name: string}>} The stored exceptions. */\n\t\texceptions() {\n\t\t\treturn normaliseExceptions(this.calendar?.exceptions)\n\t\t},\n\n\t\t/**\n\t\t * The closed dates of the year shown: the preview's, each marked as an\n\t\t * exception when the calendar lists it, else as a holiday; without a\n\t\t * preview, the stored exceptions.\n\t\t *\n\t\t * @return {Map<string, {name: string, kind: string}>}\n\t\t * @spec openspec/changes/working-calendar-widget/specs/working-calendar-widget/spec.md#requirement-a-working-calendar-shows-a-month\n\t\t */\n\t\tclosures() {\n\t\t\tconst own = new Set(this.exceptions.map((e) => e.date))\n\t\t\tconst map = new Map()\n\t\t\tconst preview = this.previews[this.year]\n\t\t\tfor (const entry of Array.isArray(preview) ? preview : []) {\n\t\t\t\tif (entry && typeof entry.date === 'string') {\n\t\t\t\t\tmap.set(entry.date, { name: String(entry.name || ''), kind: own.has(entry.date) ? 'exception' : 'holiday' })\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (const e of this.exceptions) {\n\t\t\t\tif (!map.has(e.date)) {\n\t\t\t\t\tmap.set(e.date, { name: e.name, kind: 'exception' })\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn map\n\t\t},\n\n\t\t/** @return {Array<Array<object|null>>} The weeks of the month shown. */\n\t\tweeks() {\n\t\t\treturn buildMonth(this.year, this.month, { workingWeekdays: this.workingWeekdays, closures: this.closures, today: todayIso() })\n\t\t},\n\n\t\t/** @return {Array<{short: string, long: string}>} Monday to Sunday in the user's language. */\n\t\tweekdayNames() {\n\t\t\tconst short = new Intl.DateTimeFormat(userLocale(), { weekday: 'short' })\n\t\t\tconst long = new Intl.DateTimeFormat(userLocale(), { weekday: 'long' })\n\t\t\treturn Array.from({ length: 7 }, (_v, i) => {\n\t\t\t\tconst day = new Date(Date.UTC(2024, 0, 1 + i, 12))\n\t\t\t\treturn { short: short.format(day).replace(/\\.$/, ''), long: long.format(day) }\n\t\t\t})\n\t\t},\n\n\t\t/** @return {string} \"December 2026\" in the user's language. */\n\t\tmonthTitle() {\n\t\t\tconst text = new Intl.DateTimeFormat(userLocale(), { month: 'long', year: 'numeric' }).format(new Date(this.year, this.month, 15))\n\t\t\treturn text.charAt(0).toUpperCase() + text.slice(1)\n\t\t},\n\n\t\t/** @return {string} Why holidays are missing, or ''. */\n\t\tpreviewNote() {\n\t\t\treturn this.previewFailed ? t('nextcloud-vue', 'Holidays could not be read. Only the days added by hand are shown.') : ''\n\t\t},\n\n\t\tloadingLabel: () => t('nextcloud-vue', 'Loading …'),\n\t\tpreviousMonthLabel: () => t('nextcloud-vue', 'Previous month'),\n\t\tnextMonthLabel: () => t('nextcloud-vue', 'Next month'),\n\t\taddLabel: () => t('nextcloud-vue', 'Add day'),\n\t\tdateLabel: () => t('nextcloud-vue', 'Date'),\n\t\tnameLabel: () => t('nextcloud-vue', 'Name'),\n\t\tcancelLabel: () => t('nextcloud-vue', 'Cancel'),\n\t\tsaveLabel: () => t('nextcloud-vue', 'Save'),\n\n\t\t/** @return {string} The empty-state text. */\n\t\temptyLabel() {\n\t\t\treturn this.content?.emptyText ? this.translate(this.content.emptyText) : t('nextcloud-vue', 'No working calendar found.')\n\t\t},\n\t},\n\n\twatch: {\n\t\tsourceKey: {\n\t\t\thandler() {\n\t\t\t\tthis.load()\n\t\t\t},\n\n\t\t\timmediate: true,\n\t\t},\n\n\t\tyear() {\n\t\t\tthis.loadPreview()\n\t\t},\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * The host's translate, or the text unchanged.\n\t\t *\n\t\t * @param {string} text The text.\n\t\t * @return {string} The translation.\n\t\t */\n\t\ttranslate(text) {\n\t\t\treturn typeof this.cnTranslate === 'function' ? this.cnTranslate(text) : text\n\t\t},\n\n\t\t/** @return {string} The calendar object's API URL. */\n\t\tobjectUrl() {\n\t\t\tconst s = this.source\n\t\t\tconst id = idOf(this.calendar) || s.id\n\t\t\treturn generateUrl(`${OBJECT_API}/${encodeURIComponent(s.register)}/${encodeURIComponent(s.schema)}/${encodeURIComponent(id)}`)\n\t\t},\n\n\t\t/**\n\t\t * Read the calendar object, then the closures of the year shown.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync load() {\n\t\t\tconst key = this.sourceKey\n\t\t\tif (key === '') {\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 s = this.source\n\t\t\t\tlet calendar = null\n\t\t\t\tif (s.id) {\n\t\t\t\t\tconst response = await axios.get(generateUrl(`${OBJECT_API}/${encodeURIComponent(s.register)}/${encodeURIComponent(s.schema)}/${encodeURIComponent(s.id)}`))\n\t\t\t\t\tcalendar = response?.data || null\n\t\t\t\t} else {\n\t\t\t\t\tconst found = await fetchReferenceObjects({ register: s.register, schema: s.schema, filter: s.filter || {}, limit: 1 })\n\t\t\t\t\tcalendar = found[0] || null\n\t\t\t\t}\n\t\t\t\tif (key !== this.sourceKey) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tthis.calendar = calendar\n\t\t\t\tthis.previews = {}\n\t\t\t\tif (calendar) {\n\t\t\t\t\tawait this.loadPreview()\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\tthis.error = t('nextcloud-vue', 'The working calendar could not be loaded.')\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 * Ask the calendar preview for the closed dates of the year shown,\n\t\t * once per year.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t * @spec openspec/changes/working-calendar-widget/specs/working-calendar-widget/spec.md#requirement-a-working-calendar-shows-a-month\n\t\t */\n\t\tasync loadPreview() {\n\t\t\tconst year = this.year\n\t\t\tif (!this.calendar || this.previews[year]) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst url = generateUrl(this.content?.previewUrl || PREVIEW_URL)\n\t\t\t\tconst response = await axios.post(url, { calendar: this.calendar, year })\n\t\t\t\tconst dates = Array.isArray(response?.data?.dates) ? response.data.dates : []\n\t\t\t\tthis.previews = { ...this.previews, [year]: dates }\n\t\t\t\tthis.previewFailed = false\n\t\t\t} catch {\n\t\t\t\tthis.previewFailed = true\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Show another month, keeping focus on the same day where it exists.\n\t\t *\n\t\t * @param {number} delta Months to move.\n\t\t * @return {void}\n\t\t */\n\t\tshiftMonth(delta) {\n\t\t\tconst date = new Date(this.year, this.month + delta, 1)\n\t\t\tthis.year = date.getFullYear()\n\t\t\tthis.month = date.getMonth()\n\t\t\tconst day = Math.min(Number(this.focusDate.slice(8, 10)) || 1, new Date(this.year, this.month + 1, 0).getDate())\n\t\t\tthis.focusDate = isoDate(this.year, this.month, day)\n\t\t\tthis.liveText = this.monthTitle\n\t\t},\n\n\t\t/**\n\t\t * A day's accessible label: the full date, whether it works, and the\n\t\t * closure's name.\n\t\t *\n\t\t * @param {object} slot The day.\n\t\t * @return {string} The label.\n\t\t */\n\t\tdayLabel(slot) {\n\t\t\tconst [y, m, d] = slot.date.split('-').map(Number)\n\t\t\tconst date = new Intl.DateTimeFormat(userLocale(), { weekday: 'long', day: 'numeric', month: 'long', year: 'numeric' }).format(new Date(y, m - 1, d))\n\t\t\tif (slot.closure) {\n\t\t\t\tconst name = this.closureName(slot.closure)\n\t\t\t\treturn name\n\t\t\t\t\t? t('nextcloud-vue', '{date}, closed: {name}', { date, name })\n\t\t\t\t\t: t('nextcloud-vue', '{date}, closed', { date })\n\t\t\t}\n\t\t\treturn slot.working ? t('nextcloud-vue', '{date}, working day', { date }) : t('nextcloud-vue', '{date}, not a working day', { date })\n\t\t},\n\n\t\t/**\n\t\t * A closure's name, with a fallback for an unnamed added day.\n\t\t *\n\t\t * @param {{name: string, kind: string}} closure The closure.\n\t\t * @return {string} The name.\n\t\t */\n\t\tclosureName(closure) {\n\t\t\tif (closure.name) {\n\t\t\t\treturn this.translate(closure.name)\n\t\t\t}\n\t\t\treturn closure.kind === 'exception' ? t('nextcloud-vue', 'Day added by hand') : ''\n\t\t},\n\n\t\t/**\n\t\t * Open Add day, with a date filled in.\n\t\t *\n\t\t * @param {string} [date] The date.\n\t\t * @return {void}\n\t\t */\n\t\topenAdd(date) {\n\t\t\tthis.newDate = date || this.focusDate || ''\n\t\t\tthis.newName = ''\n\t\t\tthis.saveError = ''\n\t\t\tthis.adding = true\n\t\t\tthis.$nextTick(() => this.$refs.dateInput?.focus?.())\n\t\t},\n\n\t\t/**\n\t\t * A click on a day: open Add day for it when the reader may edit.\n\t\t *\n\t\t * @param {object} slot The day.\n\t\t * @return {void}\n\t\t */\n\t\tonDayClick(slot) {\n\t\t\tthis.focusDate = slot.date\n\t\t\tif (this.editable) {\n\t\t\t\tthis.openAdd(slot.date)\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Append the new day to the calendar's exceptions with one update,\n\t\t * under the reader's rights, then read the closures again.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t * @spec openspec/changes/working-calendar-widget/specs/working-calendar-widget/spec.md#requirement-a-day-can-be-added-to-the-calendar\n\t\t */\n\t\tasync saveDay() {\n\t\t\tif (!/^\\d{4}-\\d{2}-\\d{2}$/.test(this.newDate) || !this.calendar) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.saving = true\n\t\t\tthis.saveError = ''\n\t\t\ttry {\n\t\t\t\tconst stored = Array.isArray(this.calendar.exceptions) ? this.calendar.exceptions : []\n\t\t\t\tconst name = this.newName.trim()\n\t\t\t\tconst exceptions = [...stored.filter((e) => (typeof e === 'string' ? e : e?.date) !== this.newDate), name ? { date: this.newDate, name } : { date: this.newDate }]\n\t\t\t\tconst response = await axios.patch(this.objectUrl(), { exceptions })\n\t\t\t\tthis.calendar = { ...this.calendar, ...(response?.data && typeof response.data === 'object' ? response.data : {}), exceptions }\n\t\t\t\tconst year = Number(this.newDate.slice(0, 4))\n\t\t\t\tconst { [year]: _stale, ...rest } = this.previews\n\t\t\t\tthis.previews = rest\n\t\t\t\tconst [y, m] = this.newDate.split('-').map(Number)\n\t\t\t\tthis.year = y\n\t\t\t\tthis.month = m - 1\n\t\t\t\tthis.focusDate = this.newDate\n\t\t\t\tawait this.loadPreview()\n\t\t\t\tthis.adding = false\n\t\t\t\tthis.liveText = t('nextcloud-vue', 'Day added.')\n\t\t\t} catch (e) {\n\t\t\t\tthis.saveError = e?.response?.status === 403\n\t\t\t\t\t? t('nextcloud-vue', 'Only an administrator can change the working calendar.')\n\t\t\t\t\t: t('nextcloud-vue', 'The day could not be added. Try again.')\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 * Arrow keys, Home / End and Page Up / Down move focus across the days.\n\t\t *\n\t\t * @param {KeyboardEvent} event The key event.\n\t\t * @return {void}\n\t\t */\n\t\tonKeydown(event) {\n\t\t\tconst moves = { ArrowLeft: -1, ArrowRight: 1, ArrowUp: -7, ArrowDown: 7 }\n\t\t\tconst [y, m, d] = (this.focusDate || todayIso()).split('-').map(Number)\n\t\t\tlet target\n\t\t\tif (event.key in moves) {\n\t\t\t\ttarget = new Date(y, m - 1, d + moves[event.key])\n\t\t\t} else if (event.key === 'Home' || event.key === 'End') {\n\t\t\t\tconst weekday = (new Date(y, m - 1, d).getDay() + 6) % 7\n\t\t\t\ttarget = new Date(y, m - 1, d + (event.key === 'Home' ? -weekday : 6 - weekday))\n\t\t\t} else if (event.key === 'PageUp' || event.key === 'PageDown') {\n\t\t\t\ttarget = new Date(y, m - 1 + (event.key === 'PageUp' ? -1 : 1), 1)\n\t\t\t\ttarget.setDate(Math.min(d, new Date(target.getFullYear(), target.getMonth() + 1, 0).getDate()))\n\t\t\t} else if ((event.key === 'Enter' || event.key === ' ') && this.editable) {\n\t\t\t\tevent.preventDefault()\n\t\t\t\tthis.openAdd(this.focusDate)\n\t\t\t\treturn\n\t\t\t} else {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tevent.preventDefault()\n\t\t\tthis.focusDate = isoDate(target.getFullYear(), target.getMonth(), target.getDate())\n\t\t\tif (target.getFullYear() !== this.year || target.getMonth() !== this.month) {\n\t\t\t\tthis.year = target.getFullYear()\n\t\t\t\tthis.month = target.getMonth()\n\t\t\t\tthis.liveText = this.monthTitle\n\t\t\t}\n\t\t\tthis.$nextTick(() => this.$el.querySelector?.(`[data-date=\"${this.focusDate}\"]`)?.focus?.())\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-working-calendar {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 12px;\n}\n\n.cn-working-calendar__head {\n\talign-items: center;\n\tdisplay: flex;\n\tgap: 4px;\n}\n\n.cn-working-calendar__title {\n\tfont-size: 15px;\n\tmin-width: 9em;\n\ttext-align: center;\n}\n\n.cn-working-calendar__add {\n\tmargin-inline-start: auto;\n}\n\n.cn-working-calendar__grid {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 4px;\n}\n\n.cn-working-calendar__row {\n\tdisplay: grid;\n\tgap: 4px;\n\tgrid-template-columns: repeat(7, minmax(0, 1fr));\n}\n\n.cn-working-calendar__weekday {\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 12px;\n\ttext-align: center;\n}\n\n.cn-working-calendar__day {\n\talign-items: center;\n\tbackground: var(--color-main-background);\n\tborder: 1px solid var(--color-border);\n\tborder-radius: 6px;\n\tcursor: default;\n\tdisplay: flex;\n\tfont-size: 13px;\n\theight: 34px;\n\tjustify-content: center;\n}\n\n.cn-working-calendar__day:focus-visible {\n\toutline: 2px solid var(--color-primary-element);\n\toutline-offset: 1px;\n}\n\n.cn-working-calendar__day--off {\n\tbackground: var(--color-background-dark);\n}\n\n.cn-working-calendar__day--closed {\n\tbackground: var(--color-error-light, color-mix(in srgb, var(--color-error) 12%, var(--color-main-background)));\n\tborder-color: var(--color-error);\n\tcolor: var(--color-error-text, var(--color-main-text));\n\tfont-weight: 600;\n}\n\n.cn-working-calendar__day--today {\n\tbox-shadow: inset 0 0 0 2px var(--color-primary-element);\n}\n\n.cn-working-calendar__live {\n\tclip-path: inset(50%);\n\theight: 1px;\n\toverflow: hidden;\n\tposition: absolute;\n\twhite-space: nowrap;\n\twidth: 1px;\n}\n\n.cn-working-calendar__note {\n\tcolor: var(--color-text-maxcontrast);\n\tmargin: 0;\n}\n\n.cn-working-calendar__form {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\tgap: 8px 12px;\n}\n\n.cn-working-calendar__field {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 4px;\n}\n\n.cn-working-calendar__form-actions {\n\talign-items: flex-end;\n\tdisplay: flex;\n\tgap: 8px;\n}\n\n.cn-working-calendar__error {\n\tcolor: var(--color-error-text, var(--color-error));\n\tmargin: 0;\n}\n</style>\n"],"names":["t","axios"],"mappings":"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"}