@conduction/nextcloud-vue 2.100.0 → 2.102.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/CnActionsBar/CnActionsBar.vue2.js +22 -0
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue2.js.map +1 -1
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js +8 -6
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js.map +1 -1
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue.js +1 -1
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue2.js +29 -4
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue3.js +9 -1
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue.js +1 -1
- package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue2.js +22 -1
- package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue2.js.map +1 -1
- package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue3.js +26 -16
- package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue3.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue.js +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +70 -6
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js +105 -74
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
- package/dist/esm/components/CnExportsWidget/CnExportsWidget.vue.js +9 -0
- package/dist/esm/components/CnExportsWidget/CnExportsWidget.vue.js.map +1 -0
- package/dist/esm/components/CnExportsWidget/CnExportsWidget.vue2.js +139 -0
- package/dist/esm/components/CnExportsWidget/CnExportsWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnExportsWidget/CnExportsWidget.vue3.js +76 -0
- package/dist/esm/components/CnExportsWidget/CnExportsWidget.vue3.js.map +1 -0
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue.js +1 -1
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js +160 -2
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js.map +1 -1
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js +206 -94
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js.map +1 -1
- package/dist/esm/components/CnFilesBrowser/filesReview.js +61 -0
- package/dist/esm/components/CnFilesBrowser/filesReview.js.map +1 -0
- package/dist/esm/components/CnGroupedCardsWidget/CnGroupedCardsWidget.vue.js +9 -0
- package/dist/esm/components/CnGroupedCardsWidget/CnGroupedCardsWidget.vue.js.map +1 -0
- package/dist/esm/components/CnGroupedCardsWidget/CnGroupedCardsWidget.vue2.js +279 -0
- package/dist/esm/components/CnGroupedCardsWidget/CnGroupedCardsWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnGroupedCardsWidget/CnGroupedCardsWidget.vue3.js +122 -0
- package/dist/esm/components/CnGroupedCardsWidget/CnGroupedCardsWidget.vue3.js.map +1 -0
- package/dist/esm/components/CnGroupedCardsWidget/index.js +29 -0
- package/dist/esm/components/CnGroupedCardsWidget/index.js.map +1 -0
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +320 -74
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +323 -213
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/useNamedSource.js +30 -3
- package/dist/esm/components/CnIndexPage/useNamedSource.js.map +1 -1
- package/dist/esm/components/CnMapWidget/CnMapWidget.vue.js +1 -1
- package/dist/esm/components/CnMapWidget/CnMapWidget.vue2.js +15 -0
- package/dist/esm/components/CnMapWidget/CnMapWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnMapWidget/CnMapWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnMenuWidget/CnMenuWidget.vue.js +1 -1
- package/dist/esm/components/CnMenuWidget/CnMenuWidget.vue2.js +25 -1
- package/dist/esm/components/CnMenuWidget/CnMenuWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnMenuWidget/CnMenuWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue.js +1 -1
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js +14 -1
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js +14 -6
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue.js +1 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js +10 -0
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js +6 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js.map +1 -1
- package/dist/esm/components/CnOrderedListField/CnOrderedListField.vue.js +1 -1
- package/dist/esm/components/CnOrderedListField/CnOrderedListField.vue2.js +91 -4
- package/dist/esm/components/CnOrderedListField/CnOrderedListField.vue2.js.map +1 -1
- package/dist/esm/components/CnOrderedListField/CnOrderedListField.vue3.js +63 -38
- package/dist/esm/components/CnOrderedListField/CnOrderedListField.vue3.js.map +1 -1
- package/dist/esm/components/CnQuickFilterBar/CnQuickFilterBar.vue.js +1 -1
- package/dist/esm/components/CnQuickFilterBar/CnQuickFilterBar.vue2.js +106 -4
- package/dist/esm/components/CnQuickFilterBar/CnQuickFilterBar.vue2.js.map +1 -1
- package/dist/esm/components/CnQuickFilterBar/CnQuickFilterBar.vue3.js +70 -25
- package/dist/esm/components/CnQuickFilterBar/CnQuickFilterBar.vue3.js.map +1 -1
- package/dist/esm/components/CnSavedViewAlertWidget/CnSavedViewAlertWidget.vue.js +9 -0
- package/dist/esm/components/CnSavedViewAlertWidget/CnSavedViewAlertWidget.vue.js.map +1 -0
- package/dist/esm/components/CnSavedViewAlertWidget/CnSavedViewAlertWidget.vue2.js +175 -0
- package/dist/esm/components/CnSavedViewAlertWidget/CnSavedViewAlertWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnSavedViewAlertWidget/CnSavedViewAlertWidget.vue3.js +77 -0
- package/dist/esm/components/CnSavedViewAlertWidget/CnSavedViewAlertWidget.vue3.js.map +1 -0
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue.js +1 -1
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue2.js +35 -2
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue2.js.map +1 -1
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue3.js.map +1 -1
- package/dist/esm/components/CnWidgetGrid/builtInWidgets.js +4 -0
- package/dist/esm/components/CnWidgetGrid/builtInWidgets.js.map +1 -1
- package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js +1 -0
- package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js.map +1 -1
- package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue.js +1 -1
- package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js +2 -23
- package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js.map +1 -1
- package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue3.js.map +1 -1
- package/dist/esm/composables/indexSources.js +176 -20
- package/dist/esm/composables/indexSources.js.map +1 -1
- package/dist/esm/composables/useEndpointSource.js +28 -6
- package/dist/esm/composables/useEndpointSource.js.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/l10n/en.json.js +41 -1
- package/dist/esm/l10n/en.json.js.map +1 -1
- package/dist/esm/l10n/nl.json.js +39 -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 +939 -376
- package/dist/esm/utils/builtInFormatters.js +24 -4
- package/dist/esm/utils/builtInFormatters.js.map +1 -1
- package/dist/esm/utils/languageMapText.js +50 -0
- package/dist/esm/utils/languageMapText.js.map +1 -0
- package/dist/esm/utils/libraryWidgetKeys.js +3 -0
- package/dist/esm/utils/libraryWidgetKeys.js.map +1 -1
- package/dist/esm/utils/mapList.js +71 -0
- package/dist/esm/utils/mapList.js.map +1 -0
- package/dist/esm/utils/rowClassRules.js +43 -0
- package/dist/esm/utils/rowClassRules.js.map +1 -0
- package/dist/esm/utils/validateManifestV2.compiled.js +3 -3
- package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
- package/dist/esm/utils/visibleWhen.js +19 -2
- package/dist/esm/utils/visibleWhen.js.map +1 -1
- package/dist/nextcloud-vue.cjs.js +9681 -7136
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +939 -376
- package/l10n/en.json +41 -1
- package/l10n/nl.json +39 -1
- package/package.json +1 -1
- package/src/components/CnActionsBar/CnActionsBar.md +1 -0
- package/src/components/CnActionsBar/CnActionsBar.vue +31 -4
- package/src/components/CnChartWidget/CnChartWidget.md +3 -2
- package/src/components/CnChartWidget/CnChartWidget.vue +42 -4
- package/src/components/CnChoiceCards/CnChoiceCards.md +39 -0
- package/src/components/CnChoiceCards/CnChoiceCards.vue +93 -16
- package/src/components/CnDashboardPage/CnDashboardPage.vue +110 -21
- package/src/components/CnExportsWidget/CnExportsWidget.vue +233 -0
- package/src/components/CnExportsWidget/index.js +7 -0
- package/src/components/CnFilesBrowser/CnFilesBrowser.vue +324 -0
- package/src/components/CnFilesBrowser/filesReview.js +57 -0
- package/src/components/CnGroupedCardsWidget/CnGroupedCardsWidget.vue +433 -0
- package/src/components/CnGroupedCardsWidget/index.js +28 -0
- package/src/components/CnIndexPage/CnIndexPage.md +5 -1
- package/src/components/CnIndexPage/CnIndexPage.vue +313 -9
- package/src/components/CnIndexPage/useNamedSource.js +30 -3
- package/src/components/CnMapWidget/CnMapWidget.vue +37 -0
- package/src/components/CnMenuWidget/CnMenuWidget.vue +25 -1
- package/src/components/CnObjectListWidget/CnObjectListWidget.vue +29 -1
- package/src/components/CnObjectSidebar/CnFilesTab.vue +15 -0
- package/src/components/CnOrderedListField/CnOrderedListField.vue +151 -5
- package/src/components/CnQuickFilterBar/CnQuickFilterBar.md +1 -0
- package/src/components/CnQuickFilterBar/CnQuickFilterBar.vue +159 -5
- package/src/components/CnSavedViewAlertWidget/CnSavedViewAlertWidget.vue +272 -0
- package/src/components/CnSavedViewAlertWidget/index.js +7 -0
- package/src/components/CnSetupWizard/CnSetupWizard.vue +35 -2
- package/src/components/CnWidgetGrid/builtInWidgets.js +4 -0
- package/src/components/CnWidgetGrid/registerDashboardWidgets.js +1 -0
- package/src/components/CnWidgetObjectTable/CnWidgetObjectTable.vue +2 -23
- package/src/components/index.js +3 -0
- package/src/composables/indexSources.js +175 -19
- package/src/composables/useEndpointSource.js +28 -6
- package/src/css/index-page.css +117 -0
- package/src/css/look-board-index.css +10 -0
- package/src/css/look-board.css +44 -0
- package/src/index.js +1 -0
- package/src/schemas/app-manifest-v2.schema.json +85 -3
- package/src/utils/builtInFormatters.js +24 -4
- package/src/utils/languageMapText.js +46 -0
- package/src/utils/libraryWidgetKeys.js +3 -0
- package/src/utils/mapList.js +67 -0
- package/src/utils/rowClassRules.js +39 -0
- package/src/utils/validateManifestV2.compiled.js +3 -3
- package/src/utils/visibleWhen.js +19 -2
|
@@ -6,6 +6,8 @@ import HandBackRight from 'vue-material-design-icons/HandBackRight.vue';
|
|
|
6
6
|
import LightningBolt from 'vue-material-design-icons/LightningBolt.vue';
|
|
7
7
|
import Pencil from 'vue-material-design-icons/Pencil.vue';
|
|
8
8
|
import { formatRelativeDate } from '../utils/boardDate.js';
|
|
9
|
+
import { fetchReferenceObjects } from '../utils/boardReferenceColumns.js';
|
|
10
|
+
import { fillTemplate } from '../utils/fillTemplate.js';
|
|
9
11
|
import { flowRunStatuses, FLOW_RUN_ERROR_STATUSES } from '../utils/flowRunStatus.js';
|
|
10
12
|
import { fetchGroupMembers, fetchStatuses, fetchPresence } from '../utils/nextcloudDirectory.js';
|
|
11
13
|
import { readPath } from '../utils/readPath.js';
|
|
@@ -529,6 +531,15 @@ function tasksSource() {
|
|
|
529
531
|
*/
|
|
530
532
|
loading: () => !!store.loading,
|
|
531
533
|
|
|
534
|
+
// The inbox pages: the page sends `limit` and `offset` and draws the
|
|
535
|
+
// pager from the datastore total.
|
|
536
|
+
pages: true,
|
|
537
|
+
|
|
538
|
+
/**
|
|
539
|
+
* @return {number} The datastore total, independent of the page size.
|
|
540
|
+
*/
|
|
541
|
+
total: () => Number(store.total) || 0,
|
|
542
|
+
|
|
532
543
|
/**
|
|
533
544
|
* Count the inbox for a config without touching the rows on screen,
|
|
534
545
|
* for a quick-filter tab with `showCount`.
|
|
@@ -649,6 +660,10 @@ function readRowsPath(body, path) {
|
|
|
649
660
|
* requested: page-config keys must never become query parameters. The list
|
|
650
661
|
* stays empty and one console error names the page.
|
|
651
662
|
*
|
|
663
|
+
* A quick filter with `showCount` is counted with `count(config)`: the same
|
|
664
|
+
* request with that tab's filter, its total read at `sourceConfig.totalPath`
|
|
665
|
+
* (`total` by default), else the number of rows the answer holds.
|
|
666
|
+
*
|
|
652
667
|
* @return {object} The source adapter.
|
|
653
668
|
* @spec openspec/changes/index-endpoint-source/specs/index-page/spec.md#requirement-an-index-page-can-list-rows-from-an-app-endpoint
|
|
654
669
|
*/
|
|
@@ -657,6 +672,36 @@ function endpointSource() {
|
|
|
657
672
|
let seq = 0;
|
|
658
673
|
let warned = false;
|
|
659
674
|
|
|
675
|
+
/**
|
|
676
|
+
* The query parameters for a config: every key but the url and the paths,
|
|
677
|
+
* empty values left out, a list joined by commas.
|
|
678
|
+
*
|
|
679
|
+
* @param {object} rest The config without `url`, `rowsPath` and `totalPath`.
|
|
680
|
+
* @return {object} The parameters.
|
|
681
|
+
*/
|
|
682
|
+
const paramsOf = (rest) => {
|
|
683
|
+
const params = {};
|
|
684
|
+
for (const [key, value] of Object.entries(rest)) {
|
|
685
|
+
if (value === undefined || value === null || value === '') {
|
|
686
|
+
continue
|
|
687
|
+
}
|
|
688
|
+
params[key] = Array.isArray(value) ? value.join(',') : (typeof value === 'object' ? JSON.stringify(value) : value);
|
|
689
|
+
}
|
|
690
|
+
return params
|
|
691
|
+
};
|
|
692
|
+
|
|
693
|
+
/**
|
|
694
|
+
* Whether a config can be requested: it names a url and is not the page
|
|
695
|
+
* config handed over in its place.
|
|
696
|
+
*
|
|
697
|
+
* @param {object} config The config.
|
|
698
|
+
* @return {boolean}
|
|
699
|
+
*/
|
|
700
|
+
const requestable = (config) => {
|
|
701
|
+
const url = config && config.url;
|
|
702
|
+
return typeof url === 'string' && url !== '' && !Object.hasOwn(config, 'entitySource')
|
|
703
|
+
};
|
|
704
|
+
|
|
660
705
|
return {
|
|
661
706
|
/**
|
|
662
707
|
* Fetch the rows.
|
|
@@ -665,10 +710,9 @@ function endpointSource() {
|
|
|
665
710
|
* @return {Promise<void>} Resolves when loaded; a failed request leaves no rows and rethrows.
|
|
666
711
|
*/
|
|
667
712
|
load: async (config) => {
|
|
668
|
-
const { url, rowsPath, ...rest } = config || {};
|
|
713
|
+
const { url, rowsPath, totalPath, ...rest } = config || {};
|
|
669
714
|
const mine = ++seq;
|
|
670
|
-
|
|
671
|
-
if (typeof url !== 'string' || url === '' || pageConfig) {
|
|
715
|
+
if (!requestable(config)) {
|
|
672
716
|
state.rows = [];
|
|
673
717
|
if (!warned) {
|
|
674
718
|
warned = true;
|
|
@@ -678,13 +722,7 @@ function endpointSource() {
|
|
|
678
722
|
}
|
|
679
723
|
return
|
|
680
724
|
}
|
|
681
|
-
const params =
|
|
682
|
-
for (const [key, value] of Object.entries(rest)) {
|
|
683
|
-
if (value === undefined || value === null || value === '') {
|
|
684
|
-
continue
|
|
685
|
-
}
|
|
686
|
-
params[key] = Array.isArray(value) ? value.join(',') : (typeof value === 'object' ? JSON.stringify(value) : value);
|
|
687
|
-
}
|
|
725
|
+
const params = paramsOf(rest);
|
|
688
726
|
state.loading = true;
|
|
689
727
|
try {
|
|
690
728
|
const { default: axios } = await import('@nextcloud/axios');
|
|
@@ -706,6 +744,29 @@ function endpointSource() {
|
|
|
706
744
|
}
|
|
707
745
|
},
|
|
708
746
|
|
|
747
|
+
/**
|
|
748
|
+
* Count the rows for a config without touching the rows on screen, for
|
|
749
|
+
* a quick-filter tab with `showCount`.
|
|
750
|
+
*
|
|
751
|
+
* @param {object} config The page's source config with the tab's filter merged in.
|
|
752
|
+
* @return {Promise<number>} The total, or NaN when nothing can be requested.
|
|
753
|
+
*/
|
|
754
|
+
count: async (config) => {
|
|
755
|
+
if (!requestable(config)) {
|
|
756
|
+
return Number.NaN
|
|
757
|
+
}
|
|
758
|
+
const { url, rowsPath, totalPath, ...rest } = config;
|
|
759
|
+
const { default: axios } = await import('@nextcloud/axios');
|
|
760
|
+
const res = await axios.get(generateUrl(url), { params: paramsOf(rest) });
|
|
761
|
+
const body = res ? res.data : null;
|
|
762
|
+
const total = body && typeof body === 'object' && !Array.isArray(body) ? readRowsPath(body, totalPath || 'total') : undefined;
|
|
763
|
+
if (typeof total === 'number' && Number.isFinite(total)) {
|
|
764
|
+
return total
|
|
765
|
+
}
|
|
766
|
+
const rows = Array.isArray(body) ? body : readRowsPath(body, rowsPath || 'results');
|
|
767
|
+
return Array.isArray(rows) ? rows.length : Number.NaN
|
|
768
|
+
},
|
|
769
|
+
|
|
709
770
|
/**
|
|
710
771
|
* @return {Array<object>} The rows the endpoint returned.
|
|
711
772
|
*/
|
|
@@ -738,39 +799,102 @@ function fillRowTemplate(template, row) {
|
|
|
738
799
|
* and its count (DqZoekresultaten).
|
|
739
800
|
*
|
|
740
801
|
* `sourceConfig.kinds` lists what is searched:
|
|
741
|
-
* `{ id, label, register, schema, titleField?, subtitleField?, statusField?, href?, limit? }`
|
|
802
|
+
* `{ id, label, register, schema, titleField?, subtitleField?, statusField?, statusResolve?, linkedField?, linkedTemplate?, href?, limit? }`
|
|
742
803
|
* for objects (OpenRegister's `_search`, so the reader sees what they may
|
|
743
804
|
* read), or `{ id, label, files: true, limit? }` for the reader's files
|
|
744
805
|
* (Nextcloud's unified search). The term is `sourceConfig.term`, else the
|
|
745
806
|
* address's `?q=` (or `sourceConfig.termQuery`). A kind that fails shows no
|
|
746
807
|
* rows and no count; the others still answer.
|
|
747
808
|
*
|
|
809
|
+
* The kind's `label` goes through the app's translate (the "Soort" cell and
|
|
810
|
+
* the quick filters). `statusResolve: { register?, schema, labelField? }`
|
|
811
|
+
* reads `statusField` as a reference and shows the referenced object's label
|
|
812
|
+
* (`labelField`, else `title`, then `name`); the status column is a pill,
|
|
813
|
+
* coloured by `sourceConfig.statusColorMap`. `linkedTemplate` (a field
|
|
814
|
+
* template, "{case.title}") or `linkedField` (a path) fills the "Linked"
|
|
815
|
+
* column, drawn when a kind declares one; `sourceConfig.linkedLabel` names it.
|
|
816
|
+
* The page's title and count line can name the term as `{term}`, and the
|
|
817
|
+
* count is the active kind's total. Kind, link and status are filterable.
|
|
818
|
+
*
|
|
748
819
|
* @param {object} [config] The page's source config.
|
|
820
|
+
* @param {object} [context] The page's helpers.
|
|
821
|
+
* @param {Function} [context.translate] The app's translate.
|
|
749
822
|
* @return {object} The source adapter.
|
|
750
823
|
* @spec openspec/changes/index-search-source/specs/index-page/spec.md#requirement-an-index-page-can-search-several-schemas-and-files
|
|
751
824
|
*/
|
|
752
|
-
function searchSource(config = {}) {
|
|
825
|
+
function searchSource(config = {}, context = {}) {
|
|
826
|
+
const translate$1 = typeof context.translate === 'function' ? context.translate : (text) => text;
|
|
753
827
|
const kinds = (Array.isArray(config && config.kinds) ? config.kinds : [])
|
|
754
|
-
.filter((kind) => kind && typeof kind.id === 'string' && kind.id !== '' && (kind.files === true || (kind.register && kind.schema)))
|
|
755
|
-
|
|
828
|
+
.filter((kind) => kind && typeof kind.id === 'string' && kind.id !== '' && (kind.files === true || (kind.register && kind.schema)))
|
|
829
|
+
.map((kind) => ({ ...kind, label: translate$1(String(kind.label || kind.id)) }));
|
|
830
|
+
const hasLinked = kinds.some((kind) => kind.linkedTemplate || kind.linkedField);
|
|
831
|
+
const state = reactive({ rows: [], totals: {}, loading: false, kind: 'all', term: '', filters: {} });
|
|
756
832
|
let seq = 0;
|
|
757
833
|
|
|
834
|
+
/**
|
|
835
|
+
* The labels of the objects a kind's status points at, by id: the
|
|
836
|
+
* referenced schema read once per search.
|
|
837
|
+
*
|
|
838
|
+
* @param {object} kind The kind with `statusResolve`.
|
|
839
|
+
* @return {Promise<Map<string, string>>} Labels by id; empty when it cannot be read.
|
|
840
|
+
*/
|
|
841
|
+
const statusLabels = async (kind) => {
|
|
842
|
+
const resolve = kind.statusResolve;
|
|
843
|
+
if (!resolve || !resolve.schema) {
|
|
844
|
+
return new Map()
|
|
845
|
+
}
|
|
846
|
+
const objects = await fetchReferenceObjects({ register: resolve.register || kind.register, schema: resolve.schema }).catch(() => []);
|
|
847
|
+
const labels = new Map();
|
|
848
|
+
for (const object of objects) {
|
|
849
|
+
const id = object.id || object.uuid || (object['@self'] && object['@self'].id);
|
|
850
|
+
const label = readPath(object, resolve.labelField || 'title') ?? object.name;
|
|
851
|
+
if (id !== undefined && label !== undefined && label !== null) {
|
|
852
|
+
labels.set(String(id), String(label));
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
return labels
|
|
856
|
+
};
|
|
857
|
+
|
|
858
|
+
/**
|
|
859
|
+
* What a row shows in the Linked column.
|
|
860
|
+
*
|
|
861
|
+
* @param {object} kind The row's kind.
|
|
862
|
+
* @param {object} object The found object.
|
|
863
|
+
* @return {string}
|
|
864
|
+
*/
|
|
865
|
+
const linkedOf = (kind, object) => {
|
|
866
|
+
if (kind.linkedTemplate) {
|
|
867
|
+
return fillTemplate(translate$1(kind.linkedTemplate), object)
|
|
868
|
+
}
|
|
869
|
+
if (kind.linkedField) {
|
|
870
|
+
const value = readPath(object, kind.linkedField);
|
|
871
|
+
return value === undefined || value === null ? '' : String(value)
|
|
872
|
+
}
|
|
873
|
+
return ''
|
|
874
|
+
};
|
|
875
|
+
|
|
758
876
|
const searchObjects = async (axios, kind, term) => {
|
|
759
877
|
const url = generateUrl('/apps/openregister/api/objects/{register}/{schema}', { register: kind.register, schema: kind.schema });
|
|
760
878
|
const res = await axios.get(url, { params: { _search: term, _limit: kind.limit || 20 } });
|
|
761
879
|
const body = (res && res.data) || {};
|
|
762
880
|
const results = Array.isArray(body.results) ? body.results : (Array.isArray(body) ? body : []);
|
|
881
|
+
const labels = kind.statusResolve && kind.statusField ? await statusLabels(kind) : null;
|
|
763
882
|
return {
|
|
764
883
|
total: typeof body.total === 'number' ? body.total : results.length,
|
|
765
884
|
rows: results.map((object) => {
|
|
766
885
|
const id = object.id || object.uuid || (object['@self'] && object['@self'].id);
|
|
886
|
+
const rawStatus = kind.statusField ? readPath(object, kind.statusField) : undefined;
|
|
887
|
+
const status = rawStatus === undefined || rawStatus === null
|
|
888
|
+
? ''
|
|
889
|
+
: (labels ? (labels.get(String(rawStatus)) || '') : String(rawStatus));
|
|
767
890
|
return {
|
|
768
891
|
id: `${kind.id}:${id}`,
|
|
769
892
|
kind: kind.id,
|
|
770
893
|
kindLabel: kind.label,
|
|
771
894
|
title: String(readPath(object, kind.titleField || 'title') ?? object.name ?? id ?? ''),
|
|
772
895
|
subtitle: kind.subtitleField ? String(readPath(object, kind.subtitleField) ?? '') : '',
|
|
773
|
-
status
|
|
896
|
+
status,
|
|
897
|
+
linked: linkedOf(kind, object),
|
|
774
898
|
href: kind.href ? generateUrl(fillRowTemplate(kind.href, { ...object, id })) : '',
|
|
775
899
|
object,
|
|
776
900
|
}
|
|
@@ -793,6 +917,7 @@ function searchSource(config = {}) {
|
|
|
793
917
|
title: entry.title || '',
|
|
794
918
|
subtitle: entry.subline || '',
|
|
795
919
|
status: '',
|
|
920
|
+
linked: '',
|
|
796
921
|
href: entry.resourceUrl || '',
|
|
797
922
|
})),
|
|
798
923
|
}
|
|
@@ -807,6 +932,17 @@ function searchSource(config = {}) {
|
|
|
807
932
|
*/
|
|
808
933
|
load: async (cfg) => {
|
|
809
934
|
state.kind = cfg && typeof cfg.kind === 'string' ? cfg.kind : 'all';
|
|
935
|
+
// The header filters on Kind, Linked and Status narrow the answer
|
|
936
|
+
// already fetched; they do not search again.
|
|
937
|
+
const filters = {};
|
|
938
|
+
for (const key of ['kindLabel', 'linked', 'status']) {
|
|
939
|
+
const value = cfg && cfg[key];
|
|
940
|
+
const values = (Array.isArray(value) ? value : (value === undefined || value === null || value === '' ? [] : [value])).map(String);
|
|
941
|
+
if (values.length > 0) {
|
|
942
|
+
filters[key] = values;
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
state.filters = filters;
|
|
810
946
|
const query = typeof window !== 'undefined' ? new URLSearchParams(window.location.search) : null;
|
|
811
947
|
const term = String((cfg && cfg.term) || (query && query.get((cfg && cfg.termQuery) || 'q')) || '').trim();
|
|
812
948
|
const mine = ++seq;
|
|
@@ -838,7 +974,20 @@ function searchSource(config = {}) {
|
|
|
838
974
|
/**
|
|
839
975
|
* @return {Array<object>} The results of the active kind, or all of them.
|
|
840
976
|
*/
|
|
841
|
-
rows: () => (state.kind === 'all' ? state.rows : state.rows.filter((row) => row.kind === state.kind))
|
|
977
|
+
rows: () => (state.kind === 'all' ? state.rows : state.rows.filter((row) => row.kind === state.kind))
|
|
978
|
+
.filter((row) => Object.entries(state.filters).every(([key, values]) => values.includes(String(row[key])))),
|
|
979
|
+
|
|
980
|
+
/**
|
|
981
|
+
* @return {string} The term searched for, for a `{term}` in the title or count line.
|
|
982
|
+
*/
|
|
983
|
+
term: () => state.term,
|
|
984
|
+
|
|
985
|
+
/**
|
|
986
|
+
* @return {number} The active kind's total, or every kind's together on All.
|
|
987
|
+
*/
|
|
988
|
+
total: () => (state.kind === 'all'
|
|
989
|
+
? Object.values(state.totals).reduce((sum, value) => sum + value, 0)
|
|
990
|
+
: (state.totals[state.kind] || 0)),
|
|
842
991
|
|
|
843
992
|
/**
|
|
844
993
|
* @return {boolean} Whether a search is in flight.
|
|
@@ -847,8 +996,14 @@ function searchSource(config = {}) {
|
|
|
847
996
|
|
|
848
997
|
columns: [
|
|
849
998
|
{ key: 'title', label: translate('nextcloud-vue', 'Result'), secondary: 'subtitle' },
|
|
850
|
-
{ key: 'kindLabel', label: translate('nextcloud-vue', 'Kind') },
|
|
851
|
-
{ key: '
|
|
999
|
+
{ key: 'kindLabel', label: translate('nextcloud-vue', 'Kind'), enum: kinds.map((kind) => kind.label) },
|
|
1000
|
+
...(hasLinked ? [{ key: 'linked', label: config.linkedLabel ? translate$1(config.linkedLabel) : translate('nextcloud-vue', 'Linked') }] : []),
|
|
1001
|
+
{
|
|
1002
|
+
key: 'status',
|
|
1003
|
+
label: translate('nextcloud-vue', 'Status'),
|
|
1004
|
+
widget: 'badge',
|
|
1005
|
+
widgetProps: { colorMap: (config && config.statusColorMap) || {} },
|
|
1006
|
+
},
|
|
852
1007
|
],
|
|
853
1008
|
|
|
854
1009
|
quickFilters: kinds.length > 0
|
|
@@ -1119,10 +1274,11 @@ const indexSources = {
|
|
|
1119
1274
|
*
|
|
1120
1275
|
* @param {string} name The source name from `config.source`.
|
|
1121
1276
|
* @param {object} [config] The page's source config, for a source that builds its tabs from it.
|
|
1277
|
+
* @param {object} [context] The page's helpers a source may use, such as `translate` (the app's catalogue).
|
|
1122
1278
|
*
|
|
1123
1279
|
* @return {object|null} The adapter, or null when the name is not registered.
|
|
1124
1280
|
*/
|
|
1125
|
-
function resolveIndexSource(name, config) {
|
|
1281
|
+
function resolveIndexSource(name, config, context) {
|
|
1126
1282
|
const key = String(name || '');
|
|
1127
1283
|
if (!key) {
|
|
1128
1284
|
return null
|
|
@@ -1135,7 +1291,7 @@ function resolveIndexSource(name, config) {
|
|
|
1135
1291
|
return null
|
|
1136
1292
|
}
|
|
1137
1293
|
|
|
1138
|
-
return factory(config || {})
|
|
1294
|
+
return factory(config || {}, context || {})
|
|
1139
1295
|
}
|
|
1140
1296
|
|
|
1141
1297
|
/**
|