@conduction/nextcloud-vue 2.120.0 → 2.122.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +53 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +546 -523
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/useNamedSource.js +9 -0
- package/dist/esm/components/CnIndexPage/useNamedSource.js.map +1 -1
- package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue3.js +1 -0
- package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue3.js.map +1 -1
- package/dist/esm/components/CnReadinessChecklist/CnReadinessChecklist.vue.js +9 -0
- package/dist/esm/components/CnReadinessChecklist/CnReadinessChecklist.vue.js.map +1 -0
- package/dist/esm/components/CnReadinessChecklist/CnReadinessChecklist.vue2.js +214 -0
- package/dist/esm/components/CnReadinessChecklist/CnReadinessChecklist.vue2.js.map +1 -0
- package/dist/esm/components/CnReadinessChecklist/CnReadinessChecklist.vue3.js +125 -0
- package/dist/esm/components/CnReadinessChecklist/CnReadinessChecklist.vue3.js.map +1 -0
- package/dist/esm/components/CnSchemaRulesWidget/CnSchemaRulesWidget.vue.js +9 -0
- package/dist/esm/components/CnSchemaRulesWidget/CnSchemaRulesWidget.vue.js.map +1 -0
- package/dist/esm/components/CnSchemaRulesWidget/CnSchemaRulesWidget.vue2.js +163 -0
- package/dist/esm/components/CnSchemaRulesWidget/CnSchemaRulesWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnSchemaRulesWidget/CnSchemaRulesWidget.vue3.js +131 -0
- package/dist/esm/components/CnSchemaRulesWidget/CnSchemaRulesWidget.vue3.js.map +1 -0
- package/dist/esm/components/CnSchemaRulesWidget/schemaRules.js +127 -0
- package/dist/esm/components/CnSchemaRulesWidget/schemaRules.js.map +1 -0
- package/dist/esm/components/CnSearchIndexStatus/CnSearchIndexStatus.vue.js +9 -0
- package/dist/esm/components/CnSearchIndexStatus/CnSearchIndexStatus.vue.js.map +1 -0
- package/dist/esm/components/CnSearchIndexStatus/CnSearchIndexStatus.vue2.js +82 -0
- package/dist/esm/components/CnSearchIndexStatus/CnSearchIndexStatus.vue2.js.map +1 -0
- package/dist/esm/components/CnSearchIndexStatus/CnSearchIndexStatus.vue3.js +61 -0
- package/dist/esm/components/CnSearchIndexStatus/CnSearchIndexStatus.vue3.js.map +1 -0
- package/dist/esm/components/CnSearchIndexStatus/searchIndexStatus.js +60 -0
- package/dist/esm/components/CnSearchIndexStatus/searchIndexStatus.js.map +1 -0
- package/dist/esm/components/CnShippedConfigurationSection/CnShippedConfigurationSection.vue.js +10 -0
- package/dist/esm/components/CnShippedConfigurationSection/CnShippedConfigurationSection.vue.js.map +1 -0
- package/dist/esm/components/CnShippedConfigurationSection/CnShippedConfigurationSection.vue2.js +226 -0
- package/dist/esm/components/CnShippedConfigurationSection/CnShippedConfigurationSection.vue2.js.map +1 -0
- package/dist/esm/components/CnShippedConfigurationSection/CnShippedConfigurationSection.vue3.js +126 -0
- package/dist/esm/components/CnShippedConfigurationSection/CnShippedConfigurationSection.vue3.js.map +1 -0
- package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js +42 -32
- package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js.map +1 -1
- package/dist/esm/composables/indexSources.js +116 -16
- package/dist/esm/composables/indexSources.js.map +1 -1
- package/dist/esm/index.js +4 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/l10n/en.json.js +42 -1
- package/dist/esm/l10n/en.json.js.map +1 -1
- package/dist/esm/l10n/nl.json.js +42 -1
- package/dist/esm/l10n/nl.json.js.map +1 -1
- package/dist/esm/library-style.js +1 -1
- package/dist/esm/nextcloud-vue.css +309 -13
- package/dist/esm/utils/libraryWidgetKeys.js +1 -0
- package/dist/esm/utils/libraryWidgetKeys.js.map +1 -1
- package/dist/nextcloud-vue.cjs.js +14136 -12578
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +309 -13
- package/l10n/en.json +42 -1
- package/l10n/nl.json +42 -1
- package/package.json +1 -1
- package/src/components/CnIndexPage/CnIndexPage.vue +74 -3
- package/src/components/CnIndexPage/useNamedSource.js +9 -0
- package/src/components/CnIndexSidebar/CnIndexSidebar.vue +1 -0
- package/src/components/CnReadinessChecklist/CnReadinessChecklist.vue +335 -0
- package/src/components/CnReadinessChecklist/index.js +9 -0
- package/src/components/CnSchemaRulesWidget/CnSchemaRulesWidget.vue +300 -0
- package/src/components/CnSchemaRulesWidget/index.js +10 -0
- package/src/components/CnSchemaRulesWidget/schemaRules.js +123 -0
- package/src/components/CnSearchIndexStatus/CnSearchIndexStatus.vue +160 -0
- package/src/components/CnSearchIndexStatus/index.js +10 -0
- package/src/components/CnSearchIndexStatus/searchIndexStatus.js +56 -0
- package/src/components/CnShippedConfigurationSection/CnShippedConfigurationSection.vue +328 -0
- package/src/components/CnShippedConfigurationSection/index.js +9 -0
- package/src/components/CnWidgetGrid/registerDashboardWidgets.js +10 -0
- package/src/components/index.js +4 -0
- package/src/composables/indexSources.js +116 -16
- package/src/css/index-page.css +7 -0
- package/src/css/look-board-detail.css +27 -0
- package/src/css/look-board-index.css +108 -12
- package/src/css/look-board.css +27 -1
- package/src/index.js +4 -0
- package/src/utils/libraryWidgetKeys.js +1 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CnIndexSidebar.vue3.js","sources":["../../../../src/components/CnIndexSidebar/CnIndexSidebar.vue?vue&type=template&id=7e122bb7&lang.js"],"sourcesContent":["<template>\n\t<NcAppSidebar\n\t\tv-model:open=\"internalOpen\"\n\t\t:name=\"resolvedName\"\n\t\t:title=\"resolvedName\"\n\t\t:subname=\"resolvedSubname\"\n\t\t:active=\"internalActiveTab\"\n\t\t:compact=\"!!resolvedIcon\"\n\t\t@close=\"$emit('update:open', false)\"\n\t\t@update:active=\"onTabChange\">\n\t\t<!-- Schema icon in sidebar header -->\n\t\t<template v-if=\"resolvedIcon\" #header>\n\t\t\t<div class=\"cn-index-sidebar__header-icon\">\n\t\t\t\t<CnIcon :name=\"resolvedIcon\" :size=\"32\" />\n\t\t\t</div>\n\t\t</template>\n\n\t\t<!-- Search Tab -->\n\t\t<NcAppSidebarTab\n\t\t\tid=\"search-tab\"\n\t\t\t:name=\"searchTabLabel\"\n\t\t\t:order=\"1\">\n\t\t\t<template #icon>\n\t\t\t\t<FilterOutline :size=\"20\" />\n\t\t\t</template>\n\n\t\t\t<div class=\"cn-index-sidebar__tab-content\">\n\t\t\t\t<div v-if=\"$slots['search-above']\" class=\"cn-index-sidebar__section\">\n\t\t\t\t\t<slot name=\"search-above\" />\n\t\t\t\t</div>\n\n\t\t\t\t<div class=\"cn-index-sidebar__section\">\n\t\t\t\t\t<NcTextField\n\t\t\t\t\t\t:modelValue=\"searchValue || ''\"\n\t\t\t\t\t\t:placeholder=\"searchPlaceholder\"\n\t\t\t\t\t\t:label=\"searchLabel\"\n\t\t\t\t\t\t@update:modelValue=\"$emit('search', $event)\" />\n\t\t\t\t</div>\n\n\t\t\t\t<!-- Sort (list, card and map views; the table sorts by its headers):\n\t\t\t\t the field, the direction and the order the list has now. -->\n\t\t\t\t<div v-if=\"sortOptions.length > 0\" class=\"cn-index-sidebar__section cn-index-sidebar__sort\" data-testid=\"cn-index-sidebar-sort\">\n\t\t\t\t\t<h3>{{ t('nextcloud-vue', 'Sort') }}</h3>\n\t\t\t\t\t<NcSelect\n\t\t\t\t\t\t:modelValue=\"sortSelected\"\n\t\t\t\t\t\t:options=\"sortOptions\"\n\t\t\t\t\t\tlabel=\"label\"\n\t\t\t\t\t\t:clearable=\"false\"\n\t\t\t\t\t\t:inputLabel=\"t('nextcloud-vue', 'Sort by')\"\n\t\t\t\t\t\t@update:modelValue=\"onSortField\" />\n\t\t\t\t\t<div class=\"cn-index-sidebar__sort-direction\" role=\"radiogroup\" :aria-label=\"t('nextcloud-vue', 'Direction')\">\n\t\t\t\t\t\t<NcCheckboxRadioSwitch\n\t\t\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\t\t\tname=\"cn-index-sidebar-sort-direction\"\n\t\t\t\t\t\t\tvalue=\"asc\"\n\t\t\t\t\t\t\t:modelValue=\"sortDirection\"\n\t\t\t\t\t\t\t:disabled=\"!sortSelected || sortSelected.fixed === true\"\n\t\t\t\t\t\t\t@update:modelValue=\"onSortDirection\">\n\t\t\t\t\t\t\t{{ t('nextcloud-vue', 'Ascending') }}\n\t\t\t\t\t\t</NcCheckboxRadioSwitch>\n\t\t\t\t\t\t<NcCheckboxRadioSwitch\n\t\t\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\t\t\tname=\"cn-index-sidebar-sort-direction\"\n\t\t\t\t\t\t\tvalue=\"desc\"\n\t\t\t\t\t\t\t:modelValue=\"sortDirection\"\n\t\t\t\t\t\t\t:disabled=\"!sortSelected || sortSelected.fixed === true\"\n\t\t\t\t\t\t\t@update:modelValue=\"onSortDirection\">\n\t\t\t\t\t\t\t{{ t('nextcloud-vue', 'Descending') }}\n\t\t\t\t\t\t</NcCheckboxRadioSwitch>\n\t\t\t\t\t</div>\n\t\t\t\t\t<p class=\"cn-index-sidebar__sort-current\" data-testid=\"cn-index-sidebar-sort-current\">\n\t\t\t\t\t\t{{ currentSortText }}\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\n\t\t\t\t<div v-if=\"hasActiveFilters\" class=\"cn-index-sidebar__section\">\n\t\t\t\t\t<NcButton variant=\"tertiary\" @click=\"onClearAll\">\n\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t<FilterRemoveOutline :size=\"20\" />\n\t\t\t\t\t\t</template>\n\t\t\t\t\t\t{{ clearAllLabel }}\n\t\t\t\t\t</NcButton>\n\t\t\t\t</div>\n\n\t\t\t\t<div v-if=\"schemaFilters.length > 0\" class=\"cn-index-sidebar__section\">\n\t\t\t\t\t<h3>{{ filtersLabel }}</h3>\n\t\t\t\t\t<div\n\t\t\t\t\t\tv-for=\"filter in schemaFilters\"\n\t\t\t\t\t\t:key=\"filter.key\"\n\t\t\t\t\t\tclass=\"cn-index-sidebar__filter-group\">\n\t\t\t\t\t\t<div class=\"cn-index-sidebar__filter-header\">\n\t\t\t\t\t\t\t<span class=\"cn-index-sidebar__filter-label\">{{ filter.label }}</span>\n\t\t\t\t\t\t\t<NcPopover v-if=\"filter.description\" popupRole=\"dialog\">\n\t\t\t\t\t\t\t\t<template #trigger>\n\t\t\t\t\t\t\t\t\t<NcButton\n\t\t\t\t\t\t\t\t\t\tvariant=\"tertiary-no-background\"\n\t\t\t\t\t\t\t\t\t\t:aria-label=\"filter.label + ' info'\"\n\t\t\t\t\t\t\t\t\t\tclass=\"cn-index-sidebar__info-btn\">\n\t\t\t\t\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t\t\t\t\t<InformationOutline :size=\"16\" />\n\t\t\t\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t\t\t</NcButton>\n\t\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t\t<p class=\"cn-index-sidebar__filter-description\">\n\t\t\t\t\t\t\t\t\t{{ filter.description }}\n\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t</NcPopover>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<!-- A window, not a list of values: two bounds and a\n\t\t\t\t\t\t preset, emitted as the `{ from, to }` the range\n\t\t\t\t\t\t filters upstream are already spelled in. -->\n\t\t\t\t\t\t<CnDateRangePicker\n\t\t\t\t\t\t\tv-if=\"filter.type === 'date-range'\"\n\t\t\t\t\t\t\tclass=\"cn-index-sidebar__date-range\"\n\t\t\t\t\t\t\t:modelValue=\"getRangeValue(filter)\"\n\t\t\t\t\t\t\t:presets=\"filter.presets || rangePresets\"\n\t\t\t\t\t\t\t:fromLabel=\"filter.fromLabel || fromLabel\"\n\t\t\t\t\t\t\t:toLabel=\"filter.toLabel || toLabel\"\n\t\t\t\t\t\t\t:presetLabel=\"filter.label\"\n\t\t\t\t\t\t\t@update:modelValue=\"onRangeChange(filter.key, $event)\" />\n\t\t\t\t\t\t<NcTextField\n\t\t\t\t\t\t\tv-else-if=\"filter.type === 'text'\"\n\t\t\t\t\t\t\tclass=\"cn-index-sidebar__filter-text\"\n\t\t\t\t\t\t\t:modelValue=\"getTextValue(filter)\"\n\t\t\t\t\t\t\t:label=\"filter.label\"\n\t\t\t\t\t\t\t:placeholder=\"filter.label\"\n\t\t\t\t\t\t\t@update:modelValue=\"onTextChange(filter.key, $event)\" />\n\t\t\t\t\t\t<NcSelect\n\t\t\t\t\t\t\tv-else\n\t\t\t\t\t\t\tclass=\"cn-index-sidebar__select\"\n\t\t\t\t\t\t\t:modelValue=\"getSelectedFilterOptions(filter)\"\n\t\t\t\t\t\t\t:options=\"getFilterOptions(filter)\"\n\t\t\t\t\t\t\t:loading=\"isLoadingOptions(filter)\"\n\t\t\t\t\t\t\tplaceholder=\"Select...\"\n\t\t\t\t\t\t\t:inputLabel=\"filter.label\"\n\t\t\t\t\t\t\t:multiple=\"filter.multiple !== false\"\n\t\t\t\t\t\t\t:keepOpen=\"filter.multiple !== false\"\n\t\t\t\t\t\t\t:clearable=\"true\"\n\t\t\t\t\t\t\t@update:modelValue=\"onFilterChange(filter.key, $event)\" />\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\n\t\t\t\t<slot name=\"search-extra\" />\n\t\t\t</div>\n\t\t</NcAppSidebarTab>\n\n\t\t<!-- Columns Tab -->\n\t\t<NcAppSidebarTab\n\t\t\tid=\"columns-tab\"\n\t\t\t:name=\"columnsTabLabel\"\n\t\t\t:order=\"2\">\n\t\t\t<template #icon>\n\t\t\t\t<ViewColumnOutline :size=\"20\" />\n\t\t\t</template>\n\n\t\t\t<div class=\"cn-index-sidebar__tab-content\">\n\t\t\t\t<div class=\"cn-sidebar-columns\">\n\t\t\t\t\t<h3>{{ columnsHeading }}</h3>\n\t\t\t\t\t<p class=\"cn-sidebar-columns__description\">\n\t\t\t\t\t\t{{ columnsDescription }}\n\t\t\t\t\t</p>\n\n\t\t\t\t\t<!-- Order and pin the visible columns. Drag and the Move buttons\n\t\t\t\t\t call the same method (moveColumn); the table header is not a drag target. -->\n\t\t\t\t\t<div\n\t\t\t\t\t\tv-if=\"personalColumns && orderedVisible.length > 0\"\n\t\t\t\t\t\tclass=\"cn-sidebar-columns__order\"\n\t\t\t\t\t\tdata-testid=\"cn-sidebar-columns-order\">\n\t\t\t\t\t\t<h4>{{ t('nextcloud-vue', 'Order and pin') }}</h4>\n\t\t\t\t\t\t<ol class=\"cn-sidebar-columns__order-list\">\n\t\t\t\t\t\t\t<li\n\t\t\t\t\t\t\t\tv-for=\"(item, index) in orderedVisible\"\n\t\t\t\t\t\t\t\t:key=\"item.key\"\n\t\t\t\t\t\t\t\tclass=\"cn-sidebar-columns__order-item\"\n\t\t\t\t\t\t\t\t:class=\"{ 'cn-sidebar-columns__order-item--pinned': index < pinnedCount }\"\n\t\t\t\t\t\t\t\tdraggable=\"true\"\n\t\t\t\t\t\t\t\tdata-testid=\"cn-sidebar-columns-order-item\"\n\t\t\t\t\t\t\t\t@dragstart=\"dragFrom = index\"\n\t\t\t\t\t\t\t\t@dragover.prevent\n\t\t\t\t\t\t\t\t@drop.prevent=\"onDropColumn(index)\">\n\t\t\t\t\t\t\t\t<DragVertical :size=\"18\" class=\"cn-sidebar-columns__handle\" aria-hidden=\"true\" />\n\t\t\t\t\t\t\t\t<span class=\"cn-sidebar-columns__order-label\">{{ item.label }}</span>\n\t\t\t\t\t\t\t\t<NcButton\n\t\t\t\t\t\t\t\t\tvariant=\"tertiary\"\n\t\t\t\t\t\t\t\t\t:disabled=\"index === 0 || index === pinnedCount\"\n\t\t\t\t\t\t\t\t\t:aria-label=\"t('nextcloud-vue', 'Move {column} up', { column: item.label })\"\n\t\t\t\t\t\t\t\t\tdata-testid=\"cn-sidebar-columns-up\"\n\t\t\t\t\t\t\t\t\t@click=\"moveColumn(index, index - 1)\">\n\t\t\t\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t\t\t\t<ChevronUp :size=\"18\" />\n\t\t\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t\t</NcButton>\n\t\t\t\t\t\t\t\t<NcButton\n\t\t\t\t\t\t\t\t\tvariant=\"tertiary\"\n\t\t\t\t\t\t\t\t\t:disabled=\"index === orderedVisible.length - 1 || index === pinnedCount - 1\"\n\t\t\t\t\t\t\t\t\t:aria-label=\"t('nextcloud-vue', 'Move {column} down', { column: item.label })\"\n\t\t\t\t\t\t\t\t\tdata-testid=\"cn-sidebar-columns-down\"\n\t\t\t\t\t\t\t\t\t@click=\"moveColumn(index, index + 1)\">\n\t\t\t\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t\t\t\t<ChevronDown :size=\"18\" />\n\t\t\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t\t</NcButton>\n\t\t\t\t\t\t\t\t<NcButton\n\t\t\t\t\t\t\t\t\tvariant=\"tertiary\"\n\t\t\t\t\t\t\t\t\t:aria-pressed=\"String(index < pinnedCount)\"\n\t\t\t\t\t\t\t\t\t:aria-label=\"index < pinnedCount ? t('nextcloud-vue', 'Unpin {column}', { column: item.label }) : t('nextcloud-vue', 'Pin {column}', { column: item.label })\"\n\t\t\t\t\t\t\t\t\tdata-testid=\"cn-sidebar-columns-pin\"\n\t\t\t\t\t\t\t\t\t@click=\"togglePin(index)\">\n\t\t\t\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t\t\t\t<Pin v-if=\"index < pinnedCount\" :size=\"18\" />\n\t\t\t\t\t\t\t\t\t\t<PinOutline v-else :size=\"18\" />\n\t\t\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t\t</NcButton>\n\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t</ol>\n\t\t\t\t\t\t<NcButton\n\t\t\t\t\t\t\tvariant=\"tertiary\"\n\t\t\t\t\t\t\tdata-testid=\"cn-sidebar-columns-reset\"\n\t\t\t\t\t\t\t@click=\"$emit('columns-reset')\">\n\t\t\t\t\t\t\t{{ t('nextcloud-vue', 'Reset columns') }}\n\t\t\t\t\t\t</NcButton>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<template v-if=\"allColumns.length > 0 || allGroups.length > 0\">\n\t\t\t\t\t\t<!-- Schema properties group (collapsible) -->\n\t\t\t\t\t\t<div v-if=\"allColumns.length > 0\" class=\"cn-sidebar-columns__group cn-sidebar-columns__group--collapsible\">\n\t\t\t\t\t\t\t<div class=\"cn-sidebar-columns__group-header\" @click=\"propertiesExpanded = !propertiesExpanded\">\n\t\t\t\t\t\t\t\t<ChevronDown v-if=\"propertiesExpanded\" :size=\"20\" />\n\t\t\t\t\t\t\t\t<ChevronRight v-else :size=\"20\" />\n\t\t\t\t\t\t\t\t<h4>{{ resolvedPropertiesLabel }}</h4>\n\t\t\t\t\t\t\t\t<NcCheckboxRadioSwitch\n\t\t\t\t\t\t\t\t\t:modelValue=\"isGroupAllVisible(allColumns)\"\n\t\t\t\t\t\t\t\t\tclass=\"cn-sidebar-columns__select-all\"\n\t\t\t\t\t\t\t\t\t@click.stop\n\t\t\t\t\t\t\t\t\t@update:modelValue=\"toggleGroupAll(allColumns)\">\n\t\t\t\t\t\t\t\t\tAll\n\t\t\t\t\t\t\t\t</NcCheckboxRadioSwitch>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div v-if=\"propertiesExpanded\" class=\"cn-sidebar-columns__group-content\">\n\t\t\t\t\t\t\t\t<NcCheckboxRadioSwitch\n\t\t\t\t\t\t\t\t\tv-for=\"col in allColumns\"\n\t\t\t\t\t\t\t\t\t:key=\"col.key\"\n\t\t\t\t\t\t\t\t\t:modelValue=\"isColumnVisible(col.key)\"\n\t\t\t\t\t\t\t\t\t@update:modelValue=\"toggleColumn(col.key)\">\n\t\t\t\t\t\t\t\t\t{{ col.label }}\n\t\t\t\t\t\t\t\t</NcCheckboxRadioSwitch>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t<!-- Extra column groups (built-in Metadata + external) -->\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tv-for=\"group in allGroups\"\n\t\t\t\t\t\t\t:key=\"group.id\"\n\t\t\t\t\t\t\tclass=\"cn-sidebar-columns__group cn-sidebar-columns__group--collapsible\">\n\t\t\t\t\t\t\t<div class=\"cn-sidebar-columns__group-header\" @click=\"toggleGroup(group.id)\">\n\t\t\t\t\t\t\t\t<ChevronDown v-if=\"expandedGroups[group.id]\" :size=\"20\" />\n\t\t\t\t\t\t\t\t<ChevronRight v-else :size=\"20\" />\n\t\t\t\t\t\t\t\t<h4 :lang=\"langOf(group.label)\">\n\t\t\t\t\t\t\t\t\t{{ shown(group.label) }}\n\t\t\t\t\t\t\t\t</h4>\n\t\t\t\t\t\t\t\t<NcCheckboxRadioSwitch\n\t\t\t\t\t\t\t\t\t:modelValue=\"isGroupAllVisible(group.columns)\"\n\t\t\t\t\t\t\t\t\tclass=\"cn-sidebar-columns__select-all\"\n\t\t\t\t\t\t\t\t\t@click.stop\n\t\t\t\t\t\t\t\t\t@update:modelValue=\"toggleGroupAll(group.columns)\">\n\t\t\t\t\t\t\t\t\tAll\n\t\t\t\t\t\t\t\t</NcCheckboxRadioSwitch>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div v-if=\"expandedGroups[group.id]\" class=\"cn-sidebar-columns__group-content\">\n\t\t\t\t\t\t\t\t<NcCheckboxRadioSwitch\n\t\t\t\t\t\t\t\t\tv-for=\"col in group.columns\"\n\t\t\t\t\t\t\t\t\t:key=\"col.key\"\n\t\t\t\t\t\t\t\t\t:modelValue=\"isColumnVisible(col.key)\"\n\t\t\t\t\t\t\t\t\t@update:modelValue=\"toggleColumn(col.key)\">\n\t\t\t\t\t\t\t\t\t{{ shown(col.label) }}\n\t\t\t\t\t\t\t\t</NcCheckboxRadioSwitch>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</template>\n\n\t\t\t\t\t<p v-else class=\"cn-sidebar-columns__empty\">\n\t\t\t\t\t\tNo columns available. Provide a schema to auto-generate columns.\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\n\t\t\t\t<slot name=\"columns-extra\" />\n\t\t\t</div>\n\t\t</NcAppSidebarTab>\n\n\t\t<!-- Views tab (id filters-tab): the page's saved views (save, list, manage, add to menu). -->\n\t\t<NcAppSidebarTab\n\t\t\tv-if=\"savedViews\"\n\t\t\tid=\"filters-tab\"\n\t\t\t:name=\"t('nextcloud-vue', 'Views')\"\n\t\t\t:order=\"3\">\n\t\t\t<template #icon>\n\t\t\t\t<BookmarkOutline :size=\"20\" />\n\t\t\t</template>\n\n\t\t\t<div class=\"cn-index-sidebar__tab-content\">\n\t\t\t\t<div class=\"cn-index-sidebar__section\">\n\t\t\t\t\t<CnSavedViewsPanel\n\t\t\t\t\t\tv-bind=\"savedViewsPanelProps\"\n\t\t\t\t\t\t@apply=\"onSavedView('apply', $event)\"\n\t\t\t\t\t\t@saveRequest=\"onSavedView('save', null)\"\n\t\t\t\t\t\t@editRequest=\"onSavedView('edit', $event)\"\n\t\t\t\t\t\t@shareRequest=\"onSavedView('share', $event)\"\n\t\t\t\t\t\t@updateRequest=\"onSavedView('update', $event)\"\n\t\t\t\t\t\t@copyRequest=\"onSavedView('copy', $event)\"\n\t\t\t\t\t\t@menuToggle=\"onSavedView('menu', $event)\"\n\t\t\t\t\t\t@deleteRequest=\"onSavedView('delete', $event)\" />\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</NcAppSidebarTab>\n\n\t\t<!-- Extra tabs injected by the consumer -->\n\t\t<slot name=\"tabs\" />\n\t</NcAppSidebar>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcAppSidebar, NcAppSidebarTab, NcButton, NcCheckboxRadioSwitch, NcPopover, NcSelect, NcTextField } from '@nextcloud/vue'\nimport BookmarkOutline from 'vue-material-design-icons/BookmarkOutline.vue'\nimport ChevronDown from 'vue-material-design-icons/ChevronDown.vue'\nimport ChevronRight from 'vue-material-design-icons/ChevronRight.vue'\nimport ChevronUp from 'vue-material-design-icons/ChevronUp.vue'\nimport DragVertical from 'vue-material-design-icons/DragVertical.vue'\nimport FilterOutline from 'vue-material-design-icons/FilterOutline.vue'\nimport FilterRemoveOutline from 'vue-material-design-icons/FilterRemoveOutline.vue'\nimport InformationOutline from 'vue-material-design-icons/InformationOutline.vue'\nimport Pin from 'vue-material-design-icons/Pin.vue'\nimport PinOutline from 'vue-material-design-icons/PinOutline.vue'\nimport ViewColumnOutline from 'vue-material-design-icons/ViewColumnOutline.vue'\nimport CnSavedViewsPanel from '../CnSavedViewsPanel/CnSavedViewsPanel.vue'\nimport { METADATA_COLUMNS } from '../../constants/metadata.js'\nimport { facetOptions } from '../../utils/facets.js'\nimport { labelLang } from '../../utils/manifestTranslate.js'\nimport { columnsFromSchema, filtersFromSchema } from '../../utils/schema.js'\nimport { reverseSortKeys, sameSortKeys } from '../../utils/sortOrder.js'\nimport { CnDateRangePicker, DEFAULT_DATE_RANGE_PRESETS } from '../CnDateRangePicker/index.js'\nimport { CnIcon } from '../CnIcon/index.js'\n\n/**\n * CnIndexSidebar — Reusable NcAppSidebar wrapper with Search + Columns tabs.\n *\n * Designed to be schema-driven: pass a schema and the sidebar auto-generates\n * search filters, column visibility controls, and the standard Metadata group.\n * Title and properties group label are derived from schema.title by default.\n *\n * Must be rendered at the App.vue level as a sibling of NcAppContent.\n * Use provide/inject to connect it to page components.\n *\n * @slot search-above - Content rendered above the search field in the Search tab (e.g. hints, quick actions).\n * @slot search-extra - Content rendered below the search field and filters in the Search tab (e.g. saved searches).\n */\nexport default {\n\tname: 'CnIndexSidebar',\n\n\tcomponents: {\n\t\tNcAppSidebar,\n\t\tNcAppSidebarTab,\n\t\tCnSavedViewsPanel,\n\t\tBookmarkOutline,\n\t\tNcTextField,\n\t\tNcSelect,\n\t\tCnDateRangePicker,\n\t\tNcCheckboxRadioSwitch,\n\t\tNcPopover,\n\t\tNcButton,\n\t\tCnIcon,\n\t\tFilterOutline,\n\t\tFilterRemoveOutline,\n\t\tViewColumnOutline,\n\t\tChevronDown,\n\t\tChevronRight,\n\t\tChevronUp,\n\t\tDragVertical,\n\t\tPin,\n\t\tPinOutline,\n\t\tInformationOutline,\n\t},\n\n\tinject: {\n\t\t/**\n\t\t * Consumer translation function, provided by CnAppRoot as\n\t\t * `cnTranslate: this.translate` (bound to the host app's id). Column and\n\t\t * filter labels come from schema property titles, authored in English as\n\t\t * the canonical source; the visible label is resolved through this\n\t\t * function so it follows the user's language. Defaults to identity when\n\t\t * used standalone (no CnAppRoot ancestor).\n\t\t */\n\t\tcnTranslate: { default: () => (key) => key },\n\t},\n\n\tprops: {\n\t\t/** Sidebar title. Defaults to schema.title when not set. */\n\t\ttitle: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** MDI icon name or emoji. Defaults to schema.icon when not set. */\n\t\ticon: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Schema object for auto-generating filters, columns, and labels */\n\t\tschema: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/** Array of currently visible column keys */\n\t\tvisibleColumns: {\n\t\t\ttype: Array,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Show the Order and pin controls in the Columns tab, and Reset columns.\n\t\t * Off keeps show and hide only.\n\t\t */\n\t\tpersonalColumns: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\n\t\t/** How many of the first visible columns are pinned to the start of the table. */\n\t\tpinnedCount: {\n\t\t\ttype: Number,\n\t\t\tdefault: 0,\n\t\t},\n\n\t\t/**\n\t\t * The orders the Sort section offers, `[{ value, label, keys, fixed? }]`,\n\t\t * each `keys` a `[{ key, order }]` list read as its ascending form. An\n\t\t * option with `fixed: true` is an order of its own (the rows an endpoint\n\t\t * ranks): it is chosen by its value, has no direction, and its keys are\n\t\t * not matched against the current order. Empty draws no Sort section\n\t\t * (the table view sorts by its headers).\n\t\t */\n\t\tsortOptions: {\n\t\t\ttype: Array,\n\t\t\tdefault: () => [],\n\t\t},\n\n\t\t/** The list's current order, `[{ key, order }]`. */\n\t\tcurrentSort: {\n\t\t\ttype: Array,\n\t\t\tdefault: () => [],\n\t\t},\n\n\t\t/**\n\t\t * The Sort option chosen by its value, for an order that is not a list\n\t\t * of sort keys (an option with `fixed: true`, such as one whose rows an\n\t\t * endpoint ranks). Wins over matching `currentSort`.\n\t\t */\n\t\tcurrentSortValue: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Current search term */\n\t\tsearchValue: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Whether sidebar is open */\n\t\topen: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\n\t\t/** Current active facet filters: { fieldName: [values] } */\n\t\tactiveFilters: {\n\t\t\ttype: Object,\n\t\t\tdefault: () => ({}),\n\t\t},\n\n\t\t/** Live facet data from the API: `{ fieldName: { values: [{ value, count?, label? }] } }` */\n\t\tfacetData: {\n\t\t\ttype: Object,\n\t\t\tdefault: () => ({}),\n\t\t},\n\n\t\t/**\n\t\t * Additional column groups beyond schema properties and the built-in Metadata.\n\t\t * Each group: { id: string, label: string, columns: Array<{key, label}>, expanded?: boolean }\n\t\t */\n\t\tcolumnGroups: {\n\t\t\ttype: Array,\n\t\t\tdefault: () => [],\n\t\t},\n\n\t\t/** Whether to include the built-in Metadata column group */\n\t\tshowMetadata: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\n\t\t/** Search input placeholder */\n\t\tsearchPlaceholder: {\n\t\t\ttype: String,\n\t\t\tdefault: () => t('nextcloud-vue', 'Type to search…'),\n\t\t},\n\n\t\t/** Search tab label */\n\t\tsearchTabLabel: {\n\t\t\ttype: String,\n\t\t\tdefault: () => t('nextcloud-vue', 'Search'),\n\t\t},\n\n\t\t/** Columns tab label */\n\t\tcolumnsTabLabel: {\n\t\t\ttype: String,\n\t\t\tdefault: () => t('nextcloud-vue', 'Columns'),\n\t\t},\n\n\t\t/** Search section heading */\n\t\tsearchLabel: {\n\t\t\ttype: String,\n\t\t\tdefault: () => t('nextcloud-vue', 'Search'),\n\t\t},\n\n\t\t/** Filters section heading */\n\t\tfiltersLabel: {\n\t\t\ttype: String,\n\t\t\tdefault: () => t('nextcloud-vue', 'Filters'),\n\t\t},\n\n\t\t/** \"Clear all\" button label, shown when search or a filter is active */\n\t\tclearAllLabel: {\n\t\t\ttype: String,\n\t\t\tdefault: () => t('nextcloud-vue', 'Clear all'),\n\t\t},\n\n\t\t/**\n\t\t * Filter declarations for a page with no schema of its own: `{ name: declaration }`, the same shape a schema property has. Wins over `schema`, and feeds the Search tab only.\n\t\t *\n\t\t * 🔑 A FILTER IS NOT A COLUMN, which is the whole reason this is its\n\t\t * own prop rather than a synthetic `schema`. The schema feeds BOTH\n\t\t * tabs, so a page that declared its filters there would also offer\n\t\t * them in the Columns tab: the toggle would tick and no column would\n\t\t * appear, because the table's columns come from somewhere else\n\t\t * entirely. These reach the Search tab and nothing else.\n\t\t *\n\t\t * @type {object|null}\n\t\t */\n\t\tfilterFields: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/** Start-of-window label on a date-range filter. */\n\t\tfromLabel: {\n\t\t\ttype: String,\n\t\t\tdefault: () => t('nextcloud-vue', 'From'),\n\t\t},\n\n\t\t/** End-of-window label on a date-range filter. */\n\t\ttoLabel: {\n\t\t\ttype: String,\n\t\t\tdefault: () => t('nextcloud-vue', 'To'),\n\t\t},\n\n\t\t/** Columns section heading */\n\t\tcolumnsHeading: {\n\t\t\ttype: String,\n\t\t\tdefault: () => t('nextcloud-vue', 'Column visibility'),\n\t\t},\n\n\t\t/** Columns section description */\n\t\tcolumnsDescription: {\n\t\t\ttype: String,\n\t\t\tdefault: () => t('nextcloud-vue', 'Select which columns to display in the table'),\n\t\t},\n\n\t\t/** Override label for the schema properties group. Defaults to schema.title. */\n\t\tpropertiesGroupLabel: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * ID of the tab that should be active when the sidebar opens.\n\t\t * Built-in IDs are 'search-tab' and 'columns-tab'.\n\t\t * Use the id you set on your custom NcAppSidebarTab for custom tabs.\n\t\t */\n\t\tdefaultTab: {\n\t\t\ttype: String,\n\t\t\tdefault: 'search-tab',\n\t\t},\n\n\t\t/**\n\t\t * Switch to a tab while the sidebar is mounted, e.g. `'filters-tab'`\n\t\t * after a view was saved from the toolbar. Empty leaves the tab alone.\n\t\t */\n\t\tactiveTab: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * The page's saved views, shown in the Filters tab:\n\t\t * `{ views, loading, currentUserId, counts, selectedViewId, maxDepth, menuIds }`\n\t\t * as `CnSavedViewsPanel` takes them. `null` shows no saved views.\n\t\t * Every intent comes back as one `saved-view` event.\n\t\t */\n\t\tsavedViews: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Whether the current user is an admin.\n\t\t * When false, schema properties with `adminOnly: true` are hidden from filters.\n\t\t */\n\t\tuserIsAdmin: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\t},\n\n\temits: ['clear-filters', 'columns-change', 'columns-reorder', 'columns-reset', 'pin-change', 'filter-change', 'saved-view', 'search', 'sort-change', 'tab-change', 'update:open'],\n\n\tdata() {\n\t\treturn {\n\t\t\tinternalOpen: this.open,\n\t\t\tinternalActiveTab: this.defaultTab,\n\t\t\t/** Index of the column being dragged in the Order and pin list, or -1. */\n\t\t\tdragFrom: -1,\n\t\t\tpropertiesExpanded: true,\n\t\t\texpandedGroups: {},\n\t\t\t/**\n\t\t\t * Options loaded for a `reference` filter, keyed by field.\n\t\t\t *\n\t\t\t * A reference picker lists rows from ANOTHER list (the cases a\n\t\t\t * task can hang off, say), and neither the schema nor a facet\n\t\t\t * bucket carries them. Loaded once per field and cached, because\n\t\t\t * the sidebar re-renders on every keystroke in the search box.\n\t\t\t *\n\t\t\t * @type {Record<string, Array<{id: string, label: string}>>}\n\t\t\t */\n\t\t\treferenceOptions: {},\n\t\t\t/** @type {Record<string, boolean>} Which reference loads are in flight. */\n\t\t\treferenceLoading: {},\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/**\n\t\t * The Sort option the current order matches, as declared or reversed.\n\t\t *\n\t\t * @return {{option: object, direction: string}|null} The match, or null.\n\t\t */\n\t\tsortMatch() {\n\t\t\tif (this.currentSortValue) {\n\t\t\t\tconst chosen = this.sortOptions.find((o) => o.value === this.currentSortValue)\n\t\t\t\tif (chosen) {\n\t\t\t\t\treturn { option: chosen, direction: 'asc' }\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst current = Array.isArray(this.currentSort) ? this.currentSort : []\n\t\t\tfor (const option of this.sortOptions) {\n\t\t\t\tif (option.fixed === true) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tconst keys = Array.isArray(option.keys) ? option.keys : []\n\t\t\t\tif (sameSortKeys(keys, current)) {\n\t\t\t\t\treturn { option, direction: 'asc' }\n\t\t\t\t}\n\t\t\t\tif (sameSortKeys(reverseSortKeys(keys), current)) {\n\t\t\t\t\treturn { option, direction: 'desc' }\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null\n\t\t},\n\n\t\t/** @return {object|null} The Sort option shown as chosen. */\n\t\tsortSelected() {\n\t\t\treturn this.sortMatch ? this.sortMatch.option : null\n\t\t},\n\n\t\t/** @return {string} The chosen direction, `asc` or `desc`. */\n\t\tsortDirection() {\n\t\t\treturn this.sortMatch ? this.sortMatch.direction : 'asc'\n\t\t},\n\n\t\t/**\n\t\t * The order the list has now, in words: \"Current order: Created,\n\t\t * descending\", or that it is not sorted.\n\t\t *\n\t\t * @return {string} The sentence.\n\t\t */\n\t\tcurrentSortText() {\n\t\t\tif (this.sortMatch && this.sortMatch.option.fixed === true) {\n\t\t\t\treturn t('nextcloud-vue', 'Current order: {order}', { order: this.sortMatch.option.label })\n\t\t\t}\n\t\t\tconst current = Array.isArray(this.currentSort) ? this.currentSort : []\n\t\t\tif (current.length === 0) {\n\t\t\t\treturn t('nextcloud-vue', 'Not sorted')\n\t\t\t}\n\t\t\tconst labelOf = (key) => {\n\t\t\t\tconst single = this.sortOptions.find((o) => Array.isArray(o.keys) && o.keys.length === 1 && o.keys[0].key === key)\n\t\t\t\treturn single ? single.label : key\n\t\t\t}\n\t\t\tconst order = this.sortMatch && this.sortMatch.option.keys.length > 1\n\t\t\t\t? `${this.sortMatch.option.label}, ${this.sortDirection === 'desc' ? t('nextcloud-vue', 'descending') : t('nextcloud-vue', 'ascending')}`\n\t\t\t\t: current.map((entry) => `${labelOf(entry.key)}, ${entry.order === 'desc' ? t('nextcloud-vue', 'descending') : t('nextcloud-vue', 'ascending')}`).join('; ')\n\t\t\treturn t('nextcloud-vue', 'Current order: {order}', { order })\n\t\t},\n\n\t\t/**\n\t\t * The panel's props, from `savedViews`.\n\t\t *\n\t\t * @return {object}\n\t\t * @spec openspec/changes/saved-views-manage-and-defaults/tasks.md#task-6\n\t\t */\n\t\tsavedViewsPanelProps() {\n\t\t\tconst f = this.savedViews || {}\n\t\t\treturn {\n\t\t\t\tviews: Array.isArray(f.views) ? f.views : [],\n\t\t\t\tloading: f.loading === true,\n\t\t\t\tcurrentUserId: f.currentUserId || '',\n\t\t\t\tcounts: f.counts || null,\n\t\t\t\tselectedViewId: f.selectedViewId || '',\n\t\t\t\tmaxDepth: typeof f.maxDepth === 'number' ? f.maxDepth : 3,\n\t\t\t\tmenuIds: Array.isArray(f.menuIds) ? f.menuIds : null,\n\t\t\t}\n\t\t},\n\n\t\t/** Resolved icon — explicit prop overrides schema.icon */\n\t\tresolvedIcon() {\n\t\t\treturn this.icon || this.schema?.icon || ''\n\t\t},\n\n\t\t/** Sidebar name — schema title, shown as the h2 header */\n\t\tresolvedName() {\n\t\t\tif (this.title) {\n\t\t\t\treturn this.shown(this.title)\n\t\t\t}\n\t\t\treturn this.schema?.title || 'Search'\n\t\t},\n\n\t\t/** Sidebar subname — schema description, shown below the name */\n\t\tresolvedSubname() {\n\t\t\treturn this.schema?.description || ''\n\t\t},\n\n\t\t/** Properties group label — derived from schema.title if not explicitly set */\n\t\tresolvedPropertiesLabel() {\n\t\t\tif (this.propertiesGroupLabel) {\n\t\t\t\treturn this.propertiesGroupLabel\n\t\t\t}\n\t\t\treturn this.schema?.title || 'Properties'\n\t\t},\n\n\t\t/** All available columns from schema */\n\t\tallColumns() {\n\t\t\tif (!this.schema) {\n\t\t\t\treturn []\n\t\t\t}\n\t\t\treturn columnsFromSchema(this.schema, { translate: this.cnTranslate })\n\t\t},\n\n\t\t/** Filter definitions from schema (facetable properties, respecting RBAC) */\n\t\tschemaFilters() {\n\t\t\t// An explicitly declared filter set wins: it is the page saying\n\t\t\t// \"these are the questions\", where a schema only says \"these are\n\t\t\t// the properties\" and the sidebar has to guess which of them are\n\t\t\t// worth asking about.\n\t\t\tif (this.filterFields && Object.keys(this.filterFields).length > 0) {\n\t\t\t\treturn filtersFromSchema(\n\t\t\t\t\t{ properties: this.filterFields },\n\t\t\t\t\t{ isAdmin: this.userIsAdmin, translate: this.cnTranslate },\n\t\t\t\t)\n\t\t\t}\n\t\t\tif (!this.schema) {\n\t\t\t\treturn []\n\t\t\t}\n\t\t\treturn filtersFromSchema(this.schema, { isAdmin: this.userIsAdmin, translate: this.cnTranslate })\n\t\t},\n\n\t\t/** Whether a search term or any facet filter is currently active. */\n\t\thasActiveFilters() {\n\t\t\tif ((this.searchValue || '').length > 0) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\treturn Object.values(this.activeFilters || {}).some((v) => (Array.isArray(v) ? v.length > 0 : !!v))\n\t\t},\n\n\t\t/** Combined column groups: built-in Metadata + external groups */\n\t\tallGroups() {\n\t\t\tconst groups = []\n\t\t\tif (this.showMetadata && this.schema) {\n\t\t\t\tgroups.push({\n\t\t\t\t\tid: 'metadata',\n\t\t\t\t\tlabel: 'Metadata',\n\t\t\t\t\tcolumns: METADATA_COLUMNS,\n\t\t\t\t\texpanded: true,\n\t\t\t\t})\n\t\t\t}\n\t\t\treturn [...groups, ...this.columnGroups]\n\t\t},\n\n\t\t/** Label of each column key, from the schema properties and the groups. */\n\t\tcolumnLabels() {\n\t\t\tconst map = {}\n\t\t\tthis.allColumns.forEach((c) => {\n\t\t\t\tmap[c.key] = c.label\n\t\t\t})\n\t\t\tthis.allGroups.forEach((g) => g.columns.forEach((c) => {\n\t\t\t\tmap[c.key] = c.label\n\t\t\t}))\n\t\t\treturn map\n\t\t},\n\n\t\t/** The visible columns in their order, with labels (all columns when none were chosen). */\n\t\torderedVisible() {\n\t\t\tconst keys = this.visibleColumns === null ? this.allColumnKeys : this.visibleColumns\n\t\t\treturn keys.filter((k) => this.columnLabels[k] !== undefined).map((key) => ({ key, label: this.columnLabels[key] }))\n\t\t},\n\n\t\t/** All column keys across schema properties and all groups */\n\t\tallColumnKeys() {\n\t\t\treturn [\n\t\t\t\t...this.allColumns.map((c) => c.key),\n\t\t\t\t...this.allGroups.flatMap((g) => g.columns.map((c) => c.key)),\n\t\t\t]\n\t\t},\n\n\t\t/**\n\t\t * The presets a date-range filter offers when it declares none.\n\t\t *\n\t\t * Just `custom`. Every shipped preset rolls BACKWARDS from today\n\t\t * (\"Last 30 days\"), and a sidebar filter is as often a forward window\n\t\t * (\"due next week\") as a backward one. Offering a preset that answers\n\t\t * the wrong direction is worse than offering none: it is one click and\n\t\t * it looks deliberate.\n\t\t *\n\t\t * @return {Array<object>} The preset list.\n\t\t */\n\t\trangePresets() {\n\t\t\t// Taken FROM the picker's own list rather than written out again, so\n\t\t\t// the one preset a filter offers carries the same id and the same\n\t\t\t// label as everywhere else it appears.\n\t\t\treturn DEFAULT_DATE_RANGE_PRESETS\n\t\t\t\t.filter((preset) => preset.id === 'custom')\n\t\t\t\t.map((preset) => ({ ...preset }))\n\t\t},\n\t},\n\n\twatch: {\n\t\tactiveTab(tab) {\n\t\t\tif (tab) {\n\t\t\t\tthis.internalActiveTab = tab\n\t\t\t}\n\t\t},\n\n\t\topen(val) {\n\t\t\tthis.internalOpen = val\n\t\t},\n\n\t\tinternalOpen(val) {\n\t\t\tthis.$emit('update:open', val)\n\t\t},\n\n\t\tdefaultTab(val) {\n\t\t\tthis.internalActiveTab = val\n\t\t},\n\n\t\tallGroups: {\n\t\t\timmediate: true,\n\t\t\thandler(groups) {\n\t\t\t\tfor (const group of groups) {\n\t\t\t\t\tif (!(group.id in this.expandedGroups)) {\n\t\t\t\t\t\tthis.expandedGroups[group.id] = group.expanded !== false\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\n\t\t// A reference picker's rows load once the schema naming them arrives,\n\t\t// which on a manifest page is after mount. Watching the FILTERS rather\n\t\t// than calling from `mounted()` covers both orders.\n\t\tschemaFilters: {\n\t\t\timmediate: true,\n\t\t\thandler() {\n\t\t\t\tthis.loadReferenceOptions()\n\t\t\t},\n\t\t},\n\t},\n\n\tmethods: {\n\t\tt,\n\n\t\t/**\n\t\t * A field chosen in the Sort section: its order, in the direction\n\t\t * already chosen.\n\t\t *\n\t\t * @param {object|null} option The chosen option.\n\t\t * @return {void}\n\t\t */\n\t\tonSortField(option) {\n\t\t\tconst chosen = option && this.sortOptions.find((o) => o.value === option.value)\n\t\t\tif (!chosen) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.emitSort(chosen, this.sortDirection)\n\t\t},\n\n\t\t/**\n\t\t * A direction chosen in the Sort section, for the chosen field.\n\t\t *\n\t\t * @param {string} direction `asc` or `desc`.\n\t\t * @return {void}\n\t\t */\n\t\tonSortDirection(direction) {\n\t\t\tif (!this.sortSelected) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.emitSort(this.sortSelected, direction === 'desc' ? 'desc' : 'asc')\n\t\t},\n\n\t\t/**\n\t\t * Emit the order an option stands for in a direction.\n\t\t *\n\t\t * @param {object} option The Sort option.\n\t\t * @param {string} direction `asc` or `desc`.\n\t\t * @return {void}\n\t\t */\n\t\temitSort(option, direction) {\n\t\t\tconst keys = Array.isArray(option.keys) ? option.keys : []\n\t\t\t/**\n\t\t\t * @event sort-change The Sort section chose an order. Payload: `[{ key, order }]`,\n\t\t\t * and the chosen option's value, which names an order that is not keys (`fixed`).\n\t\t\t */\n\t\t\tthis.$emit('sort-change', direction === 'desc' ? reverseSortKeys(keys) : keys.map((k) => ({ key: k.key, order: k.order || 'asc' })), option.value)\n\t\t},\n\n\t\t/**\n\t\t * Hand a saved-view intent to the page.\n\t\t *\n\t\t * @param {'apply'|'save'|'edit'|'share'|'presentation'|'update'|'copy'|'menu'|'delete'} action The intent.\n\t\t * @param {object|null} view The view, or null for save.\n\t\t * @spec openspec/changes/saved-views-manage-and-defaults/tasks.md#task-6\n\t\t */\n\t\tonSavedView(action, view) {\n\t\t\t/**\n\t\t\t * @event saved-view A saved-view intent from the Filters tab. Payload: `{ action, view }`.\n\t\t\t * @type {{action: string, view: (object|null)}}\n\t\t\t */\n\t\t\tthis.$emit('saved-view', { action, view })\n\t\t},\n\n\t\t/**\n\t\t * A manifest label through the injected lookup, or as written.\n\t\t *\n\t\t * @param {string} text The label as written.\n\t\t * @return {string} The label in the user's language.\n\t\t */\n\t\tshown(text) {\n\t\t\treturn typeof this.cnTranslate === 'function' && typeof text === 'string' && text !== '' ? this.cnTranslate(text) : text\n\t\t},\n\n\t\t/**\n\t\t * The `lang` of a label that fell back to its written text in another language.\n\t\t *\n\t\t * @param {string} text The label as written.\n\t\t * @return {string|undefined} The source language, or undefined.\n\t\t */\n\t\tlangOf(text) {\n\t\t\treturn labelLang(this.cnTranslate, text) || undefined\n\t\t},\n\n\t\t/**\n\t\t * Handle tab change from NcAppSidebar\n\t\t *\n\t\t * @param {string} tabId Tab identifier\n\t\t */\n\t\tonTabChange(tabId) {\n\t\t\tthis.internalActiveTab = tabId\n\t\t\tthis.$emit('tab-change', tabId)\n\t\t},\n\n\t\t/**\n\t\t * Check if a column is currently visible\n\t\t *\n\t\t * @param {string} key Column key\n\t\t */\n\t\tisColumnVisible(key) {\n\t\t\tif (this.visibleColumns === null) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\treturn this.visibleColumns.includes(key)\n\t\t},\n\n\t\t/**\n\t\t * Check if all columns in a group are visible\n\t\t *\n\t\t * @param {string[]} columns Array of column keys\n\t\t */\n\t\tisGroupAllVisible(columns) {\n\t\t\treturn columns.every((col) => this.isColumnVisible(col.key))\n\t\t},\n\n\t\t/**\n\t\t * Toggle a single column's visibility\n\t\t *\n\t\t * @param {string} key Column key\n\t\t */\n\t\ttoggleColumn(key) {\n\t\t\tlet newVisible\n\t\t\tif (this.visibleColumns === null) {\n\t\t\t\tnewVisible = this.allColumnKeys.filter((k) => k !== key)\n\t\t\t} else if (this.isColumnVisible(key)) {\n\t\t\t\tnewVisible = this.visibleColumns.filter((k) => k !== key)\n\t\t\t} else {\n\t\t\t\tnewVisible = [...this.visibleColumns, key]\n\t\t\t}\n\t\t\tthis.$emit('columns-change', newVisible)\n\t\t},\n\n\t\t/**\n\t\t * Select or deselect all columns in a group\n\t\t *\n\t\t * @param {string[]} columns Array of column keys\n\t\t */\n\t\ttoggleGroupAll(columns) {\n\t\t\tconst groupKeys = columns.map((c) => c.key)\n\t\t\tconst allVisible = this.isGroupAllVisible(columns)\n\n\t\t\tlet newVisible\n\t\t\tif (this.visibleColumns === null) {\n\t\t\t\t// Currently all visible — deselect this group\n\t\t\t\tnewVisible = this.allColumnKeys.filter((k) => !groupKeys.includes(k))\n\t\t\t} else if (allVisible) {\n\t\t\t\t// All in group visible — deselect them\n\t\t\t\tnewVisible = this.visibleColumns.filter((k) => !groupKeys.includes(k))\n\t\t\t} else {\n\t\t\t\t// Not all visible — select them all\n\t\t\t\tconst current = new Set(this.visibleColumns)\n\t\t\t\tgroupKeys.forEach((k) => current.add(k))\n\t\t\t\tnewVisible = [...current]\n\t\t\t}\n\t\t\tthis.$emit('columns-change', newVisible)\n\t\t},\n\n\t\t/**\n\t\t * Move a visible column to another place in the order. The drag and the\n\t\t * Move buttons both call this. A column stays inside its block: pinned\n\t\t * columns move among the pinned, the rest among the rest.\n\t\t *\n\t\t * @param {number} from Current index.\n\t\t * @param {number} to Target index.\n\t\t * @return {void}\n\t\t */\n\t\tmoveColumn(from, to) {\n\t\t\tconst list = this.orderedVisible.map((c) => c.key)\n\t\t\tconst lo = from < this.pinnedCount ? 0 : this.pinnedCount\n\t\t\tconst hi = from < this.pinnedCount ? this.pinnedCount - 1 : list.length - 1\n\t\t\tconst target = Math.min(hi, Math.max(lo, to))\n\t\t\tif (from < 0 || from >= list.length || target === from) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst [moved] = list.splice(from, 1)\n\t\t\tlist.splice(target, 0, moved)\n\t\t\t/**\n\t\t\t * @event columns-reorder Emitted when the user moves a column. Payload: the visible column keys in their new order.\n\t\t\t * @type {string[]}\n\t\t\t */\n\t\t\tthis.$emit('columns-reorder', list)\n\t\t},\n\n\t\t/**\n\t\t * Dropping a dragged column on another row.\n\t\t *\n\t\t * @param {number} index Index of the row it was dropped on.\n\t\t * @return {void}\n\t\t */\n\t\tonDropColumn(index) {\n\t\t\tconst from = this.dragFrom\n\t\t\tthis.dragFrom = -1\n\t\t\tif (from >= 0) {\n\t\t\t\tthis.moveColumn(from, index)\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Pin a column (it joins the pinned block at the start) or unpin it (it\n\t\t * leaves that block, to the first place after it).\n\t\t *\n\t\t * @param {number} index Index of the column.\n\t\t * @return {void}\n\t\t */\n\t\ttogglePin(index) {\n\t\t\tconst list = this.orderedVisible.map((c) => c.key)\n\t\t\tconst [moved] = list.splice(index, 1)\n\t\t\tlet count = this.pinnedCount\n\t\t\tif (index < count) {\n\t\t\t\tcount -= 1\n\t\t\t\tlist.splice(count, 0, moved)\n\t\t\t} else {\n\t\t\t\tlist.splice(count, 0, moved)\n\t\t\t\tcount += 1\n\t\t\t}\n\t\t\tthis.$emit('columns-reorder', list)\n\t\t\t/**\n\t\t\t * @event pin-change Emitted when a column is pinned or unpinned. Payload: the new number of pinned columns.\n\t\t\t * @type {number}\n\t\t\t */\n\t\t\tthis.$emit('pin-change', count)\n\t\t},\n\n\t\t/**\n\t\t * Toggle a group's expanded state\n\t\t *\n\t\t * @param {string} groupId Filter group identifier\n\t\t */\n\t\ttoggleGroup(groupId) {\n\t\t\tthis.expandedGroups[groupId] = !this.expandedGroups[groupId]\n\t\t},\n\n\t\t/**\n\t\t * Get filter options for a filter definition\n\t\t *\n\t\t * @param {object} filter Filter object\n\t\t */\n\t\tgetFilterOptions(filter) {\n\t\t\tconst live = facetOptions(\n\t\t\t\tthis.facetData[filter.key],\n\t\t\t\t(count) => t('nextcloud-vue', 'No value ({count})', { count }),\n\t\t\t)\n\t\t\tif (live !== null) {\n\t\t\t\treturn live\n\t\t\t}\n\t\t\t// A reference picker's rows come from another list, and neither a\n\t\t\t// schema enum nor a facet bucket can carry them.\n\t\t\tif (filter.type === 'reference') {\n\t\t\t\treturn this.referenceOptions[filter.key] || []\n\t\t\t}\n\t\t\treturn filter.options || []\n\t\t},\n\n\t\t/**\n\t\t * Whether a reference filter is still fetching its rows.\n\t\t *\n\t\t * Shown rather than hidden: an empty picker that is still loading and\n\t\t * one that genuinely has nothing to pick look identical, and only one\n\t\t * of them means the person should stop waiting.\n\t\t *\n\t\t * @param {object} filter The filter definition.\n\t\t *\n\t\t * @return {boolean} True while the load is in flight.\n\t\t */\n\t\tisLoadingOptions(filter) {\n\t\t\treturn this.referenceLoading[filter.key] === true\n\t\t},\n\n\t\t/**\n\t\t * The `{ from, to }` window a date-range filter currently holds.\n\t\t *\n\t\t * @param {object} filter The filter definition.\n\t\t *\n\t\t * @return {object|null} The window, or null when none is set.\n\t\t */\n\t\tgetRangeValue(filter) {\n\t\t\tconst value = this.activeFilters[filter.key]\n\t\t\tif (value && typeof value === 'object' && !Array.isArray(value)) {\n\t\t\t\treturn value\n\t\t\t}\n\t\t\treturn null\n\t\t},\n\n\t\t/**\n\t\t * A date-range filter changed.\n\t\t *\n\t\t * Emitted in the SAME `filter-change` shape every other control uses,\n\t\t * with the window as the payload's `values`, so a consumer has one\n\t\t * event to listen to and not two.\n\t\t *\n\t\t * @param {string} key The filter key.\n\t\t * @param {object|null} window The `{ from, to, preset }` value.\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\tonRangeChange(key, window) {\n\t\t\tconst from = (window && window.from) || ''\n\t\t\tconst to = (window && window.to) || ''\n\t\t\tif (from === '' && to === '') {\n\t\t\t\tthis.$emit('filter-change', { key, values: [] })\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.$emit('filter-change', { key, values: { from, to } })\n\t\t},\n\n\t\t/**\n\t\t * The text a `text` filter currently holds.\n\t\t *\n\t\t * @param {object} filter The filter definition.\n\t\t *\n\t\t * @return {string} The current value.\n\t\t */\n\t\tgetTextValue(filter) {\n\t\t\tconst value = this.activeFilters[filter.key]\n\t\t\tif (Array.isArray(value)) {\n\t\t\t\treturn value.length > 0 ? String(value[0]) : ''\n\t\t\t}\n\t\t\treturn (value === undefined || value === null) ? '' : String(value)\n\t\t},\n\n\t\t/**\n\t\t * A text filter changed.\n\t\t *\n\t\t * @param {string} key The filter key.\n\t\t * @param {string} value The typed value.\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\tonTextChange(key, value) {\n\t\t\tconst text = String(value ?? '').trim()\n\t\t\tthis.$emit('filter-change', { key, values: text === '' ? [] : [text] })\n\t\t},\n\n\t\t/**\n\t\t * Load the rows a `reference` filter picks from.\n\t\t *\n\t\t * Reads `optionsSource` off the schema property:\n\t\t * `{ register, schema, labelField, valueField, limit }`. The VALUE is\n\t\t * the referenced object's uuid, because that is what the server\n\t\t * filters on; the label is only what the person reads.\n\t\t *\n\t\t * Failures are logged and leave the picker empty rather than throwing:\n\t\t * one unreachable list must not take the whole sidebar with it.\n\t\t *\n\t\t * @return {Promise<void>} Resolves when every reference filter settled.\n\t\t */\n\t\tasync loadReferenceOptions() {\n\t\t\tconst pending = this.schemaFilters.filter((filter) => filter.type === 'reference'\n\t\t\t\t&& filter.optionsSource\n\t\t\t\t&& this.referenceOptions[filter.key] === undefined\n\t\t\t\t&& this.referenceLoading[filter.key] !== true)\n\t\t\tif (pending.length === 0) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst [{ default: axios }, { generateUrl }] = await Promise.all([\n\t\t\t\timport('@nextcloud/axios'),\n\t\t\t\timport('@nextcloud/router'),\n\t\t\t])\n\n\t\t\tawait Promise.all(pending.map(async (filter) => {\n\t\t\t\tconst source = filter.optionsSource\n\t\t\t\tif (!source.register || !source.schema) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tthis.referenceLoading = { ...this.referenceLoading, [filter.key]: true }\n\t\t\t\ttry {\n\t\t\t\t\tconst url = generateUrl('/apps/openregister/api/objects/{register}/{schema}', {\n\t\t\t\t\t\tregister: source.register,\n\t\t\t\t\t\tschema: source.schema,\n\t\t\t\t\t})\n\t\t\t\t\tconst response = await axios.get(url, { params: { _limit: source.limit || 200 } })\n\t\t\t\t\tconst rows = response?.data?.results || response?.data || []\n\t\t\t\t\tconst valueField = source.valueField || '@self.uuid'\n\t\t\t\t\tconst labelField = source.labelField || 'title'\n\t\t\t\t\tconst options = rows\n\t\t\t\t\t\t.map((row) => ({\n\t\t\t\t\t\t\tid: this.readPath(row, valueField),\n\t\t\t\t\t\t\tlabel: String(this.readPath(row, labelField) ?? this.readPath(row, valueField) ?? ''),\n\t\t\t\t\t\t}))\n\t\t\t\t\t\t.filter((option) => option.id !== null && option.id !== undefined && option.id !== '')\n\t\t\t\t\t\t.sort((a, b) => a.label.localeCompare(b.label))\n\t\t\t\t\tthis.referenceOptions = { ...this.referenceOptions, [filter.key]: options }\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\t\tconsole.error(`[CnIndexSidebar] the reference filter \"${filter.key}\" could not load its options`, error)\n\t\t\t\t\tthis.referenceOptions = { ...this.referenceOptions, [filter.key]: [] }\n\t\t\t\t} finally {\n\t\t\t\t\tthis.referenceLoading = { ...this.referenceLoading, [filter.key]: false }\n\t\t\t\t}\n\t\t\t}))\n\t\t},\n\n\t\t/**\n\t\t * Read a dotted path off a row (`@self.uuid`, `title`).\n\t\t *\n\t\t * @param {object} row The row.\n\t\t * @param {string} path The dotted path.\n\t\t *\n\t\t * @return {unknown} The value, or undefined.\n\t\t */\n\t\treadPath(row, path) {\n\t\t\treturn String(path).split('.').reduce((acc, part) => ((acc === null || acc === undefined) ? acc : acc[part]), row)\n\t\t},\n\n\t\t/**\n\t\t * Get currently selected options for a filter\n\t\t *\n\t\t * @param {object} filter Filter object\n\t\t */\n\t\tgetSelectedFilterOptions(filter) {\n\t\t\tconst value = this.activeFilters[filter.key]\n\t\t\tif (!value) {\n\t\t\t\treturn []\n\t\t\t}\n\t\t\tconst values = Array.isArray(value) ? value : [value]\n\t\t\tconst options = this.getFilterOptions(filter)\n\t\t\treturn values.map((v) => options.find((o) => o.id === v) || { id: v, label: String(v) })\n\t\t},\n\n\t\t/**\n\t\t * Handle filter select change\n\t\t *\n\t\t * @param {string} key Filter key\n\t\t * @param {Array} selected Selected values\n\t\t */\n\t\tonFilterChange(key, selected) {\n\t\t\t// 🔴 A SINGLE-VALUED SELECT EMITS AN OBJECT, NOT AN ARRAY. NcSelect\n\t\t\t// changes the SHAPE of its payload with `multiple`, and `.map` on\n\t\t\t// the object shape throws inside an event handler, where Vue logs\n\t\t\t// it and carries on: the picker looks inert and the console says\n\t\t\t// why in a place nobody is looking.\n\t\t\tconst chosen = Array.isArray(selected) ? selected : (selected ? [selected] : [])\n\t\t\tconst values = chosen.map((o) => ((o && typeof o === 'object' && 'id' in o) ? o.id : o))\n\t\t\tthis.$emit('filter-change', { key, values })\n\t\t},\n\n\t\t/**\n\t\t * \"Clear all\" click: reset search and every active facet filter in\n\t\t * one shot, so the parent does one fetch instead of one per field.\n\t\t */\n\t\tonClearAll() {\n\t\t\t/**\n\t\t\t * @event clear-filters \"Clear all\" clicked; reset search and every active filter.\n\t\t\t */\n\t\t\tthis.$emit('clear-filters')\n\t\t},\n\t},\n}\n</script>\n\n<!-- Styles in css/index-sidebar.css -->\n"],"names":["_createBlock","_createVNode","_createElementVNode","_openBlock","_createElementBlock","_renderSlot","_toDisplayString","_createTextVNode","_Fragment","_renderList","_normalizeClass","_withModifiers","_mergeProps"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CnIndexSidebar.vue3.js","sources":["../../../../src/components/CnIndexSidebar/CnIndexSidebar.vue?vue&type=template&id=47489466&lang.js"],"sourcesContent":["<template>\n\t<NcAppSidebar\n\t\tv-model:open=\"internalOpen\"\n\t\tclass=\"cn-index-sidebar-panel\"\n\t\t:name=\"resolvedName\"\n\t\t:title=\"resolvedName\"\n\t\t:subname=\"resolvedSubname\"\n\t\t:active=\"internalActiveTab\"\n\t\t:compact=\"!!resolvedIcon\"\n\t\t@close=\"$emit('update:open', false)\"\n\t\t@update:active=\"onTabChange\">\n\t\t<!-- Schema icon in sidebar header -->\n\t\t<template v-if=\"resolvedIcon\" #header>\n\t\t\t<div class=\"cn-index-sidebar__header-icon\">\n\t\t\t\t<CnIcon :name=\"resolvedIcon\" :size=\"32\" />\n\t\t\t</div>\n\t\t</template>\n\n\t\t<!-- Search Tab -->\n\t\t<NcAppSidebarTab\n\t\t\tid=\"search-tab\"\n\t\t\t:name=\"searchTabLabel\"\n\t\t\t:order=\"1\">\n\t\t\t<template #icon>\n\t\t\t\t<FilterOutline :size=\"20\" />\n\t\t\t</template>\n\n\t\t\t<div class=\"cn-index-sidebar__tab-content\">\n\t\t\t\t<div v-if=\"$slots['search-above']\" class=\"cn-index-sidebar__section\">\n\t\t\t\t\t<slot name=\"search-above\" />\n\t\t\t\t</div>\n\n\t\t\t\t<div class=\"cn-index-sidebar__section\">\n\t\t\t\t\t<NcTextField\n\t\t\t\t\t\t:modelValue=\"searchValue || ''\"\n\t\t\t\t\t\t:placeholder=\"searchPlaceholder\"\n\t\t\t\t\t\t:label=\"searchLabel\"\n\t\t\t\t\t\t@update:modelValue=\"$emit('search', $event)\" />\n\t\t\t\t</div>\n\n\t\t\t\t<!-- Sort (list, card and map views; the table sorts by its headers):\n\t\t\t\t the field, the direction and the order the list has now. -->\n\t\t\t\t<div v-if=\"sortOptions.length > 0\" class=\"cn-index-sidebar__section cn-index-sidebar__sort\" data-testid=\"cn-index-sidebar-sort\">\n\t\t\t\t\t<h3>{{ t('nextcloud-vue', 'Sort') }}</h3>\n\t\t\t\t\t<NcSelect\n\t\t\t\t\t\t:modelValue=\"sortSelected\"\n\t\t\t\t\t\t:options=\"sortOptions\"\n\t\t\t\t\t\tlabel=\"label\"\n\t\t\t\t\t\t:clearable=\"false\"\n\t\t\t\t\t\t:inputLabel=\"t('nextcloud-vue', 'Sort by')\"\n\t\t\t\t\t\t@update:modelValue=\"onSortField\" />\n\t\t\t\t\t<div class=\"cn-index-sidebar__sort-direction\" role=\"radiogroup\" :aria-label=\"t('nextcloud-vue', 'Direction')\">\n\t\t\t\t\t\t<NcCheckboxRadioSwitch\n\t\t\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\t\t\tname=\"cn-index-sidebar-sort-direction\"\n\t\t\t\t\t\t\tvalue=\"asc\"\n\t\t\t\t\t\t\t:modelValue=\"sortDirection\"\n\t\t\t\t\t\t\t:disabled=\"!sortSelected || sortSelected.fixed === true\"\n\t\t\t\t\t\t\t@update:modelValue=\"onSortDirection\">\n\t\t\t\t\t\t\t{{ t('nextcloud-vue', 'Ascending') }}\n\t\t\t\t\t\t</NcCheckboxRadioSwitch>\n\t\t\t\t\t\t<NcCheckboxRadioSwitch\n\t\t\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\t\t\tname=\"cn-index-sidebar-sort-direction\"\n\t\t\t\t\t\t\tvalue=\"desc\"\n\t\t\t\t\t\t\t:modelValue=\"sortDirection\"\n\t\t\t\t\t\t\t:disabled=\"!sortSelected || sortSelected.fixed === true\"\n\t\t\t\t\t\t\t@update:modelValue=\"onSortDirection\">\n\t\t\t\t\t\t\t{{ t('nextcloud-vue', 'Descending') }}\n\t\t\t\t\t\t</NcCheckboxRadioSwitch>\n\t\t\t\t\t</div>\n\t\t\t\t\t<p class=\"cn-index-sidebar__sort-current\" data-testid=\"cn-index-sidebar-sort-current\">\n\t\t\t\t\t\t{{ currentSortText }}\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\n\t\t\t\t<div v-if=\"hasActiveFilters\" class=\"cn-index-sidebar__section\">\n\t\t\t\t\t<NcButton variant=\"tertiary\" @click=\"onClearAll\">\n\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t<FilterRemoveOutline :size=\"20\" />\n\t\t\t\t\t\t</template>\n\t\t\t\t\t\t{{ clearAllLabel }}\n\t\t\t\t\t</NcButton>\n\t\t\t\t</div>\n\n\t\t\t\t<div v-if=\"schemaFilters.length > 0\" class=\"cn-index-sidebar__section\">\n\t\t\t\t\t<h3>{{ filtersLabel }}</h3>\n\t\t\t\t\t<div\n\t\t\t\t\t\tv-for=\"filter in schemaFilters\"\n\t\t\t\t\t\t:key=\"filter.key\"\n\t\t\t\t\t\tclass=\"cn-index-sidebar__filter-group\">\n\t\t\t\t\t\t<div class=\"cn-index-sidebar__filter-header\">\n\t\t\t\t\t\t\t<span class=\"cn-index-sidebar__filter-label\">{{ filter.label }}</span>\n\t\t\t\t\t\t\t<NcPopover v-if=\"filter.description\" popupRole=\"dialog\">\n\t\t\t\t\t\t\t\t<template #trigger>\n\t\t\t\t\t\t\t\t\t<NcButton\n\t\t\t\t\t\t\t\t\t\tvariant=\"tertiary-no-background\"\n\t\t\t\t\t\t\t\t\t\t:aria-label=\"filter.label + ' info'\"\n\t\t\t\t\t\t\t\t\t\tclass=\"cn-index-sidebar__info-btn\">\n\t\t\t\t\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t\t\t\t\t<InformationOutline :size=\"16\" />\n\t\t\t\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t\t\t</NcButton>\n\t\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t\t<p class=\"cn-index-sidebar__filter-description\">\n\t\t\t\t\t\t\t\t\t{{ filter.description }}\n\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t</NcPopover>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<!-- A window, not a list of values: two bounds and a\n\t\t\t\t\t\t preset, emitted as the `{ from, to }` the range\n\t\t\t\t\t\t filters upstream are already spelled in. -->\n\t\t\t\t\t\t<CnDateRangePicker\n\t\t\t\t\t\t\tv-if=\"filter.type === 'date-range'\"\n\t\t\t\t\t\t\tclass=\"cn-index-sidebar__date-range\"\n\t\t\t\t\t\t\t:modelValue=\"getRangeValue(filter)\"\n\t\t\t\t\t\t\t:presets=\"filter.presets || rangePresets\"\n\t\t\t\t\t\t\t:fromLabel=\"filter.fromLabel || fromLabel\"\n\t\t\t\t\t\t\t:toLabel=\"filter.toLabel || toLabel\"\n\t\t\t\t\t\t\t:presetLabel=\"filter.label\"\n\t\t\t\t\t\t\t@update:modelValue=\"onRangeChange(filter.key, $event)\" />\n\t\t\t\t\t\t<NcTextField\n\t\t\t\t\t\t\tv-else-if=\"filter.type === 'text'\"\n\t\t\t\t\t\t\tclass=\"cn-index-sidebar__filter-text\"\n\t\t\t\t\t\t\t:modelValue=\"getTextValue(filter)\"\n\t\t\t\t\t\t\t:label=\"filter.label\"\n\t\t\t\t\t\t\t:placeholder=\"filter.label\"\n\t\t\t\t\t\t\t@update:modelValue=\"onTextChange(filter.key, $event)\" />\n\t\t\t\t\t\t<NcSelect\n\t\t\t\t\t\t\tv-else\n\t\t\t\t\t\t\tclass=\"cn-index-sidebar__select\"\n\t\t\t\t\t\t\t:modelValue=\"getSelectedFilterOptions(filter)\"\n\t\t\t\t\t\t\t:options=\"getFilterOptions(filter)\"\n\t\t\t\t\t\t\t:loading=\"isLoadingOptions(filter)\"\n\t\t\t\t\t\t\tplaceholder=\"Select...\"\n\t\t\t\t\t\t\t:inputLabel=\"filter.label\"\n\t\t\t\t\t\t\t:multiple=\"filter.multiple !== false\"\n\t\t\t\t\t\t\t:keepOpen=\"filter.multiple !== false\"\n\t\t\t\t\t\t\t:clearable=\"true\"\n\t\t\t\t\t\t\t@update:modelValue=\"onFilterChange(filter.key, $event)\" />\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\n\t\t\t\t<slot name=\"search-extra\" />\n\t\t\t</div>\n\t\t</NcAppSidebarTab>\n\n\t\t<!-- Columns Tab -->\n\t\t<NcAppSidebarTab\n\t\t\tid=\"columns-tab\"\n\t\t\t:name=\"columnsTabLabel\"\n\t\t\t:order=\"2\">\n\t\t\t<template #icon>\n\t\t\t\t<ViewColumnOutline :size=\"20\" />\n\t\t\t</template>\n\n\t\t\t<div class=\"cn-index-sidebar__tab-content\">\n\t\t\t\t<div class=\"cn-sidebar-columns\">\n\t\t\t\t\t<h3>{{ columnsHeading }}</h3>\n\t\t\t\t\t<p class=\"cn-sidebar-columns__description\">\n\t\t\t\t\t\t{{ columnsDescription }}\n\t\t\t\t\t</p>\n\n\t\t\t\t\t<!-- Order and pin the visible columns. Drag and the Move buttons\n\t\t\t\t\t call the same method (moveColumn); the table header is not a drag target. -->\n\t\t\t\t\t<div\n\t\t\t\t\t\tv-if=\"personalColumns && orderedVisible.length > 0\"\n\t\t\t\t\t\tclass=\"cn-sidebar-columns__order\"\n\t\t\t\t\t\tdata-testid=\"cn-sidebar-columns-order\">\n\t\t\t\t\t\t<h4>{{ t('nextcloud-vue', 'Order and pin') }}</h4>\n\t\t\t\t\t\t<ol class=\"cn-sidebar-columns__order-list\">\n\t\t\t\t\t\t\t<li\n\t\t\t\t\t\t\t\tv-for=\"(item, index) in orderedVisible\"\n\t\t\t\t\t\t\t\t:key=\"item.key\"\n\t\t\t\t\t\t\t\tclass=\"cn-sidebar-columns__order-item\"\n\t\t\t\t\t\t\t\t:class=\"{ 'cn-sidebar-columns__order-item--pinned': index < pinnedCount }\"\n\t\t\t\t\t\t\t\tdraggable=\"true\"\n\t\t\t\t\t\t\t\tdata-testid=\"cn-sidebar-columns-order-item\"\n\t\t\t\t\t\t\t\t@dragstart=\"dragFrom = index\"\n\t\t\t\t\t\t\t\t@dragover.prevent\n\t\t\t\t\t\t\t\t@drop.prevent=\"onDropColumn(index)\">\n\t\t\t\t\t\t\t\t<DragVertical :size=\"18\" class=\"cn-sidebar-columns__handle\" aria-hidden=\"true\" />\n\t\t\t\t\t\t\t\t<span class=\"cn-sidebar-columns__order-label\">{{ item.label }}</span>\n\t\t\t\t\t\t\t\t<NcButton\n\t\t\t\t\t\t\t\t\tvariant=\"tertiary\"\n\t\t\t\t\t\t\t\t\t:disabled=\"index === 0 || index === pinnedCount\"\n\t\t\t\t\t\t\t\t\t:aria-label=\"t('nextcloud-vue', 'Move {column} up', { column: item.label })\"\n\t\t\t\t\t\t\t\t\tdata-testid=\"cn-sidebar-columns-up\"\n\t\t\t\t\t\t\t\t\t@click=\"moveColumn(index, index - 1)\">\n\t\t\t\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t\t\t\t<ChevronUp :size=\"18\" />\n\t\t\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t\t</NcButton>\n\t\t\t\t\t\t\t\t<NcButton\n\t\t\t\t\t\t\t\t\tvariant=\"tertiary\"\n\t\t\t\t\t\t\t\t\t:disabled=\"index === orderedVisible.length - 1 || index === pinnedCount - 1\"\n\t\t\t\t\t\t\t\t\t:aria-label=\"t('nextcloud-vue', 'Move {column} down', { column: item.label })\"\n\t\t\t\t\t\t\t\t\tdata-testid=\"cn-sidebar-columns-down\"\n\t\t\t\t\t\t\t\t\t@click=\"moveColumn(index, index + 1)\">\n\t\t\t\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t\t\t\t<ChevronDown :size=\"18\" />\n\t\t\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t\t</NcButton>\n\t\t\t\t\t\t\t\t<NcButton\n\t\t\t\t\t\t\t\t\tvariant=\"tertiary\"\n\t\t\t\t\t\t\t\t\t:aria-pressed=\"String(index < pinnedCount)\"\n\t\t\t\t\t\t\t\t\t:aria-label=\"index < pinnedCount ? t('nextcloud-vue', 'Unpin {column}', { column: item.label }) : t('nextcloud-vue', 'Pin {column}', { column: item.label })\"\n\t\t\t\t\t\t\t\t\tdata-testid=\"cn-sidebar-columns-pin\"\n\t\t\t\t\t\t\t\t\t@click=\"togglePin(index)\">\n\t\t\t\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t\t\t\t<Pin v-if=\"index < pinnedCount\" :size=\"18\" />\n\t\t\t\t\t\t\t\t\t\t<PinOutline v-else :size=\"18\" />\n\t\t\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t\t</NcButton>\n\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t</ol>\n\t\t\t\t\t\t<NcButton\n\t\t\t\t\t\t\tvariant=\"tertiary\"\n\t\t\t\t\t\t\tdata-testid=\"cn-sidebar-columns-reset\"\n\t\t\t\t\t\t\t@click=\"$emit('columns-reset')\">\n\t\t\t\t\t\t\t{{ t('nextcloud-vue', 'Reset columns') }}\n\t\t\t\t\t\t</NcButton>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<template v-if=\"allColumns.length > 0 || allGroups.length > 0\">\n\t\t\t\t\t\t<!-- Schema properties group (collapsible) -->\n\t\t\t\t\t\t<div v-if=\"allColumns.length > 0\" class=\"cn-sidebar-columns__group cn-sidebar-columns__group--collapsible\">\n\t\t\t\t\t\t\t<div class=\"cn-sidebar-columns__group-header\" @click=\"propertiesExpanded = !propertiesExpanded\">\n\t\t\t\t\t\t\t\t<ChevronDown v-if=\"propertiesExpanded\" :size=\"20\" />\n\t\t\t\t\t\t\t\t<ChevronRight v-else :size=\"20\" />\n\t\t\t\t\t\t\t\t<h4>{{ resolvedPropertiesLabel }}</h4>\n\t\t\t\t\t\t\t\t<NcCheckboxRadioSwitch\n\t\t\t\t\t\t\t\t\t:modelValue=\"isGroupAllVisible(allColumns)\"\n\t\t\t\t\t\t\t\t\tclass=\"cn-sidebar-columns__select-all\"\n\t\t\t\t\t\t\t\t\t@click.stop\n\t\t\t\t\t\t\t\t\t@update:modelValue=\"toggleGroupAll(allColumns)\">\n\t\t\t\t\t\t\t\t\tAll\n\t\t\t\t\t\t\t\t</NcCheckboxRadioSwitch>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div v-if=\"propertiesExpanded\" class=\"cn-sidebar-columns__group-content\">\n\t\t\t\t\t\t\t\t<NcCheckboxRadioSwitch\n\t\t\t\t\t\t\t\t\tv-for=\"col in allColumns\"\n\t\t\t\t\t\t\t\t\t:key=\"col.key\"\n\t\t\t\t\t\t\t\t\t:modelValue=\"isColumnVisible(col.key)\"\n\t\t\t\t\t\t\t\t\t@update:modelValue=\"toggleColumn(col.key)\">\n\t\t\t\t\t\t\t\t\t{{ col.label }}\n\t\t\t\t\t\t\t\t</NcCheckboxRadioSwitch>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t<!-- Extra column groups (built-in Metadata + external) -->\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tv-for=\"group in allGroups\"\n\t\t\t\t\t\t\t:key=\"group.id\"\n\t\t\t\t\t\t\tclass=\"cn-sidebar-columns__group cn-sidebar-columns__group--collapsible\">\n\t\t\t\t\t\t\t<div class=\"cn-sidebar-columns__group-header\" @click=\"toggleGroup(group.id)\">\n\t\t\t\t\t\t\t\t<ChevronDown v-if=\"expandedGroups[group.id]\" :size=\"20\" />\n\t\t\t\t\t\t\t\t<ChevronRight v-else :size=\"20\" />\n\t\t\t\t\t\t\t\t<h4 :lang=\"langOf(group.label)\">\n\t\t\t\t\t\t\t\t\t{{ shown(group.label) }}\n\t\t\t\t\t\t\t\t</h4>\n\t\t\t\t\t\t\t\t<NcCheckboxRadioSwitch\n\t\t\t\t\t\t\t\t\t:modelValue=\"isGroupAllVisible(group.columns)\"\n\t\t\t\t\t\t\t\t\tclass=\"cn-sidebar-columns__select-all\"\n\t\t\t\t\t\t\t\t\t@click.stop\n\t\t\t\t\t\t\t\t\t@update:modelValue=\"toggleGroupAll(group.columns)\">\n\t\t\t\t\t\t\t\t\tAll\n\t\t\t\t\t\t\t\t</NcCheckboxRadioSwitch>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div v-if=\"expandedGroups[group.id]\" class=\"cn-sidebar-columns__group-content\">\n\t\t\t\t\t\t\t\t<NcCheckboxRadioSwitch\n\t\t\t\t\t\t\t\t\tv-for=\"col in group.columns\"\n\t\t\t\t\t\t\t\t\t:key=\"col.key\"\n\t\t\t\t\t\t\t\t\t:modelValue=\"isColumnVisible(col.key)\"\n\t\t\t\t\t\t\t\t\t@update:modelValue=\"toggleColumn(col.key)\">\n\t\t\t\t\t\t\t\t\t{{ shown(col.label) }}\n\t\t\t\t\t\t\t\t</NcCheckboxRadioSwitch>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</template>\n\n\t\t\t\t\t<p v-else class=\"cn-sidebar-columns__empty\">\n\t\t\t\t\t\tNo columns available. Provide a schema to auto-generate columns.\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\n\t\t\t\t<slot name=\"columns-extra\" />\n\t\t\t</div>\n\t\t</NcAppSidebarTab>\n\n\t\t<!-- Views tab (id filters-tab): the page's saved views (save, list, manage, add to menu). -->\n\t\t<NcAppSidebarTab\n\t\t\tv-if=\"savedViews\"\n\t\t\tid=\"filters-tab\"\n\t\t\t:name=\"t('nextcloud-vue', 'Views')\"\n\t\t\t:order=\"3\">\n\t\t\t<template #icon>\n\t\t\t\t<BookmarkOutline :size=\"20\" />\n\t\t\t</template>\n\n\t\t\t<div class=\"cn-index-sidebar__tab-content\">\n\t\t\t\t<div class=\"cn-index-sidebar__section\">\n\t\t\t\t\t<CnSavedViewsPanel\n\t\t\t\t\t\tv-bind=\"savedViewsPanelProps\"\n\t\t\t\t\t\t@apply=\"onSavedView('apply', $event)\"\n\t\t\t\t\t\t@saveRequest=\"onSavedView('save', null)\"\n\t\t\t\t\t\t@editRequest=\"onSavedView('edit', $event)\"\n\t\t\t\t\t\t@shareRequest=\"onSavedView('share', $event)\"\n\t\t\t\t\t\t@updateRequest=\"onSavedView('update', $event)\"\n\t\t\t\t\t\t@copyRequest=\"onSavedView('copy', $event)\"\n\t\t\t\t\t\t@menuToggle=\"onSavedView('menu', $event)\"\n\t\t\t\t\t\t@deleteRequest=\"onSavedView('delete', $event)\" />\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</NcAppSidebarTab>\n\n\t\t<!-- Extra tabs injected by the consumer -->\n\t\t<slot name=\"tabs\" />\n\t</NcAppSidebar>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcAppSidebar, NcAppSidebarTab, NcButton, NcCheckboxRadioSwitch, NcPopover, NcSelect, NcTextField } from '@nextcloud/vue'\nimport BookmarkOutline from 'vue-material-design-icons/BookmarkOutline.vue'\nimport ChevronDown from 'vue-material-design-icons/ChevronDown.vue'\nimport ChevronRight from 'vue-material-design-icons/ChevronRight.vue'\nimport ChevronUp from 'vue-material-design-icons/ChevronUp.vue'\nimport DragVertical from 'vue-material-design-icons/DragVertical.vue'\nimport FilterOutline from 'vue-material-design-icons/FilterOutline.vue'\nimport FilterRemoveOutline from 'vue-material-design-icons/FilterRemoveOutline.vue'\nimport InformationOutline from 'vue-material-design-icons/InformationOutline.vue'\nimport Pin from 'vue-material-design-icons/Pin.vue'\nimport PinOutline from 'vue-material-design-icons/PinOutline.vue'\nimport ViewColumnOutline from 'vue-material-design-icons/ViewColumnOutline.vue'\nimport CnSavedViewsPanel from '../CnSavedViewsPanel/CnSavedViewsPanel.vue'\nimport { METADATA_COLUMNS } from '../../constants/metadata.js'\nimport { facetOptions } from '../../utils/facets.js'\nimport { labelLang } from '../../utils/manifestTranslate.js'\nimport { columnsFromSchema, filtersFromSchema } from '../../utils/schema.js'\nimport { reverseSortKeys, sameSortKeys } from '../../utils/sortOrder.js'\nimport { CnDateRangePicker, DEFAULT_DATE_RANGE_PRESETS } from '../CnDateRangePicker/index.js'\nimport { CnIcon } from '../CnIcon/index.js'\n\n/**\n * CnIndexSidebar — Reusable NcAppSidebar wrapper with Search + Columns tabs.\n *\n * Designed to be schema-driven: pass a schema and the sidebar auto-generates\n * search filters, column visibility controls, and the standard Metadata group.\n * Title and properties group label are derived from schema.title by default.\n *\n * Must be rendered at the App.vue level as a sibling of NcAppContent.\n * Use provide/inject to connect it to page components.\n *\n * @slot search-above - Content rendered above the search field in the Search tab (e.g. hints, quick actions).\n * @slot search-extra - Content rendered below the search field and filters in the Search tab (e.g. saved searches).\n */\nexport default {\n\tname: 'CnIndexSidebar',\n\n\tcomponents: {\n\t\tNcAppSidebar,\n\t\tNcAppSidebarTab,\n\t\tCnSavedViewsPanel,\n\t\tBookmarkOutline,\n\t\tNcTextField,\n\t\tNcSelect,\n\t\tCnDateRangePicker,\n\t\tNcCheckboxRadioSwitch,\n\t\tNcPopover,\n\t\tNcButton,\n\t\tCnIcon,\n\t\tFilterOutline,\n\t\tFilterRemoveOutline,\n\t\tViewColumnOutline,\n\t\tChevronDown,\n\t\tChevronRight,\n\t\tChevronUp,\n\t\tDragVertical,\n\t\tPin,\n\t\tPinOutline,\n\t\tInformationOutline,\n\t},\n\n\tinject: {\n\t\t/**\n\t\t * Consumer translation function, provided by CnAppRoot as\n\t\t * `cnTranslate: this.translate` (bound to the host app's id). Column and\n\t\t * filter labels come from schema property titles, authored in English as\n\t\t * the canonical source; the visible label is resolved through this\n\t\t * function so it follows the user's language. Defaults to identity when\n\t\t * used standalone (no CnAppRoot ancestor).\n\t\t */\n\t\tcnTranslate: { default: () => (key) => key },\n\t},\n\n\tprops: {\n\t\t/** Sidebar title. Defaults to schema.title when not set. */\n\t\ttitle: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** MDI icon name or emoji. Defaults to schema.icon when not set. */\n\t\ticon: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Schema object for auto-generating filters, columns, and labels */\n\t\tschema: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/** Array of currently visible column keys */\n\t\tvisibleColumns: {\n\t\t\ttype: Array,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Show the Order and pin controls in the Columns tab, and Reset columns.\n\t\t * Off keeps show and hide only.\n\t\t */\n\t\tpersonalColumns: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\n\t\t/** How many of the first visible columns are pinned to the start of the table. */\n\t\tpinnedCount: {\n\t\t\ttype: Number,\n\t\t\tdefault: 0,\n\t\t},\n\n\t\t/**\n\t\t * The orders the Sort section offers, `[{ value, label, keys, fixed? }]`,\n\t\t * each `keys` a `[{ key, order }]` list read as its ascending form. An\n\t\t * option with `fixed: true` is an order of its own (the rows an endpoint\n\t\t * ranks): it is chosen by its value, has no direction, and its keys are\n\t\t * not matched against the current order. Empty draws no Sort section\n\t\t * (the table view sorts by its headers).\n\t\t */\n\t\tsortOptions: {\n\t\t\ttype: Array,\n\t\t\tdefault: () => [],\n\t\t},\n\n\t\t/** The list's current order, `[{ key, order }]`. */\n\t\tcurrentSort: {\n\t\t\ttype: Array,\n\t\t\tdefault: () => [],\n\t\t},\n\n\t\t/**\n\t\t * The Sort option chosen by its value, for an order that is not a list\n\t\t * of sort keys (an option with `fixed: true`, such as one whose rows an\n\t\t * endpoint ranks). Wins over matching `currentSort`.\n\t\t */\n\t\tcurrentSortValue: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Current search term */\n\t\tsearchValue: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Whether sidebar is open */\n\t\topen: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\n\t\t/** Current active facet filters: { fieldName: [values] } */\n\t\tactiveFilters: {\n\t\t\ttype: Object,\n\t\t\tdefault: () => ({}),\n\t\t},\n\n\t\t/** Live facet data from the API: `{ fieldName: { values: [{ value, count?, label? }] } }` */\n\t\tfacetData: {\n\t\t\ttype: Object,\n\t\t\tdefault: () => ({}),\n\t\t},\n\n\t\t/**\n\t\t * Additional column groups beyond schema properties and the built-in Metadata.\n\t\t * Each group: { id: string, label: string, columns: Array<{key, label}>, expanded?: boolean }\n\t\t */\n\t\tcolumnGroups: {\n\t\t\ttype: Array,\n\t\t\tdefault: () => [],\n\t\t},\n\n\t\t/** Whether to include the built-in Metadata column group */\n\t\tshowMetadata: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\n\t\t/** Search input placeholder */\n\t\tsearchPlaceholder: {\n\t\t\ttype: String,\n\t\t\tdefault: () => t('nextcloud-vue', 'Type to search…'),\n\t\t},\n\n\t\t/** Search tab label */\n\t\tsearchTabLabel: {\n\t\t\ttype: String,\n\t\t\tdefault: () => t('nextcloud-vue', 'Search'),\n\t\t},\n\n\t\t/** Columns tab label */\n\t\tcolumnsTabLabel: {\n\t\t\ttype: String,\n\t\t\tdefault: () => t('nextcloud-vue', 'Columns'),\n\t\t},\n\n\t\t/** Search section heading */\n\t\tsearchLabel: {\n\t\t\ttype: String,\n\t\t\tdefault: () => t('nextcloud-vue', 'Search'),\n\t\t},\n\n\t\t/** Filters section heading */\n\t\tfiltersLabel: {\n\t\t\ttype: String,\n\t\t\tdefault: () => t('nextcloud-vue', 'Filters'),\n\t\t},\n\n\t\t/** \"Clear all\" button label, shown when search or a filter is active */\n\t\tclearAllLabel: {\n\t\t\ttype: String,\n\t\t\tdefault: () => t('nextcloud-vue', 'Clear all'),\n\t\t},\n\n\t\t/**\n\t\t * Filter declarations for a page with no schema of its own: `{ name: declaration }`, the same shape a schema property has. Wins over `schema`, and feeds the Search tab only.\n\t\t *\n\t\t * 🔑 A FILTER IS NOT A COLUMN, which is the whole reason this is its\n\t\t * own prop rather than a synthetic `schema`. The schema feeds BOTH\n\t\t * tabs, so a page that declared its filters there would also offer\n\t\t * them in the Columns tab: the toggle would tick and no column would\n\t\t * appear, because the table's columns come from somewhere else\n\t\t * entirely. These reach the Search tab and nothing else.\n\t\t *\n\t\t * @type {object|null}\n\t\t */\n\t\tfilterFields: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/** Start-of-window label on a date-range filter. */\n\t\tfromLabel: {\n\t\t\ttype: String,\n\t\t\tdefault: () => t('nextcloud-vue', 'From'),\n\t\t},\n\n\t\t/** End-of-window label on a date-range filter. */\n\t\ttoLabel: {\n\t\t\ttype: String,\n\t\t\tdefault: () => t('nextcloud-vue', 'To'),\n\t\t},\n\n\t\t/** Columns section heading */\n\t\tcolumnsHeading: {\n\t\t\ttype: String,\n\t\t\tdefault: () => t('nextcloud-vue', 'Column visibility'),\n\t\t},\n\n\t\t/** Columns section description */\n\t\tcolumnsDescription: {\n\t\t\ttype: String,\n\t\t\tdefault: () => t('nextcloud-vue', 'Select which columns to display in the table'),\n\t\t},\n\n\t\t/** Override label for the schema properties group. Defaults to schema.title. */\n\t\tpropertiesGroupLabel: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * ID of the tab that should be active when the sidebar opens.\n\t\t * Built-in IDs are 'search-tab' and 'columns-tab'.\n\t\t * Use the id you set on your custom NcAppSidebarTab for custom tabs.\n\t\t */\n\t\tdefaultTab: {\n\t\t\ttype: String,\n\t\t\tdefault: 'search-tab',\n\t\t},\n\n\t\t/**\n\t\t * Switch to a tab while the sidebar is mounted, e.g. `'filters-tab'`\n\t\t * after a view was saved from the toolbar. Empty leaves the tab alone.\n\t\t */\n\t\tactiveTab: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * The page's saved views, shown in the Filters tab:\n\t\t * `{ views, loading, currentUserId, counts, selectedViewId, maxDepth, menuIds }`\n\t\t * as `CnSavedViewsPanel` takes them. `null` shows no saved views.\n\t\t * Every intent comes back as one `saved-view` event.\n\t\t */\n\t\tsavedViews: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Whether the current user is an admin.\n\t\t * When false, schema properties with `adminOnly: true` are hidden from filters.\n\t\t */\n\t\tuserIsAdmin: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\t},\n\n\temits: ['clear-filters', 'columns-change', 'columns-reorder', 'columns-reset', 'pin-change', 'filter-change', 'saved-view', 'search', 'sort-change', 'tab-change', 'update:open'],\n\n\tdata() {\n\t\treturn {\n\t\t\tinternalOpen: this.open,\n\t\t\tinternalActiveTab: this.defaultTab,\n\t\t\t/** Index of the column being dragged in the Order and pin list, or -1. */\n\t\t\tdragFrom: -1,\n\t\t\tpropertiesExpanded: true,\n\t\t\texpandedGroups: {},\n\t\t\t/**\n\t\t\t * Options loaded for a `reference` filter, keyed by field.\n\t\t\t *\n\t\t\t * A reference picker lists rows from ANOTHER list (the cases a\n\t\t\t * task can hang off, say), and neither the schema nor a facet\n\t\t\t * bucket carries them. Loaded once per field and cached, because\n\t\t\t * the sidebar re-renders on every keystroke in the search box.\n\t\t\t *\n\t\t\t * @type {Record<string, Array<{id: string, label: string}>>}\n\t\t\t */\n\t\t\treferenceOptions: {},\n\t\t\t/** @type {Record<string, boolean>} Which reference loads are in flight. */\n\t\t\treferenceLoading: {},\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/**\n\t\t * The Sort option the current order matches, as declared or reversed.\n\t\t *\n\t\t * @return {{option: object, direction: string}|null} The match, or null.\n\t\t */\n\t\tsortMatch() {\n\t\t\tif (this.currentSortValue) {\n\t\t\t\tconst chosen = this.sortOptions.find((o) => o.value === this.currentSortValue)\n\t\t\t\tif (chosen) {\n\t\t\t\t\treturn { option: chosen, direction: 'asc' }\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst current = Array.isArray(this.currentSort) ? this.currentSort : []\n\t\t\tfor (const option of this.sortOptions) {\n\t\t\t\tif (option.fixed === true) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tconst keys = Array.isArray(option.keys) ? option.keys : []\n\t\t\t\tif (sameSortKeys(keys, current)) {\n\t\t\t\t\treturn { option, direction: 'asc' }\n\t\t\t\t}\n\t\t\t\tif (sameSortKeys(reverseSortKeys(keys), current)) {\n\t\t\t\t\treturn { option, direction: 'desc' }\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null\n\t\t},\n\n\t\t/** @return {object|null} The Sort option shown as chosen. */\n\t\tsortSelected() {\n\t\t\treturn this.sortMatch ? this.sortMatch.option : null\n\t\t},\n\n\t\t/** @return {string} The chosen direction, `asc` or `desc`. */\n\t\tsortDirection() {\n\t\t\treturn this.sortMatch ? this.sortMatch.direction : 'asc'\n\t\t},\n\n\t\t/**\n\t\t * The order the list has now, in words: \"Current order: Created,\n\t\t * descending\", or that it is not sorted.\n\t\t *\n\t\t * @return {string} The sentence.\n\t\t */\n\t\tcurrentSortText() {\n\t\t\tif (this.sortMatch && this.sortMatch.option.fixed === true) {\n\t\t\t\treturn t('nextcloud-vue', 'Current order: {order}', { order: this.sortMatch.option.label })\n\t\t\t}\n\t\t\tconst current = Array.isArray(this.currentSort) ? this.currentSort : []\n\t\t\tif (current.length === 0) {\n\t\t\t\treturn t('nextcloud-vue', 'Not sorted')\n\t\t\t}\n\t\t\tconst labelOf = (key) => {\n\t\t\t\tconst single = this.sortOptions.find((o) => Array.isArray(o.keys) && o.keys.length === 1 && o.keys[0].key === key)\n\t\t\t\treturn single ? single.label : key\n\t\t\t}\n\t\t\tconst order = this.sortMatch && this.sortMatch.option.keys.length > 1\n\t\t\t\t? `${this.sortMatch.option.label}, ${this.sortDirection === 'desc' ? t('nextcloud-vue', 'descending') : t('nextcloud-vue', 'ascending')}`\n\t\t\t\t: current.map((entry) => `${labelOf(entry.key)}, ${entry.order === 'desc' ? t('nextcloud-vue', 'descending') : t('nextcloud-vue', 'ascending')}`).join('; ')\n\t\t\treturn t('nextcloud-vue', 'Current order: {order}', { order })\n\t\t},\n\n\t\t/**\n\t\t * The panel's props, from `savedViews`.\n\t\t *\n\t\t * @return {object}\n\t\t * @spec openspec/changes/saved-views-manage-and-defaults/tasks.md#task-6\n\t\t */\n\t\tsavedViewsPanelProps() {\n\t\t\tconst f = this.savedViews || {}\n\t\t\treturn {\n\t\t\t\tviews: Array.isArray(f.views) ? f.views : [],\n\t\t\t\tloading: f.loading === true,\n\t\t\t\tcurrentUserId: f.currentUserId || '',\n\t\t\t\tcounts: f.counts || null,\n\t\t\t\tselectedViewId: f.selectedViewId || '',\n\t\t\t\tmaxDepth: typeof f.maxDepth === 'number' ? f.maxDepth : 3,\n\t\t\t\tmenuIds: Array.isArray(f.menuIds) ? f.menuIds : null,\n\t\t\t}\n\t\t},\n\n\t\t/** Resolved icon — explicit prop overrides schema.icon */\n\t\tresolvedIcon() {\n\t\t\treturn this.icon || this.schema?.icon || ''\n\t\t},\n\n\t\t/** Sidebar name — schema title, shown as the h2 header */\n\t\tresolvedName() {\n\t\t\tif (this.title) {\n\t\t\t\treturn this.shown(this.title)\n\t\t\t}\n\t\t\treturn this.schema?.title || 'Search'\n\t\t},\n\n\t\t/** Sidebar subname — schema description, shown below the name */\n\t\tresolvedSubname() {\n\t\t\treturn this.schema?.description || ''\n\t\t},\n\n\t\t/** Properties group label — derived from schema.title if not explicitly set */\n\t\tresolvedPropertiesLabel() {\n\t\t\tif (this.propertiesGroupLabel) {\n\t\t\t\treturn this.propertiesGroupLabel\n\t\t\t}\n\t\t\treturn this.schema?.title || 'Properties'\n\t\t},\n\n\t\t/** All available columns from schema */\n\t\tallColumns() {\n\t\t\tif (!this.schema) {\n\t\t\t\treturn []\n\t\t\t}\n\t\t\treturn columnsFromSchema(this.schema, { translate: this.cnTranslate })\n\t\t},\n\n\t\t/** Filter definitions from schema (facetable properties, respecting RBAC) */\n\t\tschemaFilters() {\n\t\t\t// An explicitly declared filter set wins: it is the page saying\n\t\t\t// \"these are the questions\", where a schema only says \"these are\n\t\t\t// the properties\" and the sidebar has to guess which of them are\n\t\t\t// worth asking about.\n\t\t\tif (this.filterFields && Object.keys(this.filterFields).length > 0) {\n\t\t\t\treturn filtersFromSchema(\n\t\t\t\t\t{ properties: this.filterFields },\n\t\t\t\t\t{ isAdmin: this.userIsAdmin, translate: this.cnTranslate },\n\t\t\t\t)\n\t\t\t}\n\t\t\tif (!this.schema) {\n\t\t\t\treturn []\n\t\t\t}\n\t\t\treturn filtersFromSchema(this.schema, { isAdmin: this.userIsAdmin, translate: this.cnTranslate })\n\t\t},\n\n\t\t/** Whether a search term or any facet filter is currently active. */\n\t\thasActiveFilters() {\n\t\t\tif ((this.searchValue || '').length > 0) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\treturn Object.values(this.activeFilters || {}).some((v) => (Array.isArray(v) ? v.length > 0 : !!v))\n\t\t},\n\n\t\t/** Combined column groups: built-in Metadata + external groups */\n\t\tallGroups() {\n\t\t\tconst groups = []\n\t\t\tif (this.showMetadata && this.schema) {\n\t\t\t\tgroups.push({\n\t\t\t\t\tid: 'metadata',\n\t\t\t\t\tlabel: 'Metadata',\n\t\t\t\t\tcolumns: METADATA_COLUMNS,\n\t\t\t\t\texpanded: true,\n\t\t\t\t})\n\t\t\t}\n\t\t\treturn [...groups, ...this.columnGroups]\n\t\t},\n\n\t\t/** Label of each column key, from the schema properties and the groups. */\n\t\tcolumnLabels() {\n\t\t\tconst map = {}\n\t\t\tthis.allColumns.forEach((c) => {\n\t\t\t\tmap[c.key] = c.label\n\t\t\t})\n\t\t\tthis.allGroups.forEach((g) => g.columns.forEach((c) => {\n\t\t\t\tmap[c.key] = c.label\n\t\t\t}))\n\t\t\treturn map\n\t\t},\n\n\t\t/** The visible columns in their order, with labels (all columns when none were chosen). */\n\t\torderedVisible() {\n\t\t\tconst keys = this.visibleColumns === null ? this.allColumnKeys : this.visibleColumns\n\t\t\treturn keys.filter((k) => this.columnLabels[k] !== undefined).map((key) => ({ key, label: this.columnLabels[key] }))\n\t\t},\n\n\t\t/** All column keys across schema properties and all groups */\n\t\tallColumnKeys() {\n\t\t\treturn [\n\t\t\t\t...this.allColumns.map((c) => c.key),\n\t\t\t\t...this.allGroups.flatMap((g) => g.columns.map((c) => c.key)),\n\t\t\t]\n\t\t},\n\n\t\t/**\n\t\t * The presets a date-range filter offers when it declares none.\n\t\t *\n\t\t * Just `custom`. Every shipped preset rolls BACKWARDS from today\n\t\t * (\"Last 30 days\"), and a sidebar filter is as often a forward window\n\t\t * (\"due next week\") as a backward one. Offering a preset that answers\n\t\t * the wrong direction is worse than offering none: it is one click and\n\t\t * it looks deliberate.\n\t\t *\n\t\t * @return {Array<object>} The preset list.\n\t\t */\n\t\trangePresets() {\n\t\t\t// Taken FROM the picker's own list rather than written out again, so\n\t\t\t// the one preset a filter offers carries the same id and the same\n\t\t\t// label as everywhere else it appears.\n\t\t\treturn DEFAULT_DATE_RANGE_PRESETS\n\t\t\t\t.filter((preset) => preset.id === 'custom')\n\t\t\t\t.map((preset) => ({ ...preset }))\n\t\t},\n\t},\n\n\twatch: {\n\t\tactiveTab(tab) {\n\t\t\tif (tab) {\n\t\t\t\tthis.internalActiveTab = tab\n\t\t\t}\n\t\t},\n\n\t\topen(val) {\n\t\t\tthis.internalOpen = val\n\t\t},\n\n\t\tinternalOpen(val) {\n\t\t\tthis.$emit('update:open', val)\n\t\t},\n\n\t\tdefaultTab(val) {\n\t\t\tthis.internalActiveTab = val\n\t\t},\n\n\t\tallGroups: {\n\t\t\timmediate: true,\n\t\t\thandler(groups) {\n\t\t\t\tfor (const group of groups) {\n\t\t\t\t\tif (!(group.id in this.expandedGroups)) {\n\t\t\t\t\t\tthis.expandedGroups[group.id] = group.expanded !== false\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\n\t\t// A reference picker's rows load once the schema naming them arrives,\n\t\t// which on a manifest page is after mount. Watching the FILTERS rather\n\t\t// than calling from `mounted()` covers both orders.\n\t\tschemaFilters: {\n\t\t\timmediate: true,\n\t\t\thandler() {\n\t\t\t\tthis.loadReferenceOptions()\n\t\t\t},\n\t\t},\n\t},\n\n\tmethods: {\n\t\tt,\n\n\t\t/**\n\t\t * A field chosen in the Sort section: its order, in the direction\n\t\t * already chosen.\n\t\t *\n\t\t * @param {object|null} option The chosen option.\n\t\t * @return {void}\n\t\t */\n\t\tonSortField(option) {\n\t\t\tconst chosen = option && this.sortOptions.find((o) => o.value === option.value)\n\t\t\tif (!chosen) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.emitSort(chosen, this.sortDirection)\n\t\t},\n\n\t\t/**\n\t\t * A direction chosen in the Sort section, for the chosen field.\n\t\t *\n\t\t * @param {string} direction `asc` or `desc`.\n\t\t * @return {void}\n\t\t */\n\t\tonSortDirection(direction) {\n\t\t\tif (!this.sortSelected) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.emitSort(this.sortSelected, direction === 'desc' ? 'desc' : 'asc')\n\t\t},\n\n\t\t/**\n\t\t * Emit the order an option stands for in a direction.\n\t\t *\n\t\t * @param {object} option The Sort option.\n\t\t * @param {string} direction `asc` or `desc`.\n\t\t * @return {void}\n\t\t */\n\t\temitSort(option, direction) {\n\t\t\tconst keys = Array.isArray(option.keys) ? option.keys : []\n\t\t\t/**\n\t\t\t * @event sort-change The Sort section chose an order. Payload: `[{ key, order }]`,\n\t\t\t * and the chosen option's value, which names an order that is not keys (`fixed`).\n\t\t\t */\n\t\t\tthis.$emit('sort-change', direction === 'desc' ? reverseSortKeys(keys) : keys.map((k) => ({ key: k.key, order: k.order || 'asc' })), option.value)\n\t\t},\n\n\t\t/**\n\t\t * Hand a saved-view intent to the page.\n\t\t *\n\t\t * @param {'apply'|'save'|'edit'|'share'|'presentation'|'update'|'copy'|'menu'|'delete'} action The intent.\n\t\t * @param {object|null} view The view, or null for save.\n\t\t * @spec openspec/changes/saved-views-manage-and-defaults/tasks.md#task-6\n\t\t */\n\t\tonSavedView(action, view) {\n\t\t\t/**\n\t\t\t * @event saved-view A saved-view intent from the Filters tab. Payload: `{ action, view }`.\n\t\t\t * @type {{action: string, view: (object|null)}}\n\t\t\t */\n\t\t\tthis.$emit('saved-view', { action, view })\n\t\t},\n\n\t\t/**\n\t\t * A manifest label through the injected lookup, or as written.\n\t\t *\n\t\t * @param {string} text The label as written.\n\t\t * @return {string} The label in the user's language.\n\t\t */\n\t\tshown(text) {\n\t\t\treturn typeof this.cnTranslate === 'function' && typeof text === 'string' && text !== '' ? this.cnTranslate(text) : text\n\t\t},\n\n\t\t/**\n\t\t * The `lang` of a label that fell back to its written text in another language.\n\t\t *\n\t\t * @param {string} text The label as written.\n\t\t * @return {string|undefined} The source language, or undefined.\n\t\t */\n\t\tlangOf(text) {\n\t\t\treturn labelLang(this.cnTranslate, text) || undefined\n\t\t},\n\n\t\t/**\n\t\t * Handle tab change from NcAppSidebar\n\t\t *\n\t\t * @param {string} tabId Tab identifier\n\t\t */\n\t\tonTabChange(tabId) {\n\t\t\tthis.internalActiveTab = tabId\n\t\t\tthis.$emit('tab-change', tabId)\n\t\t},\n\n\t\t/**\n\t\t * Check if a column is currently visible\n\t\t *\n\t\t * @param {string} key Column key\n\t\t */\n\t\tisColumnVisible(key) {\n\t\t\tif (this.visibleColumns === null) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\treturn this.visibleColumns.includes(key)\n\t\t},\n\n\t\t/**\n\t\t * Check if all columns in a group are visible\n\t\t *\n\t\t * @param {string[]} columns Array of column keys\n\t\t */\n\t\tisGroupAllVisible(columns) {\n\t\t\treturn columns.every((col) => this.isColumnVisible(col.key))\n\t\t},\n\n\t\t/**\n\t\t * Toggle a single column's visibility\n\t\t *\n\t\t * @param {string} key Column key\n\t\t */\n\t\ttoggleColumn(key) {\n\t\t\tlet newVisible\n\t\t\tif (this.visibleColumns === null) {\n\t\t\t\tnewVisible = this.allColumnKeys.filter((k) => k !== key)\n\t\t\t} else if (this.isColumnVisible(key)) {\n\t\t\t\tnewVisible = this.visibleColumns.filter((k) => k !== key)\n\t\t\t} else {\n\t\t\t\tnewVisible = [...this.visibleColumns, key]\n\t\t\t}\n\t\t\tthis.$emit('columns-change', newVisible)\n\t\t},\n\n\t\t/**\n\t\t * Select or deselect all columns in a group\n\t\t *\n\t\t * @param {string[]} columns Array of column keys\n\t\t */\n\t\ttoggleGroupAll(columns) {\n\t\t\tconst groupKeys = columns.map((c) => c.key)\n\t\t\tconst allVisible = this.isGroupAllVisible(columns)\n\n\t\t\tlet newVisible\n\t\t\tif (this.visibleColumns === null) {\n\t\t\t\t// Currently all visible — deselect this group\n\t\t\t\tnewVisible = this.allColumnKeys.filter((k) => !groupKeys.includes(k))\n\t\t\t} else if (allVisible) {\n\t\t\t\t// All in group visible — deselect them\n\t\t\t\tnewVisible = this.visibleColumns.filter((k) => !groupKeys.includes(k))\n\t\t\t} else {\n\t\t\t\t// Not all visible — select them all\n\t\t\t\tconst current = new Set(this.visibleColumns)\n\t\t\t\tgroupKeys.forEach((k) => current.add(k))\n\t\t\t\tnewVisible = [...current]\n\t\t\t}\n\t\t\tthis.$emit('columns-change', newVisible)\n\t\t},\n\n\t\t/**\n\t\t * Move a visible column to another place in the order. The drag and the\n\t\t * Move buttons both call this. A column stays inside its block: pinned\n\t\t * columns move among the pinned, the rest among the rest.\n\t\t *\n\t\t * @param {number} from Current index.\n\t\t * @param {number} to Target index.\n\t\t * @return {void}\n\t\t */\n\t\tmoveColumn(from, to) {\n\t\t\tconst list = this.orderedVisible.map((c) => c.key)\n\t\t\tconst lo = from < this.pinnedCount ? 0 : this.pinnedCount\n\t\t\tconst hi = from < this.pinnedCount ? this.pinnedCount - 1 : list.length - 1\n\t\t\tconst target = Math.min(hi, Math.max(lo, to))\n\t\t\tif (from < 0 || from >= list.length || target === from) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst [moved] = list.splice(from, 1)\n\t\t\tlist.splice(target, 0, moved)\n\t\t\t/**\n\t\t\t * @event columns-reorder Emitted when the user moves a column. Payload: the visible column keys in their new order.\n\t\t\t * @type {string[]}\n\t\t\t */\n\t\t\tthis.$emit('columns-reorder', list)\n\t\t},\n\n\t\t/**\n\t\t * Dropping a dragged column on another row.\n\t\t *\n\t\t * @param {number} index Index of the row it was dropped on.\n\t\t * @return {void}\n\t\t */\n\t\tonDropColumn(index) {\n\t\t\tconst from = this.dragFrom\n\t\t\tthis.dragFrom = -1\n\t\t\tif (from >= 0) {\n\t\t\t\tthis.moveColumn(from, index)\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Pin a column (it joins the pinned block at the start) or unpin it (it\n\t\t * leaves that block, to the first place after it).\n\t\t *\n\t\t * @param {number} index Index of the column.\n\t\t * @return {void}\n\t\t */\n\t\ttogglePin(index) {\n\t\t\tconst list = this.orderedVisible.map((c) => c.key)\n\t\t\tconst [moved] = list.splice(index, 1)\n\t\t\tlet count = this.pinnedCount\n\t\t\tif (index < count) {\n\t\t\t\tcount -= 1\n\t\t\t\tlist.splice(count, 0, moved)\n\t\t\t} else {\n\t\t\t\tlist.splice(count, 0, moved)\n\t\t\t\tcount += 1\n\t\t\t}\n\t\t\tthis.$emit('columns-reorder', list)\n\t\t\t/**\n\t\t\t * @event pin-change Emitted when a column is pinned or unpinned. Payload: the new number of pinned columns.\n\t\t\t * @type {number}\n\t\t\t */\n\t\t\tthis.$emit('pin-change', count)\n\t\t},\n\n\t\t/**\n\t\t * Toggle a group's expanded state\n\t\t *\n\t\t * @param {string} groupId Filter group identifier\n\t\t */\n\t\ttoggleGroup(groupId) {\n\t\t\tthis.expandedGroups[groupId] = !this.expandedGroups[groupId]\n\t\t},\n\n\t\t/**\n\t\t * Get filter options for a filter definition\n\t\t *\n\t\t * @param {object} filter Filter object\n\t\t */\n\t\tgetFilterOptions(filter) {\n\t\t\tconst live = facetOptions(\n\t\t\t\tthis.facetData[filter.key],\n\t\t\t\t(count) => t('nextcloud-vue', 'No value ({count})', { count }),\n\t\t\t)\n\t\t\tif (live !== null) {\n\t\t\t\treturn live\n\t\t\t}\n\t\t\t// A reference picker's rows come from another list, and neither a\n\t\t\t// schema enum nor a facet bucket can carry them.\n\t\t\tif (filter.type === 'reference') {\n\t\t\t\treturn this.referenceOptions[filter.key] || []\n\t\t\t}\n\t\t\treturn filter.options || []\n\t\t},\n\n\t\t/**\n\t\t * Whether a reference filter is still fetching its rows.\n\t\t *\n\t\t * Shown rather than hidden: an empty picker that is still loading and\n\t\t * one that genuinely has nothing to pick look identical, and only one\n\t\t * of them means the person should stop waiting.\n\t\t *\n\t\t * @param {object} filter The filter definition.\n\t\t *\n\t\t * @return {boolean} True while the load is in flight.\n\t\t */\n\t\tisLoadingOptions(filter) {\n\t\t\treturn this.referenceLoading[filter.key] === true\n\t\t},\n\n\t\t/**\n\t\t * The `{ from, to }` window a date-range filter currently holds.\n\t\t *\n\t\t * @param {object} filter The filter definition.\n\t\t *\n\t\t * @return {object|null} The window, or null when none is set.\n\t\t */\n\t\tgetRangeValue(filter) {\n\t\t\tconst value = this.activeFilters[filter.key]\n\t\t\tif (value && typeof value === 'object' && !Array.isArray(value)) {\n\t\t\t\treturn value\n\t\t\t}\n\t\t\treturn null\n\t\t},\n\n\t\t/**\n\t\t * A date-range filter changed.\n\t\t *\n\t\t * Emitted in the SAME `filter-change` shape every other control uses,\n\t\t * with the window as the payload's `values`, so a consumer has one\n\t\t * event to listen to and not two.\n\t\t *\n\t\t * @param {string} key The filter key.\n\t\t * @param {object|null} window The `{ from, to, preset }` value.\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\tonRangeChange(key, window) {\n\t\t\tconst from = (window && window.from) || ''\n\t\t\tconst to = (window && window.to) || ''\n\t\t\tif (from === '' && to === '') {\n\t\t\t\tthis.$emit('filter-change', { key, values: [] })\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.$emit('filter-change', { key, values: { from, to } })\n\t\t},\n\n\t\t/**\n\t\t * The text a `text` filter currently holds.\n\t\t *\n\t\t * @param {object} filter The filter definition.\n\t\t *\n\t\t * @return {string} The current value.\n\t\t */\n\t\tgetTextValue(filter) {\n\t\t\tconst value = this.activeFilters[filter.key]\n\t\t\tif (Array.isArray(value)) {\n\t\t\t\treturn value.length > 0 ? String(value[0]) : ''\n\t\t\t}\n\t\t\treturn (value === undefined || value === null) ? '' : String(value)\n\t\t},\n\n\t\t/**\n\t\t * A text filter changed.\n\t\t *\n\t\t * @param {string} key The filter key.\n\t\t * @param {string} value The typed value.\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\tonTextChange(key, value) {\n\t\t\tconst text = String(value ?? '').trim()\n\t\t\tthis.$emit('filter-change', { key, values: text === '' ? [] : [text] })\n\t\t},\n\n\t\t/**\n\t\t * Load the rows a `reference` filter picks from.\n\t\t *\n\t\t * Reads `optionsSource` off the schema property:\n\t\t * `{ register, schema, labelField, valueField, limit }`. The VALUE is\n\t\t * the referenced object's uuid, because that is what the server\n\t\t * filters on; the label is only what the person reads.\n\t\t *\n\t\t * Failures are logged and leave the picker empty rather than throwing:\n\t\t * one unreachable list must not take the whole sidebar with it.\n\t\t *\n\t\t * @return {Promise<void>} Resolves when every reference filter settled.\n\t\t */\n\t\tasync loadReferenceOptions() {\n\t\t\tconst pending = this.schemaFilters.filter((filter) => filter.type === 'reference'\n\t\t\t\t&& filter.optionsSource\n\t\t\t\t&& this.referenceOptions[filter.key] === undefined\n\t\t\t\t&& this.referenceLoading[filter.key] !== true)\n\t\t\tif (pending.length === 0) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst [{ default: axios }, { generateUrl }] = await Promise.all([\n\t\t\t\timport('@nextcloud/axios'),\n\t\t\t\timport('@nextcloud/router'),\n\t\t\t])\n\n\t\t\tawait Promise.all(pending.map(async (filter) => {\n\t\t\t\tconst source = filter.optionsSource\n\t\t\t\tif (!source.register || !source.schema) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tthis.referenceLoading = { ...this.referenceLoading, [filter.key]: true }\n\t\t\t\ttry {\n\t\t\t\t\tconst url = generateUrl('/apps/openregister/api/objects/{register}/{schema}', {\n\t\t\t\t\t\tregister: source.register,\n\t\t\t\t\t\tschema: source.schema,\n\t\t\t\t\t})\n\t\t\t\t\tconst response = await axios.get(url, { params: { _limit: source.limit || 200 } })\n\t\t\t\t\tconst rows = response?.data?.results || response?.data || []\n\t\t\t\t\tconst valueField = source.valueField || '@self.uuid'\n\t\t\t\t\tconst labelField = source.labelField || 'title'\n\t\t\t\t\tconst options = rows\n\t\t\t\t\t\t.map((row) => ({\n\t\t\t\t\t\t\tid: this.readPath(row, valueField),\n\t\t\t\t\t\t\tlabel: String(this.readPath(row, labelField) ?? this.readPath(row, valueField) ?? ''),\n\t\t\t\t\t\t}))\n\t\t\t\t\t\t.filter((option) => option.id !== null && option.id !== undefined && option.id !== '')\n\t\t\t\t\t\t.sort((a, b) => a.label.localeCompare(b.label))\n\t\t\t\t\tthis.referenceOptions = { ...this.referenceOptions, [filter.key]: options }\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\t\tconsole.error(`[CnIndexSidebar] the reference filter \"${filter.key}\" could not load its options`, error)\n\t\t\t\t\tthis.referenceOptions = { ...this.referenceOptions, [filter.key]: [] }\n\t\t\t\t} finally {\n\t\t\t\t\tthis.referenceLoading = { ...this.referenceLoading, [filter.key]: false }\n\t\t\t\t}\n\t\t\t}))\n\t\t},\n\n\t\t/**\n\t\t * Read a dotted path off a row (`@self.uuid`, `title`).\n\t\t *\n\t\t * @param {object} row The row.\n\t\t * @param {string} path The dotted path.\n\t\t *\n\t\t * @return {unknown} The value, or undefined.\n\t\t */\n\t\treadPath(row, path) {\n\t\t\treturn String(path).split('.').reduce((acc, part) => ((acc === null || acc === undefined) ? acc : acc[part]), row)\n\t\t},\n\n\t\t/**\n\t\t * Get currently selected options for a filter\n\t\t *\n\t\t * @param {object} filter Filter object\n\t\t */\n\t\tgetSelectedFilterOptions(filter) {\n\t\t\tconst value = this.activeFilters[filter.key]\n\t\t\tif (!value) {\n\t\t\t\treturn []\n\t\t\t}\n\t\t\tconst values = Array.isArray(value) ? value : [value]\n\t\t\tconst options = this.getFilterOptions(filter)\n\t\t\treturn values.map((v) => options.find((o) => o.id === v) || { id: v, label: String(v) })\n\t\t},\n\n\t\t/**\n\t\t * Handle filter select change\n\t\t *\n\t\t * @param {string} key Filter key\n\t\t * @param {Array} selected Selected values\n\t\t */\n\t\tonFilterChange(key, selected) {\n\t\t\t// 🔴 A SINGLE-VALUED SELECT EMITS AN OBJECT, NOT AN ARRAY. NcSelect\n\t\t\t// changes the SHAPE of its payload with `multiple`, and `.map` on\n\t\t\t// the object shape throws inside an event handler, where Vue logs\n\t\t\t// it and carries on: the picker looks inert and the console says\n\t\t\t// why in a place nobody is looking.\n\t\t\tconst chosen = Array.isArray(selected) ? selected : (selected ? [selected] : [])\n\t\t\tconst values = chosen.map((o) => ((o && typeof o === 'object' && 'id' in o) ? o.id : o))\n\t\t\tthis.$emit('filter-change', { key, values })\n\t\t},\n\n\t\t/**\n\t\t * \"Clear all\" click: reset search and every active facet filter in\n\t\t * one shot, so the parent does one fetch instead of one per field.\n\t\t */\n\t\tonClearAll() {\n\t\t\t/**\n\t\t\t * @event clear-filters \"Clear all\" clicked; reset search and every active filter.\n\t\t\t */\n\t\t\tthis.$emit('clear-filters')\n\t\t},\n\t},\n}\n</script>\n\n<!-- Styles in css/index-sidebar.css -->\n"],"names":["_createBlock","_createVNode","_createElementVNode","_openBlock","_createElementBlock","_renderSlot","_toDisplayString","_createTextVNode","_Fragment","_renderList","_normalizeClass","_withModifiers","_mergeProps"],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import script from './CnReadinessChecklist.vue2.js';
|
|
2
|
+
import { render } from './CnReadinessChecklist.vue3.js';
|
|
3
|
+
|
|
4
|
+
script.render = render;
|
|
5
|
+
script.__scopeId = "data-v-4e10a556";
|
|
6
|
+
const __sfc_main = script;
|
|
7
|
+
|
|
8
|
+
export { __sfc_main as default };
|
|
9
|
+
//# sourceMappingURL=CnReadinessChecklist.vue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CnReadinessChecklist.vue.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;"}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import axios__default from '@nextcloud/axios';
|
|
2
|
+
import { translate } from '@nextcloud/l10n';
|
|
3
|
+
import { generateUrl } from '@nextcloud/router';
|
|
4
|
+
import { NcLoadingIcon, NcNoteCard } from '@nextcloud/vue';
|
|
5
|
+
import { readPath } from '../../utils/readPath.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The fields an item is read from by default.
|
|
9
|
+
*
|
|
10
|
+
* @type {Readonly<Record<string, string>>}
|
|
11
|
+
*/
|
|
12
|
+
const DEFAULT_FIELDS = Object.freeze({
|
|
13
|
+
id: 'id',
|
|
14
|
+
label: 'label',
|
|
15
|
+
explanation: 'explanation',
|
|
16
|
+
met: 'met',
|
|
17
|
+
fixHref: 'fixHref',
|
|
18
|
+
failure: 'failure',
|
|
19
|
+
group: 'group',
|
|
20
|
+
blocking: 'blocking',
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* CnReadinessChecklist: a list of things an instance needs, each with its
|
|
25
|
+
* state in words (met, open, unknown), an explanation and a link to the
|
|
26
|
+
* screen that fixes it. Reported, never gated: nothing here blocks the app.
|
|
27
|
+
*
|
|
28
|
+
* Items come from `items`, or are read from an app endpoint (`source`, an app
|
|
29
|
+
* path resolved with `generateUrl`, the list at `itemsPath`) and re-read when
|
|
30
|
+
* the reader comes back to the tab. `fields` maps an item's keys onto the
|
|
31
|
+
* row's (`{ label: 'title', met: 'done', fixHref: 'screen' }`). Items carrying
|
|
32
|
+
* a `group` render under that group's heading (`groups`, in order).
|
|
33
|
+
*
|
|
34
|
+
* @spec openspec/changes/readiness-checklist/specs/readiness-checklist/spec.md
|
|
35
|
+
*/
|
|
36
|
+
var script = {
|
|
37
|
+
name: 'CnReadinessChecklist',
|
|
38
|
+
|
|
39
|
+
components: { NcLoadingIcon, NcNoteCard },
|
|
40
|
+
|
|
41
|
+
inject: {
|
|
42
|
+
/** The host app's translate, for texts the page declares. */
|
|
43
|
+
cnTranslate: { default: () => (key) => key },
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
props: {
|
|
47
|
+
/** The items: `{ id, label, explanation?, met (true|false|null), fixHref?, failure?, group?, blocking? }`. */
|
|
48
|
+
items: { type: Array, default: () => [] },
|
|
49
|
+
/** An app path to read the items from (`/apps/<app>/api/setup/status`). */
|
|
50
|
+
source: { type: String, default: '' },
|
|
51
|
+
/** Where the items sit in the answer. */
|
|
52
|
+
itemsPath: { type: String, default: 'items' },
|
|
53
|
+
/** Item key to row key, over the defaults. */
|
|
54
|
+
fields: { type: Object, default: () => ({}) },
|
|
55
|
+
/** Headings for grouped items, in order: `[{ id, title }]`. */
|
|
56
|
+
groups: { type: Array, default: () => [] },
|
|
57
|
+
/** A line above the list. */
|
|
58
|
+
description: { type: String, default: '' },
|
|
59
|
+
/** The words for each state: `{ met, unmet, unknown }`. */
|
|
60
|
+
statusLabels: { type: Object, default: () => ({}) },
|
|
61
|
+
/** Said when there is nothing to check. */
|
|
62
|
+
emptyText: { type: String, default: '' },
|
|
63
|
+
/** Said when the source could not be read. */
|
|
64
|
+
errorText: { type: String, default: '' },
|
|
65
|
+
/** Said before the unmet items marked `blocking` ("Cannot run until this is installed:"). */
|
|
66
|
+
blockingText: { type: String, default: '' },
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
emits: ['loaded'],
|
|
70
|
+
|
|
71
|
+
data() {
|
|
72
|
+
return {
|
|
73
|
+
loading: false,
|
|
74
|
+
loadError: '',
|
|
75
|
+
loadedItems: null,
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
|
|
79
|
+
computed: {
|
|
80
|
+
/** @return {Array<object>} The items, normalised. */
|
|
81
|
+
shownItems() {
|
|
82
|
+
const raw = this.loadedItems !== null ? this.loadedItems : this.items;
|
|
83
|
+
const map = { ...DEFAULT_FIELDS, ...(this.fields || {}) };
|
|
84
|
+
return (Array.isArray(raw) ? raw : []).map((row, index) => {
|
|
85
|
+
const read = (key) => readPath(row, map[key]);
|
|
86
|
+
const met = read('met');
|
|
87
|
+
return {
|
|
88
|
+
id: String(read('id') ?? index),
|
|
89
|
+
label: this.text(read('label') ?? read('id') ?? ''),
|
|
90
|
+
explanation: this.text(read('explanation') ?? ''),
|
|
91
|
+
met: met === true || met === false ? met : null,
|
|
92
|
+
fixHref: typeof read('fixHref') === 'string' ? read('fixHref') : '',
|
|
93
|
+
failure: read('failure') ? String(read('failure')) : '',
|
|
94
|
+
group: read('group') ? String(read('group')) : '',
|
|
95
|
+
blocking: read('blocking') === true,
|
|
96
|
+
}
|
|
97
|
+
})
|
|
98
|
+
},
|
|
99
|
+
|
|
100
|
+
/** @return {Array<object>} The unmet blocking items. */
|
|
101
|
+
blockingItems() {
|
|
102
|
+
return this.shownItems.filter((item) => item.blocking && item.met !== true)
|
|
103
|
+
},
|
|
104
|
+
|
|
105
|
+
/** @return {Array<{id: string, title: string, items: Array<object>}>} The groups that hold items, in order. */
|
|
106
|
+
shownGroups() {
|
|
107
|
+
const declared = (Array.isArray(this.groups) ? this.groups : []).map((group) => ({
|
|
108
|
+
id: String(group.id),
|
|
109
|
+
title: this.text(group.title || ''),
|
|
110
|
+
items: this.shownItems.filter((item) => item.group === String(group.id)),
|
|
111
|
+
}));
|
|
112
|
+
const known = new Set(declared.map((group) => group.id));
|
|
113
|
+
const rest = this.shownItems.filter((item) => !known.has(item.group));
|
|
114
|
+
const all = rest.length > 0 ? [{ id: 'items', title: '', items: rest }, ...declared] : declared;
|
|
115
|
+
return all.filter((group) => group.items.length > 0)
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
|
|
119
|
+
watch: {
|
|
120
|
+
source() {
|
|
121
|
+
this.reload();
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
|
|
125
|
+
mounted() {
|
|
126
|
+
this.reload();
|
|
127
|
+
window.addEventListener('focus', this.onFocus);
|
|
128
|
+
},
|
|
129
|
+
|
|
130
|
+
beforeUnmount() {
|
|
131
|
+
window.removeEventListener('focus', this.onFocus);
|
|
132
|
+
},
|
|
133
|
+
|
|
134
|
+
methods: {
|
|
135
|
+
t: translate,
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* A declared text through the host's translate.
|
|
139
|
+
*
|
|
140
|
+
* @param {string} value The text.
|
|
141
|
+
* @return {string} The translated text.
|
|
142
|
+
*/
|
|
143
|
+
text(value) {
|
|
144
|
+
return value ? String(this.cnTranslate(String(value))) : ''
|
|
145
|
+
},
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* @param {object} item The item.
|
|
149
|
+
* @return {string} `met`, `unmet` or `unknown`.
|
|
150
|
+
*/
|
|
151
|
+
stateOf(item) {
|
|
152
|
+
if (item.met === true) {
|
|
153
|
+
return 'met'
|
|
154
|
+
}
|
|
155
|
+
return item.met === false ? 'unmet' : 'unknown'
|
|
156
|
+
},
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* The word for an item's state.
|
|
160
|
+
*
|
|
161
|
+
* @param {object} item The item.
|
|
162
|
+
* @return {string} The word.
|
|
163
|
+
*/
|
|
164
|
+
stateLabel(item) {
|
|
165
|
+
const state = this.stateOf(item);
|
|
166
|
+
const own = this.statusLabels && this.statusLabels[state];
|
|
167
|
+
if (own) {
|
|
168
|
+
return this.text(own)
|
|
169
|
+
}
|
|
170
|
+
return {
|
|
171
|
+
met: translate('nextcloud-vue', 'Done'),
|
|
172
|
+
unmet: translate('nextcloud-vue', 'Still open'),
|
|
173
|
+
unknown: translate('nextcloud-vue', 'Unknown'),
|
|
174
|
+
}[state]
|
|
175
|
+
},
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Read the items again, from the source. The source asks the instance
|
|
179
|
+
* rather than a stored flag, so a fix made elsewhere shows on return.
|
|
180
|
+
*
|
|
181
|
+
* @return {Promise<void>}
|
|
182
|
+
*/
|
|
183
|
+
async reload() {
|
|
184
|
+
if (!this.source) {
|
|
185
|
+
this.loadedItems = null;
|
|
186
|
+
return
|
|
187
|
+
}
|
|
188
|
+
this.loading = this.loadedItems === null;
|
|
189
|
+
this.loadError = '';
|
|
190
|
+
try {
|
|
191
|
+
const { data } = await axios__default.get(generateUrl(this.source));
|
|
192
|
+
const rows = Array.isArray(data) ? data : readPath(data, this.itemsPath);
|
|
193
|
+
this.loadedItems = Array.isArray(rows) ? rows : [];
|
|
194
|
+
/** @event loaded The source answered. Payload: the whole answer. */
|
|
195
|
+
this.$emit('loaded', data);
|
|
196
|
+
} catch {
|
|
197
|
+
this.loadedItems = [];
|
|
198
|
+
this.loadError = this.errorText ? this.text(this.errorText) : translate('nextcloud-vue', 'The checklist could not be read.');
|
|
199
|
+
} finally {
|
|
200
|
+
this.loading = false;
|
|
201
|
+
}
|
|
202
|
+
},
|
|
203
|
+
|
|
204
|
+
/** Re-read when the reader comes back from fixing something. */
|
|
205
|
+
onFocus() {
|
|
206
|
+
if (this.source) {
|
|
207
|
+
this.reload();
|
|
208
|
+
}
|
|
209
|
+
},
|
|
210
|
+
},
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
export { script as default };
|
|
214
|
+
//# sourceMappingURL=CnReadinessChecklist.vue2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CnReadinessChecklist.vue2.js","sources":["../../../../src/components/CnReadinessChecklist/CnReadinessChecklist.vue"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n<template>\n\t<div class=\"cn-readiness-checklist\" data-testid=\"cn-readiness-checklist\">\n\t\t<p v-if=\"description\" class=\"cn-readiness-checklist__description\">\n\t\t\t{{ description }}\n\t\t</p>\n\n\t\t<NcLoadingIcon v-if=\"loading\" :size=\"32\" :name=\"t('nextcloud-vue', 'Loading')\" />\n\n\t\t<NcNoteCard v-else-if=\"loadError\" type=\"error\" data-testid=\"cn-readiness-checklist-error\">\n\t\t\t{{ loadError }}\n\t\t</NcNoteCard>\n\n\t\t<template v-else>\n\t\t\t<NcNoteCard v-if=\"blockingText && blockingItems.length > 0\"\n\t\t\t\ttype=\"error\"\n\t\t\t\tdata-testid=\"cn-readiness-checklist-blocking\">\n\t\t\t\t{{ blockingText }} {{ blockingItems.map((item) => item.label).join(', ') }}\n\t\t\t</NcNoteCard>\n\n\t\t\t<p v-if=\"shownItems.length === 0\" class=\"cn-readiness-checklist__empty\" data-testid=\"cn-readiness-checklist-empty\">\n\t\t\t\t{{ emptyText || t('nextcloud-vue', 'Nothing to check.') }}\n\t\t\t</p>\n\n\t\t\t<section v-for=\"group in shownGroups\"\n\t\t\t\t:key=\"group.id\"\n\t\t\t\tclass=\"cn-readiness-checklist__group\"\n\t\t\t\t:data-testid=\"`cn-readiness-checklist-group-${group.id}`\">\n\t\t\t\t<h4 v-if=\"group.title\" class=\"cn-readiness-checklist__group-title\">\n\t\t\t\t\t{{ group.title }}\n\t\t\t\t</h4>\n\t\t\t\t<ul class=\"cn-readiness-checklist__list\">\n\t\t\t\t\t<li v-for=\"item in group.items\"\n\t\t\t\t\t\t:key=\"item.id\"\n\t\t\t\t\t\tclass=\"cn-readiness-checklist__item\"\n\t\t\t\t\t\t:data-testid=\"`cn-readiness-item-${item.id}`\">\n\t\t\t\t\t\t<!-- The state is a word, not a colour (WCAG 1.4.1); the\n\t\t\t\t\t\t colour repeats it. -->\n\t\t\t\t\t\t<span class=\"cn-readiness-checklist__state\"\n\t\t\t\t\t\t\t:class=\"`cn-readiness-checklist__state--${stateOf(item)}`\"\n\t\t\t\t\t\t\tdata-testid=\"cn-readiness-item-state\">\n\t\t\t\t\t\t\t{{ stateLabel(item) }}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<span class=\"cn-readiness-checklist__body\">\n\t\t\t\t\t\t\t<a v-if=\"item.fixHref\"\n\t\t\t\t\t\t\t\t:href=\"item.fixHref\"\n\t\t\t\t\t\t\t\tclass=\"cn-readiness-checklist__label\"\n\t\t\t\t\t\t\t\tdata-testid=\"cn-readiness-item-fix\">{{ item.label }}</a>\n\t\t\t\t\t\t\t<span v-else class=\"cn-readiness-checklist__label\">{{ item.label }}</span>\n\t\t\t\t\t\t\t<span v-if=\"item.explanation\" class=\"cn-readiness-checklist__explanation\">{{ item.explanation }}</span>\n\t\t\t\t\t\t\t<span v-if=\"item.failure\" class=\"cn-readiness-checklist__failure\">\n\t\t\t\t\t\t\t\t{{ t('nextcloud-vue', 'This could not be read: {reason}', { reason: item.failure }) }}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</li>\n\t\t\t\t</ul>\n\t\t\t</section>\n\t\t</template>\n\t</div>\n</template>\n\n<script>\nimport axios from '@nextcloud/axios'\nimport { translate as t } from '@nextcloud/l10n'\nimport { generateUrl } from '@nextcloud/router'\nimport { NcLoadingIcon, NcNoteCard } from '@nextcloud/vue'\nimport { readPath } from '../../utils/readPath.js'\n\n/**\n * The fields an item is read from by default.\n *\n * @type {Readonly<Record<string, string>>}\n */\nconst DEFAULT_FIELDS = Object.freeze({\n\tid: 'id',\n\tlabel: 'label',\n\texplanation: 'explanation',\n\tmet: 'met',\n\tfixHref: 'fixHref',\n\tfailure: 'failure',\n\tgroup: 'group',\n\tblocking: 'blocking',\n})\n\n/**\n * CnReadinessChecklist: a list of things an instance needs, each with its\n * state in words (met, open, unknown), an explanation and a link to the\n * screen that fixes it. Reported, never gated: nothing here blocks the app.\n *\n * Items come from `items`, or are read from an app endpoint (`source`, an app\n * path resolved with `generateUrl`, the list at `itemsPath`) and re-read when\n * the reader comes back to the tab. `fields` maps an item's keys onto the\n * row's (`{ label: 'title', met: 'done', fixHref: 'screen' }`). Items carrying\n * a `group` render under that group's heading (`groups`, in order).\n *\n * @spec openspec/changes/readiness-checklist/specs/readiness-checklist/spec.md\n */\nexport default {\n\tname: 'CnReadinessChecklist',\n\n\tcomponents: { NcLoadingIcon, NcNoteCard },\n\n\tinject: {\n\t\t/** The host app's translate, for texts the page declares. */\n\t\tcnTranslate: { default: () => (key) => key },\n\t},\n\n\tprops: {\n\t\t/** The items: `{ id, label, explanation?, met (true|false|null), fixHref?, failure?, group?, blocking? }`. */\n\t\titems: { type: Array, default: () => [] },\n\t\t/** An app path to read the items from (`/apps/<app>/api/setup/status`). */\n\t\tsource: { type: String, default: '' },\n\t\t/** Where the items sit in the answer. */\n\t\titemsPath: { type: String, default: 'items' },\n\t\t/** Item key to row key, over the defaults. */\n\t\tfields: { type: Object, default: () => ({}) },\n\t\t/** Headings for grouped items, in order: `[{ id, title }]`. */\n\t\tgroups: { type: Array, default: () => [] },\n\t\t/** A line above the list. */\n\t\tdescription: { type: String, default: '' },\n\t\t/** The words for each state: `{ met, unmet, unknown }`. */\n\t\tstatusLabels: { type: Object, default: () => ({}) },\n\t\t/** Said when there is nothing to check. */\n\t\temptyText: { type: String, default: '' },\n\t\t/** Said when the source could not be read. */\n\t\terrorText: { type: String, default: '' },\n\t\t/** Said before the unmet items marked `blocking` (\"Cannot run until this is installed:\"). */\n\t\tblockingText: { type: String, default: '' },\n\t},\n\n\temits: ['loaded'],\n\n\tdata() {\n\t\treturn {\n\t\t\tloading: false,\n\t\t\tloadError: '',\n\t\t\tloadedItems: null,\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/** @return {Array<object>} The items, normalised. */\n\t\tshownItems() {\n\t\t\tconst raw = this.loadedItems !== null ? this.loadedItems : this.items\n\t\t\tconst map = { ...DEFAULT_FIELDS, ...(this.fields || {}) }\n\t\t\treturn (Array.isArray(raw) ? raw : []).map((row, index) => {\n\t\t\t\tconst read = (key) => readPath(row, map[key])\n\t\t\t\tconst met = read('met')\n\t\t\t\treturn {\n\t\t\t\t\tid: String(read('id') ?? index),\n\t\t\t\t\tlabel: this.text(read('label') ?? read('id') ?? ''),\n\t\t\t\t\texplanation: this.text(read('explanation') ?? ''),\n\t\t\t\t\tmet: met === true || met === false ? met : null,\n\t\t\t\t\tfixHref: typeof read('fixHref') === 'string' ? read('fixHref') : '',\n\t\t\t\t\tfailure: read('failure') ? String(read('failure')) : '',\n\t\t\t\t\tgroup: read('group') ? String(read('group')) : '',\n\t\t\t\t\tblocking: read('blocking') === true,\n\t\t\t\t}\n\t\t\t})\n\t\t},\n\n\t\t/** @return {Array<object>} The unmet blocking items. */\n\t\tblockingItems() {\n\t\t\treturn this.shownItems.filter((item) => item.blocking && item.met !== true)\n\t\t},\n\n\t\t/** @return {Array<{id: string, title: string, items: Array<object>}>} The groups that hold items, in order. */\n\t\tshownGroups() {\n\t\t\tconst declared = (Array.isArray(this.groups) ? this.groups : []).map((group) => ({\n\t\t\t\tid: String(group.id),\n\t\t\t\ttitle: this.text(group.title || ''),\n\t\t\t\titems: this.shownItems.filter((item) => item.group === String(group.id)),\n\t\t\t}))\n\t\t\tconst known = new Set(declared.map((group) => group.id))\n\t\t\tconst rest = this.shownItems.filter((item) => !known.has(item.group))\n\t\t\tconst all = rest.length > 0 ? [{ id: 'items', title: '', items: rest }, ...declared] : declared\n\t\t\treturn all.filter((group) => group.items.length > 0)\n\t\t},\n\t},\n\n\twatch: {\n\t\tsource() {\n\t\t\tthis.reload()\n\t\t},\n\t},\n\n\tmounted() {\n\t\tthis.reload()\n\t\twindow.addEventListener('focus', this.onFocus)\n\t},\n\n\tbeforeUnmount() {\n\t\twindow.removeEventListener('focus', this.onFocus)\n\t},\n\n\tmethods: {\n\t\tt,\n\n\t\t/**\n\t\t * A declared text through the host's translate.\n\t\t *\n\t\t * @param {string} value The text.\n\t\t * @return {string} The translated text.\n\t\t */\n\t\ttext(value) {\n\t\t\treturn value ? String(this.cnTranslate(String(value))) : ''\n\t\t},\n\n\t\t/**\n\t\t * @param {object} item The item.\n\t\t * @return {string} `met`, `unmet` or `unknown`.\n\t\t */\n\t\tstateOf(item) {\n\t\t\tif (item.met === true) {\n\t\t\t\treturn 'met'\n\t\t\t}\n\t\t\treturn item.met === false ? 'unmet' : 'unknown'\n\t\t},\n\n\t\t/**\n\t\t * The word for an item's state.\n\t\t *\n\t\t * @param {object} item The item.\n\t\t * @return {string} The word.\n\t\t */\n\t\tstateLabel(item) {\n\t\t\tconst state = this.stateOf(item)\n\t\t\tconst own = this.statusLabels && this.statusLabels[state]\n\t\t\tif (own) {\n\t\t\t\treturn this.text(own)\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tmet: t('nextcloud-vue', 'Done'),\n\t\t\t\tunmet: t('nextcloud-vue', 'Still open'),\n\t\t\t\tunknown: t('nextcloud-vue', 'Unknown'),\n\t\t\t}[state]\n\t\t},\n\n\t\t/**\n\t\t * Read the items again, from the source. The source asks the instance\n\t\t * rather than a stored flag, so a fix made elsewhere shows on return.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync reload() {\n\t\t\tif (!this.source) {\n\t\t\t\tthis.loadedItems = null\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.loading = this.loadedItems === null\n\t\t\tthis.loadError = ''\n\t\t\ttry {\n\t\t\t\tconst { data } = await axios.get(generateUrl(this.source))\n\t\t\t\tconst rows = Array.isArray(data) ? data : readPath(data, this.itemsPath)\n\t\t\t\tthis.loadedItems = Array.isArray(rows) ? rows : []\n\t\t\t\t/** @event loaded The source answered. Payload: the whole answer. */\n\t\t\t\tthis.$emit('loaded', data)\n\t\t\t} catch {\n\t\t\t\tthis.loadedItems = []\n\t\t\t\tthis.loadError = this.errorText ? this.text(this.errorText) : t('nextcloud-vue', 'The checklist could not be read.')\n\t\t\t} finally {\n\t\t\t\tthis.loading = false\n\t\t\t}\n\t\t},\n\n\t\t/** Re-read when the reader comes back from fixing something. */\n\t\tonFocus() {\n\t\t\tif (this.source) {\n\t\t\t\tthis.reload()\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-readiness-checklist__description,\n.cn-readiness-checklist__empty {\n\tcolor: var(--color-text-maxcontrast);\n\tmargin: 0 0 12px;\n}\n\n.cn-readiness-checklist__group-title {\n\tmargin: 12px 0 4px;\n}\n\n.cn-readiness-checklist__list {\n\tlist-style: none;\n\tmargin: 0;\n\tpadding: 0;\n}\n\n.cn-readiness-checklist__item {\n\tdisplay: flex;\n\tgap: calc(var(--default-grid-baseline, 4px) * 3);\n\tpadding-block: calc(var(--default-grid-baseline, 4px) * 2);\n\tborder-block-end: 1px solid var(--color-border);\n}\n\n.cn-readiness-checklist__state {\n\tflex: 0 0 auto;\n\tmin-width: 6em;\n\tfont-weight: bold;\n}\n\n.cn-readiness-checklist__state--met {\n\tcolor: var(--color-success-text, var(--color-success));\n}\n\n.cn-readiness-checklist__state--unmet {\n\tcolor: var(--color-error-text, var(--color-error));\n}\n\n.cn-readiness-checklist__state--unknown {\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-readiness-checklist__body {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 2px;\n\tmin-width: 0;\n}\n\n.cn-readiness-checklist__explanation {\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-readiness-checklist__failure {\n\tcolor: var(--color-error-text, var(--color-error));\n}\n</style>\n"],"names":["t","axios"],"mappings":"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"}
|