@conduction/nextcloud-vue 2.105.0 → 2.106.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 (153) hide show
  1. package/dist/esm/components/CnCardGrid/CnCardGrid.vue.js +1 -1
  2. package/dist/esm/components/CnCardGrid/CnCardGrid.vue2.js +18 -0
  3. package/dist/esm/components/CnCardGrid/CnCardGrid.vue2.js.map +1 -1
  4. package/dist/esm/components/CnCardGrid/CnCardGrid.vue3.js +3 -1
  5. package/dist/esm/components/CnCardGrid/CnCardGrid.vue3.js.map +1 -1
  6. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue.js +1 -1
  7. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js +18 -0
  8. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js.map +1 -1
  9. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js +1 -1
  10. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js.map +1 -1
  11. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +53 -4
  12. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
  13. package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
  14. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue.js +9 -0
  15. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue.js.map +1 -0
  16. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue2.js +24 -0
  17. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue2.js.map +1 -0
  18. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue3.js +49 -0
  19. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue3.js.map +1 -0
  20. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue.js +1 -1
  21. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js +36 -18
  22. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js.map +1 -1
  23. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js +17 -38
  24. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js.map +1 -1
  25. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue.js +1 -1
  26. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js.map +1 -1
  27. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue3.js.map +1 -1
  28. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue.js +1 -1
  29. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js +53 -2
  30. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js.map +1 -1
  31. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js +119 -111
  32. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js.map +1 -1
  33. package/dist/esm/components/CnFlowRunsWidget/CnFlowRunsWidget.vue.js +1 -1
  34. package/dist/esm/components/CnFlowRunsWidget/CnFlowRunsWidget.vue2.js +62 -1
  35. package/dist/esm/components/CnFlowRunsWidget/CnFlowRunsWidget.vue2.js.map +1 -1
  36. package/dist/esm/components/CnFlowRunsWidget/CnFlowRunsWidget.vue3.js.map +1 -1
  37. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +159 -50
  38. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
  39. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +121 -98
  40. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
  41. package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue.js +1 -1
  42. package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue2.js +24 -0
  43. package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue2.js.map +1 -1
  44. package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue3.js +20 -4
  45. package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue3.js.map +1 -1
  46. package/dist/esm/components/CnIndexPage/useSelfFetchList.js +22 -4
  47. package/dist/esm/components/CnIndexPage/useSelfFetchList.js.map +1 -1
  48. package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue2.js +112 -1
  49. package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue2.js.map +1 -1
  50. package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue3.js +100 -44
  51. package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue3.js.map +1 -1
  52. package/dist/esm/components/CnNcWidgetWidget/CnNcWidgetWidget.vue.js +1 -1
  53. package/dist/esm/components/CnNcWidgetWidget/CnNcWidgetWidget.vue2.js +67 -4
  54. package/dist/esm/components/CnNcWidgetWidget/CnNcWidgetWidget.vue2.js.map +1 -1
  55. package/dist/esm/components/CnNcWidgetWidget/CnNcWidgetWidget.vue3.js +1 -1
  56. package/dist/esm/components/CnNcWidgetWidget/CnNcWidgetWidget.vue3.js.map +1 -1
  57. package/dist/esm/components/CnObjectCard/CnObjectCard.vue.js +1 -1
  58. package/dist/esm/components/CnObjectCard/CnObjectCard.vue2.js +295 -12
  59. package/dist/esm/components/CnObjectCard/CnObjectCard.vue2.js.map +1 -1
  60. package/dist/esm/components/CnObjectCard/CnObjectCard.vue3.js +267 -144
  61. package/dist/esm/components/CnObjectCard/CnObjectCard.vue3.js.map +1 -1
  62. package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue.js +1 -1
  63. package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js +4 -0
  64. package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js.map +1 -1
  65. package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js +3 -1
  66. package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js.map +1 -1
  67. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue.js +1 -1
  68. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js +93 -1
  69. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js.map +1 -1
  70. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js +322 -246
  71. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js.map +1 -1
  72. package/dist/esm/components/CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue.js +1 -1
  73. package/dist/esm/components/CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue2.js +122 -7
  74. package/dist/esm/components/CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue2.js.map +1 -1
  75. package/dist/esm/components/CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue3.js +189 -93
  76. package/dist/esm/components/CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue3.js.map +1 -1
  77. package/dist/esm/components/CnTabs/CnTabs.vue.js +1 -1
  78. package/dist/esm/components/CnTabs/CnTabs.vue2.js.map +1 -1
  79. package/dist/esm/components/CnTabs/CnTabs.vue3.js.map +1 -1
  80. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue.js +1 -1
  81. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js +42 -0
  82. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js.map +1 -1
  83. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js +38 -19
  84. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js.map +1 -1
  85. package/dist/esm/components/CnTeamWorkloadWidget/CnTeamWorkloadWidget.vue.js +9 -0
  86. package/dist/esm/components/CnTeamWorkloadWidget/CnTeamWorkloadWidget.vue.js.map +1 -0
  87. package/dist/esm/components/CnTeamWorkloadWidget/CnTeamWorkloadWidget.vue2.js +258 -0
  88. package/dist/esm/components/CnTeamWorkloadWidget/CnTeamWorkloadWidget.vue2.js.map +1 -0
  89. package/dist/esm/components/CnTeamWorkloadWidget/CnTeamWorkloadWidget.vue3.js +69 -0
  90. package/dist/esm/components/CnTeamWorkloadWidget/CnTeamWorkloadWidget.vue3.js.map +1 -0
  91. package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js +12 -0
  92. package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js.map +1 -1
  93. package/dist/esm/index.js +1 -0
  94. package/dist/esm/index.js.map +1 -1
  95. package/dist/esm/l10n/en.json.js +21 -1
  96. package/dist/esm/l10n/en.json.js.map +1 -1
  97. package/dist/esm/l10n/nl.json.js +21 -1
  98. package/dist/esm/l10n/nl.json.js.map +1 -1
  99. package/dist/esm/library-style.js +1 -1
  100. package/dist/esm/nextcloud-vue.css +803 -453
  101. package/dist/esm/utils/dueText.js +18 -3
  102. package/dist/esm/utils/dueText.js.map +1 -1
  103. package/dist/esm/utils/libraryWidgetKeys.js +1 -0
  104. package/dist/esm/utils/libraryWidgetKeys.js.map +1 -1
  105. package/dist/esm/utils/sortOrder.js +11 -1
  106. package/dist/esm/utils/sortOrder.js.map +1 -1
  107. package/dist/esm/utils/validateManifestV2.compiled.js +3 -3
  108. package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
  109. package/dist/nextcloud-vue.cjs.js +8281 -6350
  110. package/dist/nextcloud-vue.cjs.js.map +2 -2
  111. package/dist/nextcloud-vue.css +803 -453
  112. package/l10n/en.json +21 -1
  113. package/l10n/nl.json +21 -1
  114. package/package.json +1 -1
  115. package/src/components/CnCardGrid/CnCardGrid.md +2 -0
  116. package/src/components/CnCardGrid/CnCardGrid.vue +20 -0
  117. package/src/components/CnCellRenderer/CnCellRenderer.vue +19 -1
  118. package/src/components/CnDetailPage/CnDetailPage.md +2 -2
  119. package/src/components/CnDetailPage/CnDetailPage.vue +53 -4
  120. package/src/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue +60 -0
  121. package/src/components/CnDetailWidgetHost/CnDetailWidgetHost.vue +36 -29
  122. package/src/components/CnFactsWidget/CnFactsWidget.vue +4 -0
  123. package/src/components/CnFilesBrowser/CnFilesBrowser.vue +70 -4
  124. package/src/components/CnFlowRunsWidget/CnFlowRunsWidget.vue +62 -1
  125. package/src/components/CnIndexPage/CnIndexPage.md +7 -5
  126. package/src/components/CnIndexPage/CnIndexPage.vue +187 -58
  127. package/src/components/CnIndexPage/CnIndexPageWidgets.vue +36 -1
  128. package/src/components/CnIndexPage/useSelfFetchList.js +22 -4
  129. package/src/components/CnIndexSidebar/CnIndexSidebar.md +2 -0
  130. package/src/components/CnIndexSidebar/CnIndexSidebar.vue +148 -1
  131. package/src/components/CnNcWidgetWidget/CnNcWidgetWidget.vue +68 -5
  132. package/src/components/CnObjectCard/CnObjectCard.md +1 -0
  133. package/src/components/CnObjectCard/CnObjectCard.vue +354 -13
  134. package/src/components/CnObjectSidebar/CnFilesTab.vue +6 -0
  135. package/src/components/CnRecordListWidget/CnRecordListWidget.vue +190 -4
  136. package/src/components/CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue +209 -9
  137. package/src/components/CnTabs/CnTabs.vue +11 -0
  138. package/src/components/CnTabsWidget/CnTabsWidget.vue +91 -18
  139. package/src/components/CnTeamWorkloadWidget/CnTeamWorkloadWidget.md +11 -0
  140. package/src/components/CnTeamWorkloadWidget/CnTeamWorkloadWidget.vue +382 -0
  141. package/src/components/CnTeamWorkloadWidget/index.js +14 -0
  142. package/src/components/CnWidgetGrid/registerDashboardWidgets.js +12 -0
  143. package/src/components/index.js +1 -0
  144. package/src/css/index-page.css +14 -2
  145. package/src/css/look-board-detail.css +48 -4
  146. package/src/css/look-board-index.css +64 -2
  147. package/src/css/look-board.css +25 -2
  148. package/src/index.js +1 -1
  149. package/src/schemas/app-manifest-v2.schema.json +75 -6
  150. package/src/utils/dueText.js +18 -3
  151. package/src/utils/libraryWidgetKeys.js +1 -0
  152. package/src/utils/sortOrder.js +10 -0
  153. package/src/utils/validateManifestV2.compiled.js +3 -3
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CnTeamWorkloadWidget.vue2.js","sources":["../../../../src/components/CnTeamWorkloadWidget/CnTeamWorkloadWidget.vue"],"sourcesContent":["<!--\n SPDX-FileCopyrightText: 2026 Conduction B.V.\n SPDX-License-Identifier: EUPL-1.2\n-->\n<template>\n\t<div class=\"cn-team-workload\" data-testid=\"cn-team-workload\">\n\t\t<p v-if=\"loading && members.length === 0\" class=\"cn-team-workload__state-line\" role=\"status\">\n\t\t\t{{ loadingLabel }}\n\t\t</p>\n\t\t<p v-else-if=\"members.length === 0\" class=\"cn-team-workload__state-line\">\n\t\t\t{{ emptyLabel }}\n\t\t</p>\n\t\t<ul v-else class=\"cn-team-workload__list\">\n\t\t\t<li\n\t\t\t\tv-for=\"member in members\"\n\t\t\t\t:key=\"member.id\"\n\t\t\t\tclass=\"cn-team-workload__member\"\n\t\t\t\tdata-testid=\"cn-team-workload-member\">\n\t\t\t\t<div class=\"cn-team-workload__row\">\n\t\t\t\t\t<span class=\"cn-team-workload__avatar\" aria-hidden=\"true\">{{ member.initials }}</span>\n\t\t\t\t\t<span class=\"cn-team-workload__who\">\n\t\t\t\t\t\t<strong class=\"cn-team-workload__name\">{{ member.name }}</strong>\n\t\t\t\t\t\t<span\n\t\t\t\t\t\t\tclass=\"cn-team-workload__state\"\n\t\t\t\t\t\t\t:class=\"{ 'cn-team-workload__state--away': !member.available }\">{{ member.line }}</span>\n\t\t\t\t\t</span>\n\t\t\t\t\t<span class=\"cn-team-workload__count\">{{ member.countText }}</span>\n\t\t\t\t</div>\n\t\t\t\t<span class=\"cn-team-workload__bar\" aria-hidden=\"true\">\n\t\t\t\t\t<span\n\t\t\t\t\t\tclass=\"cn-team-workload__bar-fill\"\n\t\t\t\t\t\t:class=\"{ 'cn-team-workload__bar-fill--hot': member.hot }\"\n\t\t\t\t\t\t:style=\"{ width: member.percent + '%' }\" />\n\t\t\t\t</span>\n\t\t\t</li>\n\t\t</ul>\n\t</div>\n</template>\n\n<script>\nimport { getCurrentUser } from '@nextcloud/auth'\nimport { translatePlural as n, translate as t } from '@nextcloud/l10n'\nimport { generateUrl } from '@nextcloud/router'\nimport { fetchStatuses } from '../../utils/nextcloudDirectory.js'\nimport { readPath } from '../../utils/readPath.js'\nimport { userLocale } from '../../utils/userLocale.js'\n\n/** The share of the capacity from which a load bar reads as full. */\nconst HOT_PERCENT = 90\n\n/**\n * CnTeamWorkloadWidget: the `team-workload` widget (\"Team vandaag\" on board\n * DqTeamwachtrij). Each person of the team with their initials, name, an\n * availability line, their open count and a load bar; the card's header\n * note says how many are present (\"4 of 5 present\").\n *\n * The counts come from the app (`content.source`, an endpoint that answers a\n * row per person). The availability comes from Nextcloud's user status, read\n * on the client through the OCS user status API: the person's own message\n * with the time it ends (\"In a meeting until 14:00\"), else Available, Away or\n * Busy, and Absent today without a status. Present means any status but\n * offline.\n *\n * `content`:\n * - `source`: `{ url, responsePath?, userField?, nameField?, countField? }`;\n * the url goes through `generateUrl`, the rows are read at `responsePath`\n * (else the body), each with the user id at `userField` (default\n * `userId`), the name at `nameField` (default `displayName`) and the count\n * at `countField` (default `count`).\n * - `capacity`: the count at a full bar; without it the highest count is.\n * - `countLabel`: `{ one, other }` with `{count}`, through the app's\n * translate; without it the count reads \"{count} open\".\n * - `emptyText`: shown without anyone to list.\n */\nexport default {\n\tname: 'CnTeamWorkloadWidget',\n\n\tinject: {\n\t\tcnTranslate: { default: () => (key) => key },\n\t},\n\n\tprops: {\n\t\t/** The widget's content: `source`, `capacity`, `countLabel`, `emptyText`. */\n\t\tcontent: {\n\t\t\ttype: Object,\n\t\t\tdefault: () => ({}),\n\t\t},\n\t},\n\n\temits: ['header'],\n\n\tdata() {\n\t\treturn {\n\t\t\t/** The rows the source answered. */\n\t\t\trows: [],\n\t\t\t/** The user statuses by user id. */\n\t\t\tstatuses: {},\n\t\t\t/** Whether the source is being read. */\n\t\t\tloading: false,\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/** @return {string} The signed-in user's id. */\n\t\tviewerId() {\n\t\t\treturn String(getCurrentUser()?.uid || '')\n\t\t},\n\n\t\t/**\n\t\t * The people to list, the viewer first and the rest by name, each with\n\t\t * the line, count and bar to draw.\n\t\t *\n\t\t * @return {Array<object>} The members.\n\t\t */\n\t\tmembers() {\n\t\t\tconst source = this.content?.source || {}\n\t\t\tconst userField = source.userField || 'userId'\n\t\t\tconst nameField = source.nameField || 'displayName'\n\t\t\tconst countField = source.countField || 'count'\n\t\t\tconst people = this.rows\n\t\t\t\t.filter((row) => row && typeof row === 'object' && readPath(row, userField))\n\t\t\t\t.map((row) => {\n\t\t\t\t\tconst id = String(readPath(row, userField))\n\t\t\t\t\tconst name = String(readPath(row, nameField) || id)\n\t\t\t\t\treturn { id, name, count: Number(readPath(row, countField)) || 0 }\n\t\t\t\t})\n\t\t\tconst capacity = Number(this.content?.capacity) > 0\n\t\t\t\t? Number(this.content.capacity)\n\t\t\t\t: Math.max(1, ...people.map((p) => p.count))\n\t\t\treturn people\n\t\t\t\t.sort((a, b) => (Number(b.id === this.viewerId) - Number(a.id === this.viewerId)) || a.name.localeCompare(b.name))\n\t\t\t\t.map((person) => {\n\t\t\t\t\tconst status = this.statuses[person.id] || null\n\t\t\t\t\tconst percent = Math.min(100, Math.round((person.count / capacity) * 100))\n\t\t\t\t\treturn {\n\t\t\t\t\t\t...person,\n\t\t\t\t\t\tname: person.id === this.viewerId ? t('nextcloud-vue', '{name} (you)', { name: person.name }) : person.name,\n\t\t\t\t\t\tinitials: initialsOf(person.name),\n\t\t\t\t\t\tline: this.lineOf(status),\n\t\t\t\t\t\tavailable: !!status && status.status === 'online',\n\t\t\t\t\t\tpresent: isPresent(status),\n\t\t\t\t\t\tcountText: this.countText(person.count),\n\t\t\t\t\t\tpercent,\n\t\t\t\t\t\thot: percent >= HOT_PERCENT,\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t},\n\n\t\t/** @return {string} The header note: how many of the team are present. */\n\t\theaderNote() {\n\t\t\tconst total = this.members.length\n\t\t\tif (total === 0) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tconst present = this.members.filter((member) => member.present).length\n\t\t\treturn t('nextcloud-vue', '{present} of {total} present', { present, total })\n\t\t},\n\n\t\t/** @return {string} What the card says while it reads. */\n\t\tloadingLabel() {\n\t\t\treturn t('nextcloud-vue', 'Loading…')\n\t\t},\n\n\t\t/** @return {string} What the card says without anyone to list. */\n\t\temptyLabel() {\n\t\t\treturn this.content?.emptyText ? this.cnTranslate(this.content.emptyText) : t('nextcloud-vue', 'No one in the team')\n\t\t},\n\t},\n\n\twatch: {\n\t\theaderNote: {\n\t\t\timmediate: true,\n\t\t\thandler(note) {\n\t\t\t\t/**\n\t\t\t\t * @event header The card header's parts: `{ link, note, action, pill }`, the note being how many are present.\n\t\t\t\t */\n\t\t\t\tthis.$emit('header', { link: null, note, action: null, pill: null })\n\t\t\t},\n\t\t},\n\n\t\t'content.source': {\n\t\t\tdeep: true,\n\t\t\thandler() {\n\t\t\t\tthis.load()\n\t\t\t},\n\t\t},\n\t},\n\n\tmounted() {\n\t\tthis.load()\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * Read the counts and the user statuses. A failed read leaves the card\n\t\t * empty; a failed status read leaves everyone without a status.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync load() {\n\t\t\tconst source = this.content?.source\n\t\t\tif (!source || typeof source.url !== 'string' || source.url === '') {\n\t\t\t\tthis.rows = []\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.loading = true\n\t\t\ttry {\n\t\t\t\tconst { default: axios } = await import('@nextcloud/axios')\n\t\t\t\tconst [answer, statuses] = await Promise.all([\n\t\t\t\t\taxios.get(generateUrl(source.url)),\n\t\t\t\t\tfetchStatuses(axios),\n\t\t\t\t])\n\t\t\t\tconst body = answer && answer.data\n\t\t\t\tconst rows = source.responsePath ? readPath(body, source.responsePath) : body\n\t\t\t\tthis.rows = Array.isArray(rows) ? rows : []\n\t\t\t\tthis.statuses = statuses || {}\n\t\t\t} catch {\n\t\t\t\tthis.rows = []\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 * The availability line of a user status.\n\t\t *\n\t\t * @param {object|null} status The user status, or null without one.\n\t\t * @return {string} The line.\n\t\t */\n\t\tlineOf(status) {\n\t\t\tif (!status) {\n\t\t\t\treturn t('nextcloud-vue', 'Absent today')\n\t\t\t}\n\t\t\tconst message = typeof status.message === 'string' ? status.message.trim() : ''\n\t\t\tif (message !== '') {\n\t\t\t\tconst clearAt = Number(status.clearAt)\n\t\t\t\tif (!Number.isFinite(clearAt) || clearAt <= 0) {\n\t\t\t\t\treturn message\n\t\t\t\t}\n\t\t\t\tconst time = new Date(clearAt * 1000).toLocaleTimeString(userLocale() || undefined, { hour: '2-digit', minute: '2-digit' })\n\t\t\t\treturn t('nextcloud-vue', '{message} until {time}', { message, time })\n\t\t\t}\n\t\t\tswitch (status.status) {\n\t\t\t\tcase 'online':\n\t\t\t\t\treturn t('nextcloud-vue', 'Available')\n\t\t\t\tcase 'away':\n\t\t\t\t\treturn t('nextcloud-vue', 'Away')\n\t\t\t\tcase 'dnd':\n\t\t\t\tcase 'busy':\n\t\t\t\t\treturn t('nextcloud-vue', 'Busy')\n\t\t\t\tdefault:\n\t\t\t\t\treturn t('nextcloud-vue', 'Absent today')\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * The count as words: the content's `countLabel`, else \"{count} open\".\n\t\t *\n\t\t * @param {number} count The open count.\n\t\t * @return {string} The text.\n\t\t */\n\t\tcountText(count) {\n\t\t\tconst label = this.content?.countLabel\n\t\t\tif (label && typeof label === 'object' && typeof label.one === 'string' && typeof label.other === 'string') {\n\t\t\t\treturn this.cnTranslate(count === 1 ? label.one : label.other).replace('{count}', String(count))\n\t\t\t}\n\t\t\treturn n('nextcloud-vue', '{count} open', '{count} open', count, { count })\n\t\t},\n\t},\n}\n\n/**\n * Up to two initials of a name.\n *\n * @param {string} name The name.\n * @return {string} The initials, upper case.\n */\nfunction initialsOf(name) {\n\tconst parts = String(name || '').trim().split(/\\s+/).filter(Boolean)\n\tif (parts.length === 0) {\n\t\treturn ''\n\t}\n\tconst last = parts.length > 1 ? parts[parts.length - 1].charAt(0) : ''\n\treturn (parts[0].charAt(0) + last).toUpperCase()\n}\n\n/**\n * Whether a person is at work today: any status but offline or invisible.\n *\n * @param {object|null} status The user status.\n * @return {boolean} True when present.\n */\nfunction isPresent(status) {\n\treturn !!status && status.status !== 'offline' && status.status !== 'invisible'\n}\n</script>\n\n<style scoped>\n.cn-team-workload__list {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 14px;\n\tmargin: 0;\n\tpadding: 0;\n\tlist-style: none;\n}\n\n.cn-team-workload__member {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 6px;\n}\n\n.cn-team-workload__row {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 10px;\n}\n\n.cn-team-workload__avatar {\n\tdisplay: flex;\n\tflex: none;\n\talign-items: center;\n\tjustify-content: center;\n\twidth: 32px;\n\theight: 32px;\n\tborder-radius: 50%;\n\tbackground: var(--color-background-dark);\n\tcolor: var(--color-main-text);\n\tfont-size: 12px;\n\tfont-weight: 700;\n}\n\n.cn-team-workload__who {\n\tdisplay: flex;\n\tflex: 1;\n\tflex-direction: column;\n\tmin-width: 0;\n}\n\n.cn-team-workload__name {\n\tfont-size: 14px;\n}\n\n.cn-team-workload__state {\n\tfont-size: 13px;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-team-workload__state--away {\n\tcolor: var(--color-warning-text, var(--color-text-maxcontrast));\n}\n\n.cn-team-workload__count {\n\tfont-size: 13px;\n\tfont-weight: 600;\n\twhite-space: nowrap;\n}\n\n.cn-team-workload__bar {\n\tdisplay: block;\n\theight: 6px;\n\toverflow: hidden;\n\tborder-radius: 3px;\n\tbackground: var(--color-border);\n}\n\n.cn-team-workload__bar-fill {\n\tdisplay: block;\n\theight: 100%;\n\tbackground: var(--color-primary-element);\n}\n\n.cn-team-workload__bar-fill--hot {\n\tbackground: var(--color-error);\n}\n\n.cn-team-workload__state-line {\n\tmargin: 0;\n\tcolor: var(--color-text-maxcontrast);\n}\n</style>\n"],"names":["t","n"],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ import { openBlock, createElementBlock, toDisplayString, Fragment, renderList, createElementVNode, normalizeClass, normalizeStyle } from 'vue';
2
+
3
+ const _hoisted_1 = {
4
+ class: "cn-team-workload",
5
+ "data-testid": "cn-team-workload"
6
+ };
7
+ const _hoisted_2 = {
8
+ key: 0,
9
+ class: "cn-team-workload__state-line",
10
+ role: "status"
11
+ };
12
+ const _hoisted_3 = {
13
+ key: 1,
14
+ class: "cn-team-workload__state-line"
15
+ };
16
+ const _hoisted_4 = {
17
+ key: 2,
18
+ class: "cn-team-workload__list"
19
+ };
20
+ const _hoisted_5 = { class: "cn-team-workload__row" };
21
+ const _hoisted_6 = {
22
+ class: "cn-team-workload__avatar",
23
+ "aria-hidden": "true"
24
+ };
25
+ const _hoisted_7 = { class: "cn-team-workload__who" };
26
+ const _hoisted_8 = { class: "cn-team-workload__name" };
27
+ const _hoisted_9 = { class: "cn-team-workload__count" };
28
+ const _hoisted_10 = {
29
+ class: "cn-team-workload__bar",
30
+ "aria-hidden": "true"
31
+ };
32
+
33
+ function render(_ctx, _cache, $props, $setup, $data, $options) {
34
+ return (openBlock(), createElementBlock("div", _hoisted_1, [
35
+ ($data.loading && $options.members.length === 0)
36
+ ? (openBlock(), createElementBlock("p", _hoisted_2, toDisplayString($options.loadingLabel), 1 /* TEXT */))
37
+ : ($options.members.length === 0)
38
+ ? (openBlock(), createElementBlock("p", _hoisted_3, toDisplayString($options.emptyLabel), 1 /* TEXT */))
39
+ : (openBlock(), createElementBlock("ul", _hoisted_4, [
40
+ (openBlock(true), createElementBlock(Fragment, null, renderList($options.members, (member) => {
41
+ return (openBlock(), createElementBlock("li", {
42
+ key: member.id,
43
+ class: "cn-team-workload__member",
44
+ "data-testid": "cn-team-workload-member"
45
+ }, [
46
+ createElementVNode("div", _hoisted_5, [
47
+ createElementVNode("span", _hoisted_6, toDisplayString(member.initials), 1 /* TEXT */),
48
+ createElementVNode("span", _hoisted_7, [
49
+ createElementVNode("strong", _hoisted_8, toDisplayString(member.name), 1 /* TEXT */),
50
+ createElementVNode("span", {
51
+ class: normalizeClass(["cn-team-workload__state", { 'cn-team-workload__state--away': !member.available }])
52
+ }, toDisplayString(member.line), 3 /* TEXT, CLASS */)
53
+ ]),
54
+ createElementVNode("span", _hoisted_9, toDisplayString(member.countText), 1 /* TEXT */)
55
+ ]),
56
+ createElementVNode("span", _hoisted_10, [
57
+ createElementVNode("span", {
58
+ class: normalizeClass(["cn-team-workload__bar-fill", { 'cn-team-workload__bar-fill--hot': member.hot }]),
59
+ style: normalizeStyle({ width: member.percent + '%' })
60
+ }, null, 6 /* CLASS, STYLE */)
61
+ ])
62
+ ]))
63
+ }), 128 /* KEYED_FRAGMENT */))
64
+ ]))
65
+ ]))
66
+ }
67
+
68
+ export { render };
69
+ //# sourceMappingURL=CnTeamWorkloadWidget.vue3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CnTeamWorkloadWidget.vue3.js","sources":["../../../../src/components/CnTeamWorkloadWidget/CnTeamWorkloadWidget.vue?vue&type=template&id=8e82bdea&lang.js"],"sourcesContent":["<!--\n SPDX-FileCopyrightText: 2026 Conduction B.V.\n SPDX-License-Identifier: EUPL-1.2\n-->\n<template>\n\t<div class=\"cn-team-workload\" data-testid=\"cn-team-workload\">\n\t\t<p v-if=\"loading && members.length === 0\" class=\"cn-team-workload__state-line\" role=\"status\">\n\t\t\t{{ loadingLabel }}\n\t\t</p>\n\t\t<p v-else-if=\"members.length === 0\" class=\"cn-team-workload__state-line\">\n\t\t\t{{ emptyLabel }}\n\t\t</p>\n\t\t<ul v-else class=\"cn-team-workload__list\">\n\t\t\t<li\n\t\t\t\tv-for=\"member in members\"\n\t\t\t\t:key=\"member.id\"\n\t\t\t\tclass=\"cn-team-workload__member\"\n\t\t\t\tdata-testid=\"cn-team-workload-member\">\n\t\t\t\t<div class=\"cn-team-workload__row\">\n\t\t\t\t\t<span class=\"cn-team-workload__avatar\" aria-hidden=\"true\">{{ member.initials }}</span>\n\t\t\t\t\t<span class=\"cn-team-workload__who\">\n\t\t\t\t\t\t<strong class=\"cn-team-workload__name\">{{ member.name }}</strong>\n\t\t\t\t\t\t<span\n\t\t\t\t\t\t\tclass=\"cn-team-workload__state\"\n\t\t\t\t\t\t\t:class=\"{ 'cn-team-workload__state--away': !member.available }\">{{ member.line }}</span>\n\t\t\t\t\t</span>\n\t\t\t\t\t<span class=\"cn-team-workload__count\">{{ member.countText }}</span>\n\t\t\t\t</div>\n\t\t\t\t<span class=\"cn-team-workload__bar\" aria-hidden=\"true\">\n\t\t\t\t\t<span\n\t\t\t\t\t\tclass=\"cn-team-workload__bar-fill\"\n\t\t\t\t\t\t:class=\"{ 'cn-team-workload__bar-fill--hot': member.hot }\"\n\t\t\t\t\t\t:style=\"{ width: member.percent + '%' }\" />\n\t\t\t\t</span>\n\t\t\t</li>\n\t\t</ul>\n\t</div>\n</template>\n\n<script>\nimport { getCurrentUser } from '@nextcloud/auth'\nimport { translatePlural as n, translate as t } from '@nextcloud/l10n'\nimport { generateUrl } from '@nextcloud/router'\nimport { fetchStatuses } from '../../utils/nextcloudDirectory.js'\nimport { readPath } from '../../utils/readPath.js'\nimport { userLocale } from '../../utils/userLocale.js'\n\n/** The share of the capacity from which a load bar reads as full. */\nconst HOT_PERCENT = 90\n\n/**\n * CnTeamWorkloadWidget: the `team-workload` widget (\"Team vandaag\" on board\n * DqTeamwachtrij). Each person of the team with their initials, name, an\n * availability line, their open count and a load bar; the card's header\n * note says how many are present (\"4 of 5 present\").\n *\n * The counts come from the app (`content.source`, an endpoint that answers a\n * row per person). The availability comes from Nextcloud's user status, read\n * on the client through the OCS user status API: the person's own message\n * with the time it ends (\"In a meeting until 14:00\"), else Available, Away or\n * Busy, and Absent today without a status. Present means any status but\n * offline.\n *\n * `content`:\n * - `source`: `{ url, responsePath?, userField?, nameField?, countField? }`;\n * the url goes through `generateUrl`, the rows are read at `responsePath`\n * (else the body), each with the user id at `userField` (default\n * `userId`), the name at `nameField` (default `displayName`) and the count\n * at `countField` (default `count`).\n * - `capacity`: the count at a full bar; without it the highest count is.\n * - `countLabel`: `{ one, other }` with `{count}`, through the app's\n * translate; without it the count reads \"{count} open\".\n * - `emptyText`: shown without anyone to list.\n */\nexport default {\n\tname: 'CnTeamWorkloadWidget',\n\n\tinject: {\n\t\tcnTranslate: { default: () => (key) => key },\n\t},\n\n\tprops: {\n\t\t/** The widget's content: `source`, `capacity`, `countLabel`, `emptyText`. */\n\t\tcontent: {\n\t\t\ttype: Object,\n\t\t\tdefault: () => ({}),\n\t\t},\n\t},\n\n\temits: ['header'],\n\n\tdata() {\n\t\treturn {\n\t\t\t/** The rows the source answered. */\n\t\t\trows: [],\n\t\t\t/** The user statuses by user id. */\n\t\t\tstatuses: {},\n\t\t\t/** Whether the source is being read. */\n\t\t\tloading: false,\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/** @return {string} The signed-in user's id. */\n\t\tviewerId() {\n\t\t\treturn String(getCurrentUser()?.uid || '')\n\t\t},\n\n\t\t/**\n\t\t * The people to list, the viewer first and the rest by name, each with\n\t\t * the line, count and bar to draw.\n\t\t *\n\t\t * @return {Array<object>} The members.\n\t\t */\n\t\tmembers() {\n\t\t\tconst source = this.content?.source || {}\n\t\t\tconst userField = source.userField || 'userId'\n\t\t\tconst nameField = source.nameField || 'displayName'\n\t\t\tconst countField = source.countField || 'count'\n\t\t\tconst people = this.rows\n\t\t\t\t.filter((row) => row && typeof row === 'object' && readPath(row, userField))\n\t\t\t\t.map((row) => {\n\t\t\t\t\tconst id = String(readPath(row, userField))\n\t\t\t\t\tconst name = String(readPath(row, nameField) || id)\n\t\t\t\t\treturn { id, name, count: Number(readPath(row, countField)) || 0 }\n\t\t\t\t})\n\t\t\tconst capacity = Number(this.content?.capacity) > 0\n\t\t\t\t? Number(this.content.capacity)\n\t\t\t\t: Math.max(1, ...people.map((p) => p.count))\n\t\t\treturn people\n\t\t\t\t.sort((a, b) => (Number(b.id === this.viewerId) - Number(a.id === this.viewerId)) || a.name.localeCompare(b.name))\n\t\t\t\t.map((person) => {\n\t\t\t\t\tconst status = this.statuses[person.id] || null\n\t\t\t\t\tconst percent = Math.min(100, Math.round((person.count / capacity) * 100))\n\t\t\t\t\treturn {\n\t\t\t\t\t\t...person,\n\t\t\t\t\t\tname: person.id === this.viewerId ? t('nextcloud-vue', '{name} (you)', { name: person.name }) : person.name,\n\t\t\t\t\t\tinitials: initialsOf(person.name),\n\t\t\t\t\t\tline: this.lineOf(status),\n\t\t\t\t\t\tavailable: !!status && status.status === 'online',\n\t\t\t\t\t\tpresent: isPresent(status),\n\t\t\t\t\t\tcountText: this.countText(person.count),\n\t\t\t\t\t\tpercent,\n\t\t\t\t\t\thot: percent >= HOT_PERCENT,\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t},\n\n\t\t/** @return {string} The header note: how many of the team are present. */\n\t\theaderNote() {\n\t\t\tconst total = this.members.length\n\t\t\tif (total === 0) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tconst present = this.members.filter((member) => member.present).length\n\t\t\treturn t('nextcloud-vue', '{present} of {total} present', { present, total })\n\t\t},\n\n\t\t/** @return {string} What the card says while it reads. */\n\t\tloadingLabel() {\n\t\t\treturn t('nextcloud-vue', 'Loading…')\n\t\t},\n\n\t\t/** @return {string} What the card says without anyone to list. */\n\t\temptyLabel() {\n\t\t\treturn this.content?.emptyText ? this.cnTranslate(this.content.emptyText) : t('nextcloud-vue', 'No one in the team')\n\t\t},\n\t},\n\n\twatch: {\n\t\theaderNote: {\n\t\t\timmediate: true,\n\t\t\thandler(note) {\n\t\t\t\t/**\n\t\t\t\t * @event header The card header's parts: `{ link, note, action, pill }`, the note being how many are present.\n\t\t\t\t */\n\t\t\t\tthis.$emit('header', { link: null, note, action: null, pill: null })\n\t\t\t},\n\t\t},\n\n\t\t'content.source': {\n\t\t\tdeep: true,\n\t\t\thandler() {\n\t\t\t\tthis.load()\n\t\t\t},\n\t\t},\n\t},\n\n\tmounted() {\n\t\tthis.load()\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * Read the counts and the user statuses. A failed read leaves the card\n\t\t * empty; a failed status read leaves everyone without a status.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync load() {\n\t\t\tconst source = this.content?.source\n\t\t\tif (!source || typeof source.url !== 'string' || source.url === '') {\n\t\t\t\tthis.rows = []\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.loading = true\n\t\t\ttry {\n\t\t\t\tconst { default: axios } = await import('@nextcloud/axios')\n\t\t\t\tconst [answer, statuses] = await Promise.all([\n\t\t\t\t\taxios.get(generateUrl(source.url)),\n\t\t\t\t\tfetchStatuses(axios),\n\t\t\t\t])\n\t\t\t\tconst body = answer && answer.data\n\t\t\t\tconst rows = source.responsePath ? readPath(body, source.responsePath) : body\n\t\t\t\tthis.rows = Array.isArray(rows) ? rows : []\n\t\t\t\tthis.statuses = statuses || {}\n\t\t\t} catch {\n\t\t\t\tthis.rows = []\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 * The availability line of a user status.\n\t\t *\n\t\t * @param {object|null} status The user status, or null without one.\n\t\t * @return {string} The line.\n\t\t */\n\t\tlineOf(status) {\n\t\t\tif (!status) {\n\t\t\t\treturn t('nextcloud-vue', 'Absent today')\n\t\t\t}\n\t\t\tconst message = typeof status.message === 'string' ? status.message.trim() : ''\n\t\t\tif (message !== '') {\n\t\t\t\tconst clearAt = Number(status.clearAt)\n\t\t\t\tif (!Number.isFinite(clearAt) || clearAt <= 0) {\n\t\t\t\t\treturn message\n\t\t\t\t}\n\t\t\t\tconst time = new Date(clearAt * 1000).toLocaleTimeString(userLocale() || undefined, { hour: '2-digit', minute: '2-digit' })\n\t\t\t\treturn t('nextcloud-vue', '{message} until {time}', { message, time })\n\t\t\t}\n\t\t\tswitch (status.status) {\n\t\t\t\tcase 'online':\n\t\t\t\t\treturn t('nextcloud-vue', 'Available')\n\t\t\t\tcase 'away':\n\t\t\t\t\treturn t('nextcloud-vue', 'Away')\n\t\t\t\tcase 'dnd':\n\t\t\t\tcase 'busy':\n\t\t\t\t\treturn t('nextcloud-vue', 'Busy')\n\t\t\t\tdefault:\n\t\t\t\t\treturn t('nextcloud-vue', 'Absent today')\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * The count as words: the content's `countLabel`, else \"{count} open\".\n\t\t *\n\t\t * @param {number} count The open count.\n\t\t * @return {string} The text.\n\t\t */\n\t\tcountText(count) {\n\t\t\tconst label = this.content?.countLabel\n\t\t\tif (label && typeof label === 'object' && typeof label.one === 'string' && typeof label.other === 'string') {\n\t\t\t\treturn this.cnTranslate(count === 1 ? label.one : label.other).replace('{count}', String(count))\n\t\t\t}\n\t\t\treturn n('nextcloud-vue', '{count} open', '{count} open', count, { count })\n\t\t},\n\t},\n}\n\n/**\n * Up to two initials of a name.\n *\n * @param {string} name The name.\n * @return {string} The initials, upper case.\n */\nfunction initialsOf(name) {\n\tconst parts = String(name || '').trim().split(/\\s+/).filter(Boolean)\n\tif (parts.length === 0) {\n\t\treturn ''\n\t}\n\tconst last = parts.length > 1 ? parts[parts.length - 1].charAt(0) : ''\n\treturn (parts[0].charAt(0) + last).toUpperCase()\n}\n\n/**\n * Whether a person is at work today: any status but offline or invisible.\n *\n * @param {object|null} status The user status.\n * @return {boolean} True when present.\n */\nfunction isPresent(status) {\n\treturn !!status && status.status !== 'offline' && status.status !== 'invisible'\n}\n</script>\n\n<style scoped>\n.cn-team-workload__list {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 14px;\n\tmargin: 0;\n\tpadding: 0;\n\tlist-style: none;\n}\n\n.cn-team-workload__member {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 6px;\n}\n\n.cn-team-workload__row {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 10px;\n}\n\n.cn-team-workload__avatar {\n\tdisplay: flex;\n\tflex: none;\n\talign-items: center;\n\tjustify-content: center;\n\twidth: 32px;\n\theight: 32px;\n\tborder-radius: 50%;\n\tbackground: var(--color-background-dark);\n\tcolor: var(--color-main-text);\n\tfont-size: 12px;\n\tfont-weight: 700;\n}\n\n.cn-team-workload__who {\n\tdisplay: flex;\n\tflex: 1;\n\tflex-direction: column;\n\tmin-width: 0;\n}\n\n.cn-team-workload__name {\n\tfont-size: 14px;\n}\n\n.cn-team-workload__state {\n\tfont-size: 13px;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-team-workload__state--away {\n\tcolor: var(--color-warning-text, var(--color-text-maxcontrast));\n}\n\n.cn-team-workload__count {\n\tfont-size: 13px;\n\tfont-weight: 600;\n\twhite-space: nowrap;\n}\n\n.cn-team-workload__bar {\n\tdisplay: block;\n\theight: 6px;\n\toverflow: hidden;\n\tborder-radius: 3px;\n\tbackground: var(--color-border);\n}\n\n.cn-team-workload__bar-fill {\n\tdisplay: block;\n\theight: 100%;\n\tbackground: var(--color-primary-element);\n}\n\n.cn-team-workload__bar-fill--hot {\n\tbackground: var(--color-error);\n}\n\n.cn-team-workload__state-line {\n\tmargin: 0;\n\tcolor: var(--color-text-maxcontrast);\n}\n</style>\n"],"names":["_openBlock","_createElementBlock","_toDisplayString","_createElementVNode","_normalizeClass","_normalizeStyle"],"mappings":";;;AASM,EAAA,KAAK,EAAC,kBAAiB;AAAE,EAAA,aAAW,EAAC,kBAAkB;;;;AAC3C,EAAA,KAAA,EAAA,8BAAA;AAAA,EAAA,IAAA,EAAA,QAAA;;;;AAGb,EAAA,KAAA,EAAA,8BAAA;;;;AAGQ,EAAA,KAAK,EAAC,wBAAgB;;AAM1B,MAAA,UAAA,GAAA,EAAA,KAAC,EAAA,uBAAA,GAAA;;AACC,EAAA,KAAK,EAAC,0BAAoB;AAAA,EAAA,aAAA,EAAA,MAAA;;AAC1B,MAAA,UAAA,GAAA,EAAA,KAAI,EAAE,uBAAuB,GAAA;AAC7B,MAAA,UAAA,GAAA,EAAA,KAAA,EAAA,wBAAA,GAAA;AAKA,MAAA,UAAA,GAAA,EAAA,KAAK,EAAC,yBAAsB,GAAA;;AAE7B,EAAA,KAAM,EAAA;AAAwB,EAAA,aAAQ,EAAA,MAAA;;;;AAvB9C,EAAA,QAAAA,SAAA,EAAA,EAAAC,kBAAA,QAAA;KACS,KAAO,CAAA,OAAA,IAAA,QAAA,CAAA,OAAA,CAAA,MAAA,KAAA,CAAA;wCAEZ,CAAA,GAAA,YAAA,EAAAC,eAAA,CADD,QAAA,CAAA,YAAA,CAAA,EAAA,CAAA,YAAA;AAEA,QAAA,CAAA,QAAA,CAAA,OAAA,CAAA,MAAA,KAAA,CAAA;wBAAFD,kBAEG,CAAA,GAAA,EAFH,UAEG,EAAAC,eAAA,CADA,QAAU,CAAA,UAAA,CAAA,EAAA,CAAA,YAAA;AAEZ,WAAAF,SAAA,EAAA,EAAAC,kBAAA,OAAA;8BACAA,8CACiB,QAAO,CAAA,OAAA,EAAA,CAAjB,MAAM,KAAA;mCADbA;gBAEC,GAAG,EAAG,MAAK,CAAC,EAAE;AACd,gBAAA,KAAI,EAAA,0BAA2B;6BACrB,EAAC,yBAAyB;;mCAU/B,iBAAA,EAAA;AARH,kBAAAE,kBAAA,CAA8B,MAA9B,EAAA,UAA8B,EAAAD,eAAA,CAAA,MAAA,CAAA,QAAA,CAAA,EAAA,CAAA,YAAA;AAC9B,kBAAAC,kBAAA,CAKE,QALF,UAKE,EAAA;AAJH,oBAAAA,kBAAA,CAAK,QAAL,EAAA,UAAK,EAAAD,eAAA,CAAA,MAAA,CAAA,IAAA,CAAA,EAAA,CAAA,YAAA;oBACLC,kBAEoD,CAAA,MAAA,EAAA;AADnD,sBAAA,KAAE,EAAAC,cAAA,CAAA,CAAA,yBAAA,EAC0C,EAAA,+BAAA,EAAA,CAAA,MAAM,CAAC,SAAA,EAAA,CAAA,CAAA;AAAA,qBAAA,EAAAF,eAAA,CAAA,MAAA,CAAA,IAAA,CAAA,EAAA,CAAA,mBAAA;;AAEpD,kBAAAC,kBAAA,CAAiC,MAAjC,EAAA,UAAiC,EAAAD,eAAA,CAAA,MAAA,CAAA,SAAA,CAAA,EAAA,CAAA,YAAA;;AAEjC,gBAAAC,kBAAA,SAAA;kBACDA,kBAGC,CAAA,MAAA,EAAA;AAFA,oBAAA,KAAC,EAAAC,cAAA,CAAA,CAAA,4BAAA,EACD,EAAA,iCAAA,EAAA,MAAA,CAAA,GAAA,EAAA,CAAA,CAAA;oBACA,KAAA,EAAAC,cAAA,CAAA,EAAA,KAAA,EAAA,MAAA,CAAA,OAAA,GAAA,GAAA,EAAA,CAAA;;;;;;;;;;;"}
@@ -23,6 +23,7 @@ import __sfc_main$2 from '../CnStatsBlockWidget/CnStatsBlockWidget.vue.js';
23
23
  import __sfc_main$3 from '../CnStatsBlockWidgetForm/CnStatsBlockWidgetForm.vue.js';
24
24
  import __sfc_main$l from '../CnTabsWidget/CnTabsWidget.vue.js';
25
25
  import __sfc_main$m from '../CnTabsWidgetForm/CnTabsWidgetForm.vue.js';
26
+ import __sfc_main$r from '../CnTeamWorkloadWidget/CnTeamWorkloadWidget.vue.js';
26
27
  import __sfc_main$n from '../CnWeekStripWidget/CnWeekStripWidget.vue.js';
27
28
  import __sfc_main$o from '../CnWeekStripWidgetForm/CnWeekStripWidgetForm.vue.js';
28
29
  import { registerDashboardWidget } from './dashboardWidgetRegistry.js';
@@ -375,6 +376,17 @@ registerDashboardWidget('stacked-bar', {
375
376
  icon: 'ChartBar',
376
377
  });
377
378
 
379
+ // The team today: availability from the Nextcloud user status and each
380
+ // person's open count from the app (DqTeamwachtrij "Team vandaag"). Placed
381
+ // from the manifest: there is no config form yet.
382
+ registerDashboardWidget('team-workload', {
383
+ renderer: __sfc_main$r,
384
+ form: null,
385
+ defaultContent: { source: { url: '', responsePath: '', userField: 'userId', nameField: 'displayName', countField: 'count' } },
386
+ displayName: 'Team workload',
387
+ icon: 'AccountGroup',
388
+ });
389
+
378
390
  /**
379
391
  * Explicit no-op that guarantees this module (and therefore every widget's
380
392
  * self-registration side effect) is evaluated. Now optional: `CnDashboardPage`
@@ -1 +1 @@
1
- {"version":3,"file":"registerDashboardWidgets.js","sources":["../../../../src/components/CnWidgetGrid/registerDashboardWidgets.js"],"sourcesContent":["/**\n * Side-effect aggregator for the cn-widget-library dashboard widget catalog.\n *\n * Importing this module imports every migrated widget's `index.js`, each of\n * which self-registers its `{ renderer, form, defaultContent, displayName,\n * icon }` into `dashboardWidgetRegistry` at load time. The library barrel\n * imports this module so the catalog is populated whenever a consuming app\n * imports `@conduction/nextcloud-vue`; `CnWidgetGrid` then resolves widgets by\n * type key and `CnAddWidgetModal` lists the addable types.\n *\n * The individual widget components are intentionally NOT public exports — they\n * are resolved by their registry type key (the whole point of the registry),\n * so consumers reference them via the manifest `widgetKey`, not by import.\n *\n * @module components/CnWidgetGrid/registerDashboardWidgets\n */\n\nimport CnChartWidget from '../CnChartWidget/CnChartWidget.vue'\nimport CnChartWidgetForm from '../CnChartWidgetForm/CnChartWidgetForm.vue'\nimport CnConversationWidget from '../CnConversationThread/CnConversationWidget.vue'\nimport CnCountdownWidget from '../CnCountdownWidget/CnCountdownWidget.vue'\nimport CnCountdownWidgetForm from '../CnCountdownWidgetForm/CnCountdownWidgetForm.vue'\nimport CnDocumentReviewWidget from '../CnDocumentReviewList/CnDocumentReviewWidget.vue'\nimport CnMapWidget from '../CnMapWidget/CnMapWidget.vue'\nimport CnMapWidgetForm from '../CnMapWidgetForm/CnMapWidgetForm.vue'\nimport CnMarkdownWidget2 from '../CnMarkdownWidget/CnMarkdownWidget.vue'\nimport CnMarkdownWidgetForm2 from '../CnMarkdownWidgetForm/CnMarkdownWidgetForm.vue'\nimport CnNextStepWidget from '../CnNextStepCard/CnNextStepWidget.vue'\nimport CnObjectListWidget2 from '../CnObjectListWidget/CnObjectListWidget.vue'\nimport CnObjectListWidgetForm2 from '../CnObjectListWidgetForm/CnObjectListWidgetForm.vue'\nimport CnRelatedObjectsWidget from '../CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue'\nimport CnRelatedObjectsWidgetForm from '../CnRelatedObjectsWidgetForm/CnRelatedObjectsWidgetForm.vue'\nimport CnSavedViewWidget2 from '../CnSavedViewWidget/CnSavedViewWidget.vue'\nimport CnSavedViewWidgetForm2 from '../CnSavedViewWidgetForm/CnSavedViewWidgetForm.vue'\nimport CnStackedBarWidget from '../CnStackedBarWidget/CnStackedBarWidget.vue'\nimport CnStackedBarWidgetForm from '../CnStackedBarWidgetForm/CnStackedBarWidgetForm.vue'\nimport CnStagesWidget from '../CnStagesWidget/CnStagesWidget.vue'\nimport CnStagesWidgetForm from '../CnStagesWidgetForm/CnStagesWidgetForm.vue'\nimport CnStatsBlockWidget from '../CnStatsBlockWidget/CnStatsBlockWidget.vue'\nimport CnStatsBlockWidgetForm from '../CnStatsBlockWidgetForm/CnStatsBlockWidgetForm.vue'\nimport CnTabsWidget from '../CnTabsWidget/CnTabsWidget.vue'\nimport CnTabsWidgetForm from '../CnTabsWidgetForm/CnTabsWidgetForm.vue'\nimport CnWeekStripWidget from '../CnWeekStripWidget/CnWeekStripWidget.vue'\nimport CnWeekStripWidgetForm from '../CnWeekStripWidgetForm/CnWeekStripWidgetForm.vue'\n// Typed widgets registered with an explicit renderer + config FORM. chart /\n// stats-block render through CnDashboardPage's own isChart()/isStatsBlock()\n// branches and `related` through CnDetailPage's isRelatedWidget() branch — the\n// registry entry exists so the cog editor + Add-widget picker get a form (and,\n// for `related`, the detail-page surface). `table` aliases the object-list\n// renderer/form for legacy manifests using type:'table'.\nimport { registerDashboardWidget } from './dashboardWidgetRegistry.js'\n\nimport '../CnLabelWidget/index.js'\nimport '../CnTextWidget/index.js'\nimport '../CnImageWidget/index.js'\nimport '../CnLinkButtonWidget/index.js'\nimport '../CnDividerWidget/index.js'\nimport '../CnHeaderWidget/index.js'\nimport '../CnQuicklinksWidget/index.js'\nimport '../CnVideoWidget/index.js'\nimport '../CnDashTileWidget/index.js'\nimport '../CnLinksWidget/index.js'\nimport '../CnMenuWidget/index.js'\nimport '../CnContainerWidget/index.js'\nimport '../CnFilesWidget/index.js'\nimport '../CnPeopleWidget/index.js'\nimport '../CnCalendarWidget/index.js'\nimport '../CnNcWidgetWidget/index.js'\nimport '../CnSpendAnalyticsWidget/index.js'\nimport '../CnStatWidget/index.js'\nimport '../CnDeltaWidget/index.js'\nimport '../CnGaugeWidget/index.js'\nimport '../CnFlowRunsWidget/index.js'\nimport '../CnTasksWidget/index.js'\nimport '../CnSectionsWidget/index.js'\nimport '../CnFactsWidget/index.js'\nimport '../CnDeviceFramesWidget/index.js'\nimport '../CnGroupedCardsWidget/index.js'\nimport '../CnChecklistRunWidget/index.js'\nimport '../CnWorkingCalendarWidget/index.js'\nimport '../CnPartyActionsWidget/index.js'\nimport '../CnFieldListWidget/index.js'\nimport '../CnSettingsFormWidget/index.js'\nimport '../CnSwitchRowsWidget/index.js'\nimport '../CnRadioCardsWidget/index.js'\nimport '../CnChipsFieldWidget/index.js'\nimport '../CnToggleTableWidget/index.js'\nimport '../CnChoicePickerWidget/index.js'\nimport '../CnRecordListWidget/index.js'\nimport '../CnSavedViewsWidget/index.js'\nimport '../CnNotepadWidget/index.js'\nimport '../CnObjectDataWidget/dashboardRegistration.js'\nimport '../CnObjectGeoWidget/dashboardRegistration.js'\nimport '../CnWidgetObjectTable/dashboardRegistration.js'\nimport '../CnAuditTrailWidget/dashboardRegistration.js'\nimport '../CnTimelineWidget/dashboardRegistration.js'\nimport '../CnKbSearchWidget/index.js'\nimport '../CnInteractionFormWidget/index.js'\nimport '../CnBannerWidget/index.js'\nimport '../CnWorkspaceFilterWidget/index.js'\n\nregisterDashboardWidget('chart', {\n\trenderer: CnChartWidget,\n\tform: CnChartWidgetForm,\n\tdefaultContent: {\n\t\tchartKind: 'area',\n\t\tdataSource: { register: '', schema: '', filter: {}, bucket: { field: '', interval: 'month', metric: 'count', metricField: '' } },\n\t},\n\tdisplayName: 'Chart',\n\ticon: 'ChartLine',\n})\n\nregisterDashboardWidget('stats-block', {\n\trenderer: CnStatsBlockWidget,\n\tform: CnStatsBlockWidgetForm,\n\tdefaultContent: {\n\t\ttitle: '',\n\t\tprops: { countLabel: '', variant: 'default', iconClass: '' },\n\t\tdataSource: { register: '', schema: '', metric: 'count', field: '', filter: {} },\n\t},\n\tdisplayName: 'Statistic card',\n\ticon: 'ChartBar',\n\t// Card family (docs/architecture/cards-and-widgets.md), like `stat` and\n\t// `delta`: the tile headlines itself with its own title, so the wrapper\n\t// renders no header of its own and would otherwise show the title twice.\n\tcard: true,\n})\n\n// `table` and `object-list` (below) are legacy aliases of `object-table` — same\n// config form (CnObjectListWidgetForm), same job. They stay registered so\n// existing placements keep rendering, but are hidden from every Add-widget\n// picker via a sentinel surface no picker queries (see widgetTypeAllowsSurface):\n// `object-table` is the one to add now. Rendering resolves through\n// getWidgetTypeEntry, which ignores `surfaces`, so hidden ≠ broken.\nregisterDashboardWidget('table', {\n\trenderer: CnObjectListWidget2,\n\tform: CnObjectListWidgetForm2,\n\tdefaultContent: {\n\t\tregister: '',\n\t\tschema: '',\n\t\tfilter: {},\n\t\tsort: { field: '', dir: 'asc' },\n\t\tlimit: 10,\n\t\tcolumns: [],\n\t},\n\tdisplayName: 'Table',\n\ticon: 'ClipboardList',\n\tsurfaces: ['legacy'],\n})\n\n// `object-list` is registered HERE and only here. Registering it from\n// CnObjectListWidget/index.js instead is not enough: package.json declares\n// `sideEffects: [\"**/*.css\"]` (ADR-061 tree-shaking), which lets\n// rollup/webpack legally DROP bare imports of side-effect-free JS modules —\n// the dist bundle shipped without the object-list registration and every\n// manifest `type:\"object-list\"` widget rendered blank. Inline calls in this\n// module survive because consumers import live bindings from the registry.\n//\n// That index.js ALSO self-registered, with a divergent entry (limit 5, no\n// `surfaces`), so both ran in a consumer's build — components/index.js\n// re-exports it, so it was never tree-shaken — and last-registration-wins\n// decided whether this legacy alias stayed hidden from the Add-widget picker.\n// The self-registration is gone; this entry is the one that already won.\nregisterDashboardWidget('object-list', {\n\trenderer: CnObjectListWidget2,\n\tform: CnObjectListWidgetForm2,\n\tdefaultContent: {\n\t\tregister: '',\n\t\tschema: '',\n\t\tfilter: {},\n\t\tsort: { field: '', dir: 'asc' },\n\t\tlimit: 25,\n\t\tcolumns: [],\n\t},\n\tdisplayName: 'Object list',\n\ticon: 'ClipboardList',\n\tsurfaces: ['legacy'],\n})\n\n// `saved-view`: a list driven by one of the reader's saved views. The only data\n// widget a user may add themselves, because the view carries the register and\n// schema a user would otherwise have to name. Registered inline for the same\n// tree-shaking reason as `object-list` above.\n// @spec openspec/changes/a-saved-view-drives-a-widget/tasks.md#task-1.1\nregisterDashboardWidget('saved-view', {\n\trenderer: CnSavedViewWidget2,\n\tform: CnSavedViewWidgetForm2,\n\tdefaultContent: { viewId: '', limit: 10 },\n\tdisplayName: 'Saved view',\n\ticon: 'ClipboardList',\n\tuserAddable: true,\n})\n\n// `markdown`: prose inside a grid page, through the one shared renderer. The\n// only catalog widget a PUBLIC host may mount so far: every other entry is\n// `public: false` until its author opts in deliberately.\n// @spec openspec/changes/widget-registry-public-flag/tasks.md#task-4\nregisterDashboardWidget('markdown', {\n\trenderer: CnMarkdownWidget2,\n\tform: CnMarkdownWidgetForm2,\n\tdefaultContent: { markdown: '' },\n\tdisplayName: 'Markdown',\n\ticon: 'FormatTitle',\n\tpublic: true,\n})\n\nregisterDashboardWidget('related', {\n\trenderer: CnRelatedObjectsWidget,\n\tform: CnRelatedObjectsWidgetForm,\n\tdefaultContent: { title: '', groups: [], hideSingleTabTitle: true, showTotalCount: true },\n\tdisplayName: 'Object relations',\n\ticon: 'FileTreeOutline',\n\tsurfaces: ['detail-page'],\n\townsTitle: true,\n})\n\n// `map` is registered here for the same tree-shaking reason as `object-list`\n// above — a bare `import '../CnMapWidget/index.js'` is a side-effect-free JS module\n// as far as the bundler is concerned, so it may legally be dropped and the widget\n// would silently never appear in Add Widget. CnMapWidget/index.js carried a\n// byte-identical copy of this entry, which only produced a duplicate-registration\n// warning on every consumer's boot; it no longer registers.\nregisterDashboardWidget('map', {\n\trenderer: CnMapWidget,\n\tform: CnMapWidgetForm,\n\tdefaultContent: {\n\t\tregister: '',\n\t\tschema: '',\n\t\t// The Netherlands, roughly — only visible until autoFit frames the objects.\n\t\tcenter: [52.13, 5.29],\n\t\tzoom: 7,\n\t\theight: '400px',\n\t\tpopupField: '',\n\t\tclustering: false,\n\t\tautoFit: true,\n\t\t// A map with no tile layer renders as a grey box. `basemaps` is opt-in and\n\t\t// empty by default (so consumers declaring a `tile` entry in `layers` are\n\t\t// unaffected), which meant a freshly-placed Map widget had NO background at\n\t\t// all. Ship OpenStreetMap — the Nextcloud CSP already allows *.tile.openstreetmap.org.\n\t\tbasemaps: [\n\t\t\t{\n\t\t\t\tname: 'OpenStreetMap',\n\t\t\t\turl: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',\n\t\t\t\tattribution: '© OpenStreetMap contributors',\n\t\t\t\toptions: { maxZoom: 19 },\n\t\t\t},\n\t\t],\n\t\tmarkers: {\n\t\t\tdataSource: { register: '', schema: '' },\n\t\t\tpopupField: '',\n\t\t\tclustering: false,\n\t\t},\n\t},\n\tdisplayName: 'Map',\n\ticon: 'Map',\n})\n\nregisterDashboardWidget('countdown', {\n\trenderer: CnCountdownWidget,\n\tform: CnCountdownWidgetForm,\n\tdefaultContent: {\n\t\tlabel: '',\n\t\tfield: '',\n\t\ticon: 'ClockOutline',\n\t\tthresholds: {},\n\t\tshowDate: true,\n\t},\n\tdisplayName: 'Countdown',\n\ticon: 'ClockOutline',\n\t// Card family: the tile headlines itself, so the wrapper draws no header.\n\tcard: true,\n\t// It reads a date off the BOUND RECORD, which only a detail page has.\n\tsurfaces: ['detail-page'],\n})\n\n// The case surfaces (detail-action-model-and-case-surfaces). Each reads the\n// BOUND RECORD, which only a detail page has, and none has a config form yet,\n// so `form: null` keeps them out of the Add-widget picker: they are placed\n// from the manifest. Registered inline for the same tree-shaking reason as\n// `map` above.\nregisterDashboardWidget('next-step', {\n\trenderer: CnNextStepWidget,\n\tform: null,\n\tdefaultContent: { field: 'status', stages: {} },\n\tdisplayName: 'Next step',\n\ticon: 'CheckCircleOutline',\n\tsurfaces: ['detail-page'],\n\townsTitle: true,\n})\n\nregisterDashboardWidget('document-review', {\n\trenderer: CnDocumentReviewWidget,\n\tform: null,\n\tdefaultContent: { field: 'documents', statusField: 'reviewStatus', statuses: [] },\n\tdisplayName: 'Document review',\n\ticon: 'FileDocumentCheckOutline',\n\tsurfaces: ['detail-page'],\n\townsTitle: true,\n})\n\nregisterDashboardWidget('conversation', {\n\trenderer: CnConversationWidget,\n\tform: null,\n\tdefaultContent: { field: 'messages', endpoint: '' },\n\tdisplayName: 'Conversation',\n\ticon: 'ForumOutline',\n\tsurfaces: ['detail-page'],\n\townsTitle: true,\n})\n\n// The record's stages, where clicking a stage moves the record there.\n// Registered inline for the same tree-shaking reason as `map` above.\nregisterDashboardWidget('stages', {\n\trenderer: CnStagesWidget,\n\tform: CnStagesWidgetForm,\n\tdefaultContent: {\n\t\tcurrentField: 'status',\n\t\torientation: 'horizontal',\n\t\tsize: 'medium',\n\t\tstagesEndpoint: { url: '', path: '' },\n\t\t// The LIFECYCLE, not a record write. OpenRegister decides what is\n\t\t// reachable and re-validates the move; a field write has neither.\n\t\ttransition: { kind: 'lifecycle' },\n\t},\n\tdisplayName: 'Stages',\n\ticon: 'Timeline',\n\t// Card family on the detail grid: a titled wrapper around a self-contained\n\t// strip, like the KPI tiles it usually sits beside.\n\tcard: true,\n\t// It reads and moves the BOUND RECORD, which only a detail page has.\n\tsurfaces: ['detail-page'],\n})\n\nregisterDashboardWidget('tabs', {\n\trenderer: CnTabsWidget,\n\tform: CnTabsWidgetForm,\n\tdefaultContent: {\n\t\ttabs: [],\n\t\tariaLabel: '',\n\t},\n\tdisplayName: 'Tabs',\n\ticon: 'TabPlus',\n\t// Renders OTHER widgets, so CnDetailWidgetHost hands it the surface's\n\t// sibling definitions and the context its children will need.\n\tcontainer: true,\n\t// The strip's labels ARE the titles, so a card header above them would name\n\t// the group twice.\n\townsTitle: true,\n\tsurfaces: ['detail-page'],\n})\n\n// The current week as day columns, with the dated items under each day.\n// Registered inline for the same tree-shaking reason as `map` above.\nregisterDashboardWidget('week-strip', {\n\trenderer: CnWeekStripWidget,\n\tform: CnWeekStripWidgetForm,\n\tdefaultContent: {\n\t\tsource: { register: '', schema: '', filter: {} },\n\t\tdateField: '',\n\t\ttitleField: '',\n\t\tmetaFields: [],\n\t\tdays: 5,\n\t\titemRoute: '',\n\t\temptyText: '',\n\t},\n\tdisplayName: 'Week strip',\n\ticon: 'Calendar',\n})\n\n// One segmented bar with a legend that carries the numbers.\nregisterDashboardWidget('stacked-bar', {\n\trenderer: CnStackedBarWidget,\n\tform: CnStackedBarWidgetForm,\n\tdefaultContent: {\n\t\tsource: { register: '', schema: '', groupBy: '', filter: {} },\n\t\torder: [],\n\t\tlabels: {},\n\t\temptyText: '',\n\t},\n\tdisplayName: 'Stacked bar',\n\ticon: 'ChartBar',\n})\n\n/**\n * Explicit no-op that guarantees this module (and therefore every widget's\n * self-registration side effect) is evaluated. Now optional: `CnDashboardPage`\n * and `CnDetailPage` import this module themselves, and a second call changes\n * nothing because the module body runs once.\n *\n * @return {void}\n */\nexport function registerBuiltinDashboardWidgets() {}\n"],"names":["CnChartWidget","CnChartWidgetForm","CnStatsBlockWidget","CnStatsBlockWidgetForm","CnObjectListWidget2","CnObjectListWidgetForm2","CnSavedViewWidget2","CnSavedViewWidgetForm2","CnMarkdownWidget2","CnMarkdownWidgetForm2","CnRelatedObjectsWidget","CnRelatedObjectsWidgetForm","CnMapWidget","CnMapWidgetForm","CnCountdownWidget","CnCountdownWidgetForm","CnNextStepWidget","CnDocumentReviewWidget","CnConversationWidget","CnStagesWidget","CnStagesWidgetForm","CnTabsWidget","CnTabsWidgetForm","CnWeekStripWidget","CnWeekStripWidgetForm","CnStackedBarWidget","CnStackedBarWidgetForm"],"mappings":"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"}
1
+ {"version":3,"file":"registerDashboardWidgets.js","sources":["../../../../src/components/CnWidgetGrid/registerDashboardWidgets.js"],"sourcesContent":["/**\n * Side-effect aggregator for the cn-widget-library dashboard widget catalog.\n *\n * Importing this module imports every migrated widget's `index.js`, each of\n * which self-registers its `{ renderer, form, defaultContent, displayName,\n * icon }` into `dashboardWidgetRegistry` at load time. The library barrel\n * imports this module so the catalog is populated whenever a consuming app\n * imports `@conduction/nextcloud-vue`; `CnWidgetGrid` then resolves widgets by\n * type key and `CnAddWidgetModal` lists the addable types.\n *\n * The individual widget components are intentionally NOT public exports — they\n * are resolved by their registry type key (the whole point of the registry),\n * so consumers reference them via the manifest `widgetKey`, not by import.\n *\n * @module components/CnWidgetGrid/registerDashboardWidgets\n */\n\nimport CnChartWidget from '../CnChartWidget/CnChartWidget.vue'\nimport CnChartWidgetForm from '../CnChartWidgetForm/CnChartWidgetForm.vue'\nimport CnConversationWidget from '../CnConversationThread/CnConversationWidget.vue'\nimport CnCountdownWidget from '../CnCountdownWidget/CnCountdownWidget.vue'\nimport CnCountdownWidgetForm from '../CnCountdownWidgetForm/CnCountdownWidgetForm.vue'\nimport CnDocumentReviewWidget from '../CnDocumentReviewList/CnDocumentReviewWidget.vue'\nimport CnMapWidget from '../CnMapWidget/CnMapWidget.vue'\nimport CnMapWidgetForm from '../CnMapWidgetForm/CnMapWidgetForm.vue'\nimport CnMarkdownWidget2 from '../CnMarkdownWidget/CnMarkdownWidget.vue'\nimport CnMarkdownWidgetForm2 from '../CnMarkdownWidgetForm/CnMarkdownWidgetForm.vue'\nimport CnNextStepWidget from '../CnNextStepCard/CnNextStepWidget.vue'\nimport CnObjectListWidget2 from '../CnObjectListWidget/CnObjectListWidget.vue'\nimport CnObjectListWidgetForm2 from '../CnObjectListWidgetForm/CnObjectListWidgetForm.vue'\nimport CnRelatedObjectsWidget from '../CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue'\nimport CnRelatedObjectsWidgetForm from '../CnRelatedObjectsWidgetForm/CnRelatedObjectsWidgetForm.vue'\nimport CnSavedViewWidget2 from '../CnSavedViewWidget/CnSavedViewWidget.vue'\nimport CnSavedViewWidgetForm2 from '../CnSavedViewWidgetForm/CnSavedViewWidgetForm.vue'\nimport CnStackedBarWidget from '../CnStackedBarWidget/CnStackedBarWidget.vue'\nimport CnStackedBarWidgetForm from '../CnStackedBarWidgetForm/CnStackedBarWidgetForm.vue'\nimport CnStagesWidget from '../CnStagesWidget/CnStagesWidget.vue'\nimport CnStagesWidgetForm from '../CnStagesWidgetForm/CnStagesWidgetForm.vue'\nimport CnStatsBlockWidget from '../CnStatsBlockWidget/CnStatsBlockWidget.vue'\nimport CnStatsBlockWidgetForm from '../CnStatsBlockWidgetForm/CnStatsBlockWidgetForm.vue'\nimport CnTabsWidget from '../CnTabsWidget/CnTabsWidget.vue'\nimport CnTabsWidgetForm from '../CnTabsWidgetForm/CnTabsWidgetForm.vue'\nimport CnTeamWorkloadWidget from '../CnTeamWorkloadWidget/CnTeamWorkloadWidget.vue'\nimport CnWeekStripWidget from '../CnWeekStripWidget/CnWeekStripWidget.vue'\nimport CnWeekStripWidgetForm from '../CnWeekStripWidgetForm/CnWeekStripWidgetForm.vue'\n// Typed widgets registered with an explicit renderer + config FORM. chart /\n// stats-block render through CnDashboardPage's own isChart()/isStatsBlock()\n// branches and `related` through CnDetailPage's isRelatedWidget() branch — the\n// registry entry exists so the cog editor + Add-widget picker get a form (and,\n// for `related`, the detail-page surface). `table` aliases the object-list\n// renderer/form for legacy manifests using type:'table'.\nimport { registerDashboardWidget } from './dashboardWidgetRegistry.js'\n\nimport '../CnLabelWidget/index.js'\nimport '../CnTextWidget/index.js'\nimport '../CnImageWidget/index.js'\nimport '../CnLinkButtonWidget/index.js'\nimport '../CnDividerWidget/index.js'\nimport '../CnHeaderWidget/index.js'\nimport '../CnQuicklinksWidget/index.js'\nimport '../CnVideoWidget/index.js'\nimport '../CnDashTileWidget/index.js'\nimport '../CnLinksWidget/index.js'\nimport '../CnMenuWidget/index.js'\nimport '../CnContainerWidget/index.js'\nimport '../CnFilesWidget/index.js'\nimport '../CnPeopleWidget/index.js'\nimport '../CnCalendarWidget/index.js'\nimport '../CnNcWidgetWidget/index.js'\nimport '../CnSpendAnalyticsWidget/index.js'\nimport '../CnStatWidget/index.js'\nimport '../CnDeltaWidget/index.js'\nimport '../CnGaugeWidget/index.js'\nimport '../CnFlowRunsWidget/index.js'\nimport '../CnTasksWidget/index.js'\nimport '../CnSectionsWidget/index.js'\nimport '../CnFactsWidget/index.js'\nimport '../CnDeviceFramesWidget/index.js'\nimport '../CnGroupedCardsWidget/index.js'\nimport '../CnChecklistRunWidget/index.js'\nimport '../CnWorkingCalendarWidget/index.js'\nimport '../CnPartyActionsWidget/index.js'\nimport '../CnFieldListWidget/index.js'\nimport '../CnSettingsFormWidget/index.js'\nimport '../CnSwitchRowsWidget/index.js'\nimport '../CnRadioCardsWidget/index.js'\nimport '../CnChipsFieldWidget/index.js'\nimport '../CnToggleTableWidget/index.js'\nimport '../CnChoicePickerWidget/index.js'\nimport '../CnRecordListWidget/index.js'\nimport '../CnSavedViewsWidget/index.js'\nimport '../CnNotepadWidget/index.js'\nimport '../CnObjectDataWidget/dashboardRegistration.js'\nimport '../CnObjectGeoWidget/dashboardRegistration.js'\nimport '../CnWidgetObjectTable/dashboardRegistration.js'\nimport '../CnAuditTrailWidget/dashboardRegistration.js'\nimport '../CnTimelineWidget/dashboardRegistration.js'\nimport '../CnKbSearchWidget/index.js'\nimport '../CnInteractionFormWidget/index.js'\nimport '../CnBannerWidget/index.js'\nimport '../CnWorkspaceFilterWidget/index.js'\n\nregisterDashboardWidget('chart', {\n\trenderer: CnChartWidget,\n\tform: CnChartWidgetForm,\n\tdefaultContent: {\n\t\tchartKind: 'area',\n\t\tdataSource: { register: '', schema: '', filter: {}, bucket: { field: '', interval: 'month', metric: 'count', metricField: '' } },\n\t},\n\tdisplayName: 'Chart',\n\ticon: 'ChartLine',\n})\n\nregisterDashboardWidget('stats-block', {\n\trenderer: CnStatsBlockWidget,\n\tform: CnStatsBlockWidgetForm,\n\tdefaultContent: {\n\t\ttitle: '',\n\t\tprops: { countLabel: '', variant: 'default', iconClass: '' },\n\t\tdataSource: { register: '', schema: '', metric: 'count', field: '', filter: {} },\n\t},\n\tdisplayName: 'Statistic card',\n\ticon: 'ChartBar',\n\t// Card family (docs/architecture/cards-and-widgets.md), like `stat` and\n\t// `delta`: the tile headlines itself with its own title, so the wrapper\n\t// renders no header of its own and would otherwise show the title twice.\n\tcard: true,\n})\n\n// `table` and `object-list` (below) are legacy aliases of `object-table` — same\n// config form (CnObjectListWidgetForm), same job. They stay registered so\n// existing placements keep rendering, but are hidden from every Add-widget\n// picker via a sentinel surface no picker queries (see widgetTypeAllowsSurface):\n// `object-table` is the one to add now. Rendering resolves through\n// getWidgetTypeEntry, which ignores `surfaces`, so hidden ≠ broken.\nregisterDashboardWidget('table', {\n\trenderer: CnObjectListWidget2,\n\tform: CnObjectListWidgetForm2,\n\tdefaultContent: {\n\t\tregister: '',\n\t\tschema: '',\n\t\tfilter: {},\n\t\tsort: { field: '', dir: 'asc' },\n\t\tlimit: 10,\n\t\tcolumns: [],\n\t},\n\tdisplayName: 'Table',\n\ticon: 'ClipboardList',\n\tsurfaces: ['legacy'],\n})\n\n// `object-list` is registered HERE and only here. Registering it from\n// CnObjectListWidget/index.js instead is not enough: package.json declares\n// `sideEffects: [\"**/*.css\"]` (ADR-061 tree-shaking), which lets\n// rollup/webpack legally DROP bare imports of side-effect-free JS modules —\n// the dist bundle shipped without the object-list registration and every\n// manifest `type:\"object-list\"` widget rendered blank. Inline calls in this\n// module survive because consumers import live bindings from the registry.\n//\n// That index.js ALSO self-registered, with a divergent entry (limit 5, no\n// `surfaces`), so both ran in a consumer's build — components/index.js\n// re-exports it, so it was never tree-shaken — and last-registration-wins\n// decided whether this legacy alias stayed hidden from the Add-widget picker.\n// The self-registration is gone; this entry is the one that already won.\nregisterDashboardWidget('object-list', {\n\trenderer: CnObjectListWidget2,\n\tform: CnObjectListWidgetForm2,\n\tdefaultContent: {\n\t\tregister: '',\n\t\tschema: '',\n\t\tfilter: {},\n\t\tsort: { field: '', dir: 'asc' },\n\t\tlimit: 25,\n\t\tcolumns: [],\n\t},\n\tdisplayName: 'Object list',\n\ticon: 'ClipboardList',\n\tsurfaces: ['legacy'],\n})\n\n// `saved-view`: a list driven by one of the reader's saved views. The only data\n// widget a user may add themselves, because the view carries the register and\n// schema a user would otherwise have to name. Registered inline for the same\n// tree-shaking reason as `object-list` above.\n// @spec openspec/changes/a-saved-view-drives-a-widget/tasks.md#task-1.1\nregisterDashboardWidget('saved-view', {\n\trenderer: CnSavedViewWidget2,\n\tform: CnSavedViewWidgetForm2,\n\tdefaultContent: { viewId: '', limit: 10 },\n\tdisplayName: 'Saved view',\n\ticon: 'ClipboardList',\n\tuserAddable: true,\n})\n\n// `markdown`: prose inside a grid page, through the one shared renderer. The\n// only catalog widget a PUBLIC host may mount so far: every other entry is\n// `public: false` until its author opts in deliberately.\n// @spec openspec/changes/widget-registry-public-flag/tasks.md#task-4\nregisterDashboardWidget('markdown', {\n\trenderer: CnMarkdownWidget2,\n\tform: CnMarkdownWidgetForm2,\n\tdefaultContent: { markdown: '' },\n\tdisplayName: 'Markdown',\n\ticon: 'FormatTitle',\n\tpublic: true,\n})\n\nregisterDashboardWidget('related', {\n\trenderer: CnRelatedObjectsWidget,\n\tform: CnRelatedObjectsWidgetForm,\n\tdefaultContent: { title: '', groups: [], hideSingleTabTitle: true, showTotalCount: true },\n\tdisplayName: 'Object relations',\n\ticon: 'FileTreeOutline',\n\tsurfaces: ['detail-page'],\n\townsTitle: true,\n})\n\n// `map` is registered here for the same tree-shaking reason as `object-list`\n// above — a bare `import '../CnMapWidget/index.js'` is a side-effect-free JS module\n// as far as the bundler is concerned, so it may legally be dropped and the widget\n// would silently never appear in Add Widget. CnMapWidget/index.js carried a\n// byte-identical copy of this entry, which only produced a duplicate-registration\n// warning on every consumer's boot; it no longer registers.\nregisterDashboardWidget('map', {\n\trenderer: CnMapWidget,\n\tform: CnMapWidgetForm,\n\tdefaultContent: {\n\t\tregister: '',\n\t\tschema: '',\n\t\t// The Netherlands, roughly — only visible until autoFit frames the objects.\n\t\tcenter: [52.13, 5.29],\n\t\tzoom: 7,\n\t\theight: '400px',\n\t\tpopupField: '',\n\t\tclustering: false,\n\t\tautoFit: true,\n\t\t// A map with no tile layer renders as a grey box. `basemaps` is opt-in and\n\t\t// empty by default (so consumers declaring a `tile` entry in `layers` are\n\t\t// unaffected), which meant a freshly-placed Map widget had NO background at\n\t\t// all. Ship OpenStreetMap — the Nextcloud CSP already allows *.tile.openstreetmap.org.\n\t\tbasemaps: [\n\t\t\t{\n\t\t\t\tname: 'OpenStreetMap',\n\t\t\t\turl: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',\n\t\t\t\tattribution: '© OpenStreetMap contributors',\n\t\t\t\toptions: { maxZoom: 19 },\n\t\t\t},\n\t\t],\n\t\tmarkers: {\n\t\t\tdataSource: { register: '', schema: '' },\n\t\t\tpopupField: '',\n\t\t\tclustering: false,\n\t\t},\n\t},\n\tdisplayName: 'Map',\n\ticon: 'Map',\n})\n\nregisterDashboardWidget('countdown', {\n\trenderer: CnCountdownWidget,\n\tform: CnCountdownWidgetForm,\n\tdefaultContent: {\n\t\tlabel: '',\n\t\tfield: '',\n\t\ticon: 'ClockOutline',\n\t\tthresholds: {},\n\t\tshowDate: true,\n\t},\n\tdisplayName: 'Countdown',\n\ticon: 'ClockOutline',\n\t// Card family: the tile headlines itself, so the wrapper draws no header.\n\tcard: true,\n\t// It reads a date off the BOUND RECORD, which only a detail page has.\n\tsurfaces: ['detail-page'],\n})\n\n// The case surfaces (detail-action-model-and-case-surfaces). Each reads the\n// BOUND RECORD, which only a detail page has, and none has a config form yet,\n// so `form: null` keeps them out of the Add-widget picker: they are placed\n// from the manifest. Registered inline for the same tree-shaking reason as\n// `map` above.\nregisterDashboardWidget('next-step', {\n\trenderer: CnNextStepWidget,\n\tform: null,\n\tdefaultContent: { field: 'status', stages: {} },\n\tdisplayName: 'Next step',\n\ticon: 'CheckCircleOutline',\n\tsurfaces: ['detail-page'],\n\townsTitle: true,\n})\n\nregisterDashboardWidget('document-review', {\n\trenderer: CnDocumentReviewWidget,\n\tform: null,\n\tdefaultContent: { field: 'documents', statusField: 'reviewStatus', statuses: [] },\n\tdisplayName: 'Document review',\n\ticon: 'FileDocumentCheckOutline',\n\tsurfaces: ['detail-page'],\n\townsTitle: true,\n})\n\nregisterDashboardWidget('conversation', {\n\trenderer: CnConversationWidget,\n\tform: null,\n\tdefaultContent: { field: 'messages', endpoint: '' },\n\tdisplayName: 'Conversation',\n\ticon: 'ForumOutline',\n\tsurfaces: ['detail-page'],\n\townsTitle: true,\n})\n\n// The record's stages, where clicking a stage moves the record there.\n// Registered inline for the same tree-shaking reason as `map` above.\nregisterDashboardWidget('stages', {\n\trenderer: CnStagesWidget,\n\tform: CnStagesWidgetForm,\n\tdefaultContent: {\n\t\tcurrentField: 'status',\n\t\torientation: 'horizontal',\n\t\tsize: 'medium',\n\t\tstagesEndpoint: { url: '', path: '' },\n\t\t// The LIFECYCLE, not a record write. OpenRegister decides what is\n\t\t// reachable and re-validates the move; a field write has neither.\n\t\ttransition: { kind: 'lifecycle' },\n\t},\n\tdisplayName: 'Stages',\n\ticon: 'Timeline',\n\t// Card family on the detail grid: a titled wrapper around a self-contained\n\t// strip, like the KPI tiles it usually sits beside.\n\tcard: true,\n\t// It reads and moves the BOUND RECORD, which only a detail page has.\n\tsurfaces: ['detail-page'],\n})\n\nregisterDashboardWidget('tabs', {\n\trenderer: CnTabsWidget,\n\tform: CnTabsWidgetForm,\n\tdefaultContent: {\n\t\ttabs: [],\n\t\tariaLabel: '',\n\t},\n\tdisplayName: 'Tabs',\n\ticon: 'TabPlus',\n\t// Renders OTHER widgets, so CnDetailWidgetHost hands it the surface's\n\t// sibling definitions and the context its children will need.\n\tcontainer: true,\n\t// The strip's labels ARE the titles, so a card header above them would name\n\t// the group twice.\n\townsTitle: true,\n\tsurfaces: ['detail-page'],\n})\n\n// The current week as day columns, with the dated items under each day.\n// Registered inline for the same tree-shaking reason as `map` above.\nregisterDashboardWidget('week-strip', {\n\trenderer: CnWeekStripWidget,\n\tform: CnWeekStripWidgetForm,\n\tdefaultContent: {\n\t\tsource: { register: '', schema: '', filter: {} },\n\t\tdateField: '',\n\t\ttitleField: '',\n\t\tmetaFields: [],\n\t\tdays: 5,\n\t\titemRoute: '',\n\t\temptyText: '',\n\t},\n\tdisplayName: 'Week strip',\n\ticon: 'Calendar',\n})\n\n// One segmented bar with a legend that carries the numbers.\nregisterDashboardWidget('stacked-bar', {\n\trenderer: CnStackedBarWidget,\n\tform: CnStackedBarWidgetForm,\n\tdefaultContent: {\n\t\tsource: { register: '', schema: '', groupBy: '', filter: {} },\n\t\torder: [],\n\t\tlabels: {},\n\t\temptyText: '',\n\t},\n\tdisplayName: 'Stacked bar',\n\ticon: 'ChartBar',\n})\n\n// The team today: availability from the Nextcloud user status and each\n// person's open count from the app (DqTeamwachtrij \"Team vandaag\"). Placed\n// from the manifest: there is no config form yet.\nregisterDashboardWidget('team-workload', {\n\trenderer: CnTeamWorkloadWidget,\n\tform: null,\n\tdefaultContent: { source: { url: '', responsePath: '', userField: 'userId', nameField: 'displayName', countField: 'count' } },\n\tdisplayName: 'Team workload',\n\ticon: 'AccountGroup',\n})\n\n/**\n * Explicit no-op that guarantees this module (and therefore every widget's\n * self-registration side effect) is evaluated. Now optional: `CnDashboardPage`\n * and `CnDetailPage` import this module themselves, and a second call changes\n * nothing because the module body runs once.\n *\n * @return {void}\n */\nexport function registerBuiltinDashboardWidgets() {}\n"],"names":["CnChartWidget","CnChartWidgetForm","CnStatsBlockWidget","CnStatsBlockWidgetForm","CnObjectListWidget2","CnObjectListWidgetForm2","CnSavedViewWidget2","CnSavedViewWidgetForm2","CnMarkdownWidget2","CnMarkdownWidgetForm2","CnRelatedObjectsWidget","CnRelatedObjectsWidgetForm","CnMapWidget","CnMapWidgetForm","CnCountdownWidget","CnCountdownWidgetForm","CnNextStepWidget","CnDocumentReviewWidget","CnConversationWidget","CnStagesWidget","CnStagesWidgetForm","CnTabsWidget","CnTabsWidgetForm","CnWeekStripWidget","CnWeekStripWidgetForm","CnStackedBarWidget","CnStackedBarWidgetForm","CnTeamWorkloadWidget"],"mappings":"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"}
package/dist/esm/index.js CHANGED
@@ -379,6 +379,7 @@ export { default as CnBrandStripe } from './components/CnBrandStripe/CnBrandStri
379
379
  export { default as CnSegmentedControl } from './components/CnSegmentedControl/CnSegmentedControl.vue.js';
380
380
  export { default as CnStackedBarWidget } from './components/CnStackedBarWidget/CnStackedBarWidget.vue.js';
381
381
  export { default as CnStackedBarWidgetForm } from './components/CnStackedBarWidgetForm/CnStackedBarWidgetForm.vue.js';
382
+ export { default as CnTeamWorkloadWidget } from './components/CnTeamWorkloadWidget/CnTeamWorkloadWidget.vue.js';
382
383
  export { default as CnWeekStripWidget } from './components/CnWeekStripWidget/CnWeekStripWidget.vue.js';
383
384
  export { default as CnWeekStripWidgetForm } from './components/CnWeekStripWidgetForm/CnWeekStripWidgetForm.vue.js';
384
385
  export { default as CnFormPage } from './components/CnFormPage/CnFormPage.vue.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1726,7 +1726,23 @@ var translations = {
1726
1726
  On: "On",
1727
1727
  "Select a step on the canvas to see its settings.": "Select a step on the canvas to see its settings.",
1728
1728
  "Show runs": "Show runs",
1729
- "Back to the step settings": "Back to the step settings"
1729
+ "Back to the step settings": "Back to the step settings",
1730
+ Sort: "Sort",
1731
+ Direction: "Direction",
1732
+ Ascending: "Ascending",
1733
+ Descending: "Descending",
1734
+ ascending: "ascending",
1735
+ descending: "descending",
1736
+ "Not sorted": "Not sorted",
1737
+ "Current order: {order}": "Current order: {order}",
1738
+ Soon: "Soon",
1739
+ "{name} (you)": "{name} (you)",
1740
+ "{present} of {total} present": "{present} of {total} present",
1741
+ "Absent today": "Absent today",
1742
+ "{message} until {time}": "{message} until {time}",
1743
+ Away: "Away",
1744
+ Busy: "Busy",
1745
+ "No one in the team": "No one in the team"
1730
1746
  };
1731
1747
  var plurals = {
1732
1748
  "{count} member": [
@@ -1844,6 +1860,10 @@ var plurals = {
1844
1860
  "downloaded %n time": [
1845
1861
  "downloaded %n time",
1846
1862
  "downloaded %n times"
1863
+ ],
1864
+ "{count} open": [
1865
+ "{count} open",
1866
+ "{count} open"
1847
1867
  ]
1848
1868
  };
1849
1869
  var en = {
@@ -1 +1 @@
1
- {"version":3,"file":"en.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"en.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1939,7 +1939,23 @@ var translations = {
1939
1939
  On: "Aan",
1940
1940
  "Select a step on the canvas to see its settings.": "Kies een stap op het canvas om de instellingen te zien.",
1941
1941
  "Show runs": "Uitvoeringen tonen",
1942
- "Back to the step settings": "Terug naar de stapinstellingen"
1942
+ "Back to the step settings": "Terug naar de stapinstellingen",
1943
+ Sort: "Sorteren",
1944
+ Direction: "Richting",
1945
+ Ascending: "Oplopend",
1946
+ Descending: "Aflopend",
1947
+ ascending: "oplopend",
1948
+ descending: "aflopend",
1949
+ "Not sorted": "Niet gesorteerd",
1950
+ "Current order: {order}": "Huidige volgorde: {order}",
1951
+ Soon: "Bijna",
1952
+ "{name} (you)": "{name} (u)",
1953
+ "{present} of {total} present": "{present} van {total} aanwezig",
1954
+ "Absent today": "Vandaag afwezig",
1955
+ "{message} until {time}": "{message} tot {time}",
1956
+ Away: "Afwezig",
1957
+ Busy: "Bezet",
1958
+ "No one in the team": "Niemand in het team"
1943
1959
  };
1944
1960
  var plurals = {
1945
1961
  "{count} member": [
@@ -2057,6 +2073,10 @@ var plurals = {
2057
2073
  "downloaded %n time": [
2058
2074
  "%n keer gedownload",
2059
2075
  "%n keer gedownload"
2076
+ ],
2077
+ "{count} open": [
2078
+ "{count} open",
2079
+ "{count} open"
2060
2080
  ]
2061
2081
  };
2062
2082
  var nl = {
@@ -1 +1 @@
1
- {"version":3,"file":"nl.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"nl.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}