@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
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import axios__default from '@nextcloud/axios';
|
|
2
|
+
import { generateUrl } from '@nextcloud/router';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* SPDX-FileCopyrightText: 2026 Conduction B.V.
|
|
6
|
+
* SPDX-License-Identifier: EUPL-1.2
|
|
7
|
+
*
|
|
8
|
+
* The rules OpenRegister's engine holds for a schema, read rather than kept:
|
|
9
|
+
* the closed sets (vocabulary), the inventory in evaluation order, and a dry
|
|
10
|
+
* run that writes nothing.
|
|
11
|
+
*
|
|
12
|
+
* A rule is keyed on its id (`<kind>:<schemaSlug>:<key>`), never on its
|
|
13
|
+
* position: the order belongs to the pipeline and moves the day a kind is
|
|
14
|
+
* added. Kind labels come from the vocabulary endpoint, so a kind added later
|
|
15
|
+
* renders instead of blanking.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
/** Where OpenRegister publishes the three closed sets. */
|
|
20
|
+
const RULE_VOCABULARY_PATH = '/apps/openregister/api/rules/vocabulary';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @param {string} schema The schema slug.
|
|
24
|
+
* @return {string} The url of the schema's rule inventory.
|
|
25
|
+
*/
|
|
26
|
+
function ruleInventoryUrl(schema) {
|
|
27
|
+
return generateUrl(`/apps/openregister/api/schemas/${encodeURIComponent(schema)}/rules`)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @param {string} schema The schema slug.
|
|
32
|
+
* @param {string} ruleId The rule id.
|
|
33
|
+
* @return {string} The url of the rule's dry run.
|
|
34
|
+
*/
|
|
35
|
+
function ruleEvaluateUrl(schema, ruleId) {
|
|
36
|
+
return generateUrl(`/apps/openregister/api/schemas/${encodeURIComponent(schema)}/rules/${encodeURIComponent(ruleId)}/evaluate`)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* @param {unknown} data An answer.
|
|
41
|
+
* @return {boolean} Whether it carries the three sets.
|
|
42
|
+
*/
|
|
43
|
+
function isRuleVocabulary(data) {
|
|
44
|
+
return !!data && Array.isArray(data.kinds) && Array.isArray(data.verdicts) && Array.isArray(data.actions)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* The kinds the engine publishes, keyed by kind.
|
|
49
|
+
*
|
|
50
|
+
* @param {object} vocabulary The vocabulary answer.
|
|
51
|
+
* @return {object} The descriptors, by kind.
|
|
52
|
+
*/
|
|
53
|
+
function kindsByName(vocabulary) {
|
|
54
|
+
const kinds = {};
|
|
55
|
+
if (!isRuleVocabulary(vocabulary)) {
|
|
56
|
+
return kinds
|
|
57
|
+
}
|
|
58
|
+
vocabulary.kinds.forEach((kind) => {
|
|
59
|
+
const name = String((kind && kind.kind) ?? '');
|
|
60
|
+
if (name !== '') {
|
|
61
|
+
kinds[name] = kind;
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
return kinds
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Read the vocabulary. A refusal answers the empty sets: the vocabulary is open
|
|
69
|
+
* to any signed-in caller, so a refusal means an instance that predates the
|
|
70
|
+
* engine, and each rule then shows its own kind string.
|
|
71
|
+
*
|
|
72
|
+
* @return {Promise<object>} The vocabulary, possibly empty.
|
|
73
|
+
*/
|
|
74
|
+
async function fetchRuleVocabulary() {
|
|
75
|
+
try {
|
|
76
|
+
const { data } = await axios__default.get(generateUrl(RULE_VOCABULARY_PATH));
|
|
77
|
+
return isRuleVocabulary(data) ? data : { kinds: [], verdicts: [], actions: [] }
|
|
78
|
+
} catch {
|
|
79
|
+
return { kinds: [], verdicts: [], actions: [] }
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Read one schema's rules, in the order the engine evaluates them. The
|
|
85
|
+
* inventory is an admin read; a refusal throws for the caller to say so.
|
|
86
|
+
*
|
|
87
|
+
* @param {string} schema The schema slug.
|
|
88
|
+
* @return {Promise<Array<object>>} The rules.
|
|
89
|
+
*/
|
|
90
|
+
async function fetchSchemaRules(schema) {
|
|
91
|
+
const { data } = await axios__default.get(ruleInventoryUrl(schema));
|
|
92
|
+
return Array.isArray(data && data.rules) ? data.rules : []
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Try one rule against one stored object, writing nothing.
|
|
97
|
+
*
|
|
98
|
+
* @param {string} schema The schema slug.
|
|
99
|
+
* @param {string} ruleId The rule id.
|
|
100
|
+
* @param {string} register The register slug the object lives in.
|
|
101
|
+
* @param {string} objectId The object to try it against.
|
|
102
|
+
* @return {Promise<object>} The trial result, carrying `trace`.
|
|
103
|
+
*/
|
|
104
|
+
async function evaluateRule(schema, ruleId, register, objectId) {
|
|
105
|
+
const { data } = await axios__default.post(ruleEvaluateUrl(schema, ruleId), { register, objectId });
|
|
106
|
+
return data || {}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* The trace of a trial. `operand` and `operandValue` are what turn "why did this
|
|
111
|
+
* rule not fire" into a fact, so they are shown beside the verdict.
|
|
112
|
+
*
|
|
113
|
+
* @param {object} result The trial result.
|
|
114
|
+
* @return {{verdict: string, operand: string, operandValue: string, message: string}} The trace.
|
|
115
|
+
*/
|
|
116
|
+
function traceOf(result) {
|
|
117
|
+
const trace = (result && result.trace) || {};
|
|
118
|
+
return {
|
|
119
|
+
verdict: String(trace.verdict ?? ''),
|
|
120
|
+
operand: String(trace.operand ?? ''),
|
|
121
|
+
operandValue: String(trace.operandValue ?? ''),
|
|
122
|
+
message: String(trace.message ?? (result && result.error && result.error.message) ?? ''),
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export { RULE_VOCABULARY_PATH, evaluateRule, fetchRuleVocabulary, fetchSchemaRules, isRuleVocabulary, kindsByName, ruleEvaluateUrl, ruleInventoryUrl, traceOf };
|
|
127
|
+
//# sourceMappingURL=schemaRules.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schemaRules.js","sources":["../../../../src/components/CnSchemaRulesWidget/schemaRules.js"],"sourcesContent":["/**\n * SPDX-FileCopyrightText: 2026 Conduction B.V.\n * SPDX-License-Identifier: EUPL-1.2\n *\n * The rules OpenRegister's engine holds for a schema, read rather than kept:\n * the closed sets (vocabulary), the inventory in evaluation order, and a dry\n * run that writes nothing.\n *\n * A rule is keyed on its id (`<kind>:<schemaSlug>:<key>`), never on its\n * position: the order belongs to the pipeline and moves the day a kind is\n * added. Kind labels come from the vocabulary endpoint, so a kind added later\n * renders instead of blanking.\n */\n\nimport axios from '@nextcloud/axios'\nimport { generateUrl } from '@nextcloud/router'\n\n/** Where OpenRegister publishes the three closed sets. */\nexport const RULE_VOCABULARY_PATH = '/apps/openregister/api/rules/vocabulary'\n\n/**\n * @param {string} schema The schema slug.\n * @return {string} The url of the schema's rule inventory.\n */\nexport function ruleInventoryUrl(schema) {\n\treturn generateUrl(`/apps/openregister/api/schemas/${encodeURIComponent(schema)}/rules`)\n}\n\n/**\n * @param {string} schema The schema slug.\n * @param {string} ruleId The rule id.\n * @return {string} The url of the rule's dry run.\n */\nexport function ruleEvaluateUrl(schema, ruleId) {\n\treturn generateUrl(`/apps/openregister/api/schemas/${encodeURIComponent(schema)}/rules/${encodeURIComponent(ruleId)}/evaluate`)\n}\n\n/**\n * @param {unknown} data An answer.\n * @return {boolean} Whether it carries the three sets.\n */\nexport function isRuleVocabulary(data) {\n\treturn !!data && Array.isArray(data.kinds) && Array.isArray(data.verdicts) && Array.isArray(data.actions)\n}\n\n/**\n * The kinds the engine publishes, keyed by kind.\n *\n * @param {object} vocabulary The vocabulary answer.\n * @return {object} The descriptors, by kind.\n */\nexport function kindsByName(vocabulary) {\n\tconst kinds = {}\n\tif (!isRuleVocabulary(vocabulary)) {\n\t\treturn kinds\n\t}\n\tvocabulary.kinds.forEach((kind) => {\n\t\tconst name = String((kind && kind.kind) ?? '')\n\t\tif (name !== '') {\n\t\t\tkinds[name] = kind\n\t\t}\n\t})\n\treturn kinds\n}\n\n/**\n * Read the vocabulary. A refusal answers the empty sets: the vocabulary is open\n * to any signed-in caller, so a refusal means an instance that predates the\n * engine, and each rule then shows its own kind string.\n *\n * @return {Promise<object>} The vocabulary, possibly empty.\n */\nexport async function fetchRuleVocabulary() {\n\ttry {\n\t\tconst { data } = await axios.get(generateUrl(RULE_VOCABULARY_PATH))\n\t\treturn isRuleVocabulary(data) ? data : { kinds: [], verdicts: [], actions: [] }\n\t} catch {\n\t\treturn { kinds: [], verdicts: [], actions: [] }\n\t}\n}\n\n/**\n * Read one schema's rules, in the order the engine evaluates them. The\n * inventory is an admin read; a refusal throws for the caller to say so.\n *\n * @param {string} schema The schema slug.\n * @return {Promise<Array<object>>} The rules.\n */\nexport async function fetchSchemaRules(schema) {\n\tconst { data } = await axios.get(ruleInventoryUrl(schema))\n\treturn Array.isArray(data && data.rules) ? data.rules : []\n}\n\n/**\n * Try one rule against one stored object, writing nothing.\n *\n * @param {string} schema The schema slug.\n * @param {string} ruleId The rule id.\n * @param {string} register The register slug the object lives in.\n * @param {string} objectId The object to try it against.\n * @return {Promise<object>} The trial result, carrying `trace`.\n */\nexport async function evaluateRule(schema, ruleId, register, objectId) {\n\tconst { data } = await axios.post(ruleEvaluateUrl(schema, ruleId), { register, objectId })\n\treturn data || {}\n}\n\n/**\n * The trace of a trial. `operand` and `operandValue` are what turn \"why did this\n * rule not fire\" into a fact, so they are shown beside the verdict.\n *\n * @param {object} result The trial result.\n * @return {{verdict: string, operand: string, operandValue: string, message: string}} The trace.\n */\nexport function traceOf(result) {\n\tconst trace = (result && result.trace) || {}\n\treturn {\n\t\tverdict: String(trace.verdict ?? ''),\n\t\toperand: String(trace.operand ?? ''),\n\t\toperandValue: String(trace.operandValue ?? ''),\n\t\tmessage: String(trace.message ?? (result && result.error && result.error.message) ?? ''),\n\t}\n}\n"],"names":["axios"],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import script from './CnSearchIndexStatus.vue2.js';
|
|
2
|
+
import { render } from './CnSearchIndexStatus.vue3.js';
|
|
3
|
+
|
|
4
|
+
script.render = render;
|
|
5
|
+
script.__scopeId = "data-v-52b442a4";
|
|
6
|
+
const __sfc_main = script;
|
|
7
|
+
|
|
8
|
+
export { __sfc_main as default };
|
|
9
|
+
//# sourceMappingURL=CnSearchIndexStatus.vue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CnSearchIndexStatus.vue.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { translate, getCanonicalLocale } from '@nextcloud/l10n';
|
|
2
|
+
import { NcLoadingIcon, NcNoteCard } from '@nextcloud/vue';
|
|
3
|
+
import { SEARCH_INDEX_STATUS_URL, SEARCH_INDEX_COMMAND, fetchSearchIndexStatus } from './searchIndexStatus.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* CnSearchIndexStatus: the state of OpenRegister's search indexes (tables in
|
|
7
|
+
* scope, indexes on them, the last maintenance run, whether a rebuild locks a
|
|
8
|
+
* table), read live and never copied. The acts are named, not offered: a
|
|
9
|
+
* rebuild walks every table in scope and nothing stops one from a settings
|
|
10
|
+
* page, so the occ verbs are printed for somebody with a shell.
|
|
11
|
+
*
|
|
12
|
+
* @spec openspec/changes/search-index-status/specs/search-index-status/spec.md
|
|
13
|
+
*/
|
|
14
|
+
var script = {
|
|
15
|
+
name: 'CnSearchIndexStatus',
|
|
16
|
+
|
|
17
|
+
components: { NcLoadingIcon, NcNoteCard },
|
|
18
|
+
|
|
19
|
+
props: {
|
|
20
|
+
/** The app path OpenRegister reports its indexes at. */
|
|
21
|
+
source: { type: String, default: SEARCH_INDEX_STATUS_URL },
|
|
22
|
+
/** The occ command that acts on the indexes. */
|
|
23
|
+
command: { type: String, default: SEARCH_INDEX_COMMAND },
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
data() {
|
|
27
|
+
return {
|
|
28
|
+
loading: true,
|
|
29
|
+
error: '',
|
|
30
|
+
status: { concurrentRebuildSupported: false, tables: {}, tableCount: 0, indexCount: 0, lastRun: null },
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
|
|
34
|
+
computed: {
|
|
35
|
+
/** @return {string} When maintenance last ran, or that it never has. */
|
|
36
|
+
lastRun() {
|
|
37
|
+
if (!this.status.lastRun) {
|
|
38
|
+
return translate('nextcloud-vue', 'Never')
|
|
39
|
+
}
|
|
40
|
+
const when = new Date(this.status.lastRun);
|
|
41
|
+
if (Number.isNaN(when.getTime())) {
|
|
42
|
+
return String(this.status.lastRun)
|
|
43
|
+
}
|
|
44
|
+
return when.toLocaleString(getCanonicalLocale(), { dateStyle: 'medium', timeStyle: 'short' })
|
|
45
|
+
},
|
|
46
|
+
|
|
47
|
+
/** @return {string} Whether a rebuild locks the table, in words. */
|
|
48
|
+
concurrent() {
|
|
49
|
+
return this.status.concurrentRebuildSupported === true
|
|
50
|
+
? translate('nextcloud-vue', 'Yes')
|
|
51
|
+
: translate('nextcloud-vue', 'No, a rebuild locks the table it is on')
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
mounted() {
|
|
56
|
+
this.load();
|
|
57
|
+
},
|
|
58
|
+
|
|
59
|
+
methods: {
|
|
60
|
+
t: translate,
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Read what OpenRegister says about its indexes.
|
|
64
|
+
*
|
|
65
|
+
* @return {Promise<void>}
|
|
66
|
+
*/
|
|
67
|
+
async load() {
|
|
68
|
+
this.loading = true;
|
|
69
|
+
this.error = '';
|
|
70
|
+
try {
|
|
71
|
+
this.status = await fetchSearchIndexStatus(this.source);
|
|
72
|
+
} catch (e) {
|
|
73
|
+
this.error = String((e && e.message) || e);
|
|
74
|
+
} finally {
|
|
75
|
+
this.loading = false;
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export { script as default };
|
|
82
|
+
//# sourceMappingURL=CnSearchIndexStatus.vue2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CnSearchIndexStatus.vue2.js","sources":["../../../../src/components/CnSearchIndexStatus/CnSearchIndexStatus.vue"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n<template>\n\t<div class=\"cn-search-index-status\" data-testid=\"cn-search-index-status\">\n\t\t<NcLoadingIcon v-if=\"loading\" :size=\"24\" :name=\"t('nextcloud-vue', 'Loading')\" />\n\t\t<NcNoteCard v-else-if=\"error\" type=\"error\" data-testid=\"cn-search-index-error\">\n\t\t\t{{ error }}\n\t\t</NcNoteCard>\n\t\t<template v-else>\n\t\t\t<dl class=\"cn-search-index-status__figures\">\n\t\t\t\t<div>\n\t\t\t\t\t<dt>{{ t('nextcloud-vue', 'Tables in scope') }}</dt>\n\t\t\t\t\t<dd data-testid=\"cn-search-index-tables\">\n\t\t\t\t\t\t{{ status.tableCount }}\n\t\t\t\t\t</dd>\n\t\t\t\t</div>\n\t\t\t\t<div>\n\t\t\t\t\t<dt>{{ t('nextcloud-vue', 'Indexes on them') }}</dt>\n\t\t\t\t\t<dd data-testid=\"cn-search-index-indexes\">\n\t\t\t\t\t\t{{ status.indexCount }}\n\t\t\t\t\t</dd>\n\t\t\t\t</div>\n\t\t\t\t<div>\n\t\t\t\t\t<dt>{{ t('nextcloud-vue', 'Last run') }}</dt>\n\t\t\t\t\t<dd data-testid=\"cn-search-index-last-run\">\n\t\t\t\t\t\t{{ lastRun }}\n\t\t\t\t\t</dd>\n\t\t\t\t</div>\n\t\t\t\t<div>\n\t\t\t\t\t<dt>{{ t('nextcloud-vue', 'Rebuild without locking') }}</dt>\n\t\t\t\t\t<dd data-testid=\"cn-search-index-concurrent\">\n\t\t\t\t\t\t{{ concurrent }}\n\t\t\t\t\t</dd>\n\t\t\t\t</div>\n\t\t\t</dl>\n\t\t\t<p data-testid=\"cn-search-index-commands\">\n\t\t\t\t{{ t('nextcloud-vue', 'Run {command} status on the server for the same figures, and {command} rebuild --apply after a schema change.', { command }) }}\n\t\t\t</p>\n\t\t</template>\n\t</div>\n</template>\n\n<script>\nimport { getCanonicalLocale, translate as t } from '@nextcloud/l10n'\nimport { NcLoadingIcon, NcNoteCard } from '@nextcloud/vue'\nimport { fetchSearchIndexStatus, SEARCH_INDEX_COMMAND, SEARCH_INDEX_STATUS_URL } from './searchIndexStatus.js'\n\n/**\n * CnSearchIndexStatus: the state of OpenRegister's search indexes (tables in\n * scope, indexes on them, the last maintenance run, whether a rebuild locks a\n * table), read live and never copied. The acts are named, not offered: a\n * rebuild walks every table in scope and nothing stops one from a settings\n * page, so the occ verbs are printed for somebody with a shell.\n *\n * @spec openspec/changes/search-index-status/specs/search-index-status/spec.md\n */\nexport default {\n\tname: 'CnSearchIndexStatus',\n\n\tcomponents: { NcLoadingIcon, NcNoteCard },\n\n\tprops: {\n\t\t/** The app path OpenRegister reports its indexes at. */\n\t\tsource: { type: String, default: SEARCH_INDEX_STATUS_URL },\n\t\t/** The occ command that acts on the indexes. */\n\t\tcommand: { type: String, default: SEARCH_INDEX_COMMAND },\n\t},\n\n\tdata() {\n\t\treturn {\n\t\t\tloading: true,\n\t\t\terror: '',\n\t\t\tstatus: { concurrentRebuildSupported: false, tables: {}, tableCount: 0, indexCount: 0, lastRun: null },\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/** @return {string} When maintenance last ran, or that it never has. */\n\t\tlastRun() {\n\t\t\tif (!this.status.lastRun) {\n\t\t\t\treturn t('nextcloud-vue', 'Never')\n\t\t\t}\n\t\t\tconst when = new Date(this.status.lastRun)\n\t\t\tif (Number.isNaN(when.getTime())) {\n\t\t\t\treturn String(this.status.lastRun)\n\t\t\t}\n\t\t\treturn when.toLocaleString(getCanonicalLocale(), { dateStyle: 'medium', timeStyle: 'short' })\n\t\t},\n\n\t\t/** @return {string} Whether a rebuild locks the table, in words. */\n\t\tconcurrent() {\n\t\t\treturn this.status.concurrentRebuildSupported === true\n\t\t\t\t? t('nextcloud-vue', 'Yes')\n\t\t\t\t: t('nextcloud-vue', 'No, a rebuild locks the table it is on')\n\t\t},\n\t},\n\n\tmounted() {\n\t\tthis.load()\n\t},\n\n\tmethods: {\n\t\tt,\n\n\t\t/**\n\t\t * Read what OpenRegister says about its indexes.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync load() {\n\t\t\tthis.loading = true\n\t\t\tthis.error = ''\n\t\t\ttry {\n\t\t\t\tthis.status = await fetchSearchIndexStatus(this.source)\n\t\t\t} catch (e) {\n\t\t\t\tthis.error = String((e && e.message) || e)\n\t\t\t} finally {\n\t\t\t\tthis.loading = false\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n/* Label above value, and the label wraps: Nextcloud's settings stylesheet gives a `dt` a fixed width. */\n.cn-search-index-status__figures {\n\tdisplay: grid;\n\tgrid-template-columns: repeat(auto-fit, minmax(160px, 1fr));\n\tgap: 16px 24px;\n\tmargin-block: 0 12px;\n}\n\n.cn-search-index-status__figures > div {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 2px;\n\tmin-width: 0;\n}\n\n.cn-search-index-status__figures dt {\n\tdisplay: block;\n\tfloat: none;\n\twidth: auto;\n\tmargin: 0;\n\tpadding: 0;\n\ttext-align: start;\n\twhite-space: normal;\n\toverflow-wrap: anywhere;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-search-index-status__figures dd {\n\tfont-weight: bold;\n\tmargin: 0;\n\toverflow-wrap: anywhere;\n}\n</style>\n"],"names":["t"],"mappings":";;;;AAiDA;AACC;AACA;;;;AAIA;AACA;;AAED,aAAe;CACd,IAAI,EAAE,qBAAqB;;AAE3B,CAAA,UAAU,EAAE,EAAE,aAAa,EAAE,YAAY;;AAEzC,CAAA,KAAK,EAAE;;EAEN,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,uBAAsB,EAAG;AAC1D;EACA,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAmB,EAAG;EACxD;;AAED,CAAA,IAAI,GAAG;AACN,EAAA,OAAO;GACN,OAAO,EAAE,IAAI;AACb,GAAA,KAAK,EAAE,EAAE;AACT,GAAA,MAAM,EAAE,EAAE,0BAA0B,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM;AACvG,GAAA;EACA;;AAED,CAAA,QAAQ,EAAE;;AAET,EAAA,OAAO,GAAG;GACT,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE;AACzB,IAAA,OAAOA,SAAC,CAAC,eAAe,EAAE,OAAO,CAAA;AAClC,IAAA;AACA,GAAA,MAAM,IAAK,GAAE,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAA;AACzC,GAAA,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE;AACjC,IAAA,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAA;AAClC,IAAA;AACA,GAAA,OAAO,IAAI,CAAC,cAAc,CAAC,kBAAkB,EAAE,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,CAAA;GAC5F;;;EAGD,UAAU,GAAG;GACZ,OAAO,IAAI,CAAC,MAAM,CAAC,0BAAyB,KAAM,IAAG;MAClDA,SAAC,CAAC,eAAe,EAAE,KAAK,CAAA;MACxBA,SAAC,CAAC,eAAe,EAAE,wCAAwC,CAAA;GAC9D;EACD;;AAED,CAAA,OAAO,GAAG;EACT,IAAI,CAAC,IAAI,GAAC;EACV;;AAED,CAAA,OAAO,EAAE;KACRA,SAAC;;AAED;AACC;AACA;;;EAGD,MAAM,IAAI,GAAG;AACZ,GAAA,IAAI,CAAC,OAAM,GAAI,KAAG;GAClB,IAAI,CAAC,KAAM,GAAE,GAAC;AACd,GAAA,IAAI;IACH,IAAI,CAAC,MAAO,GAAE,MAAM,sBAAsB,CAAC,IAAI,CAAC,MAAM,EAAA;AACvD,IAAA,CAAE,OAAO,CAAC,EAAE;AACX,IAAA,IAAI,CAAC,KAAI,GAAI,MAAM,CAAC,CAAC,CAAE,IAAG,CAAC,CAAC,OAAO,KAAK,CAAC,EAAA;AAC1C,IAAA,SAAU;AACT,IAAA,IAAI,CAAC,OAAQ,GAAE,MAAI;AACpB,IAAA;GACA;EACD;AACF;;;;"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { resolveComponent, openBlock, createElementBlock, createBlock, withCtx, createTextVNode, toDisplayString, Fragment, createElementVNode } from 'vue';
|
|
2
|
+
|
|
3
|
+
const _hoisted_1 = {
|
|
4
|
+
class: "cn-search-index-status",
|
|
5
|
+
"data-testid": "cn-search-index-status"
|
|
6
|
+
};
|
|
7
|
+
const _hoisted_2 = { class: "cn-search-index-status__figures" };
|
|
8
|
+
const _hoisted_3 = { "data-testid": "cn-search-index-tables" };
|
|
9
|
+
const _hoisted_4 = { "data-testid": "cn-search-index-indexes" };
|
|
10
|
+
const _hoisted_5 = { "data-testid": "cn-search-index-last-run" };
|
|
11
|
+
const _hoisted_6 = { "data-testid": "cn-search-index-concurrent" };
|
|
12
|
+
const _hoisted_7 = { "data-testid": "cn-search-index-commands" };
|
|
13
|
+
|
|
14
|
+
function render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
15
|
+
const _component_NcLoadingIcon = resolveComponent("NcLoadingIcon");
|
|
16
|
+
const _component_NcNoteCard = resolveComponent("NcNoteCard");
|
|
17
|
+
|
|
18
|
+
return (openBlock(), createElementBlock("div", _hoisted_1, [
|
|
19
|
+
($data.loading)
|
|
20
|
+
? (openBlock(), createBlock(_component_NcLoadingIcon, {
|
|
21
|
+
key: 0,
|
|
22
|
+
size: 24,
|
|
23
|
+
name: $options.t('nextcloud-vue', 'Loading')
|
|
24
|
+
}, null, 8 /* PROPS */, ["name"]))
|
|
25
|
+
: ($data.error)
|
|
26
|
+
? (openBlock(), createBlock(_component_NcNoteCard, {
|
|
27
|
+
key: 1,
|
|
28
|
+
type: "error",
|
|
29
|
+
"data-testid": "cn-search-index-error"
|
|
30
|
+
}, {
|
|
31
|
+
default: withCtx(() => [
|
|
32
|
+
createTextVNode(toDisplayString($data.error), 1 /* TEXT */)
|
|
33
|
+
]),
|
|
34
|
+
_: 1 /* STABLE */
|
|
35
|
+
}))
|
|
36
|
+
: (openBlock(), createElementBlock(Fragment, { key: 2 }, [
|
|
37
|
+
createElementVNode("dl", _hoisted_2, [
|
|
38
|
+
createElementVNode("div", null, [
|
|
39
|
+
createElementVNode("dt", null, toDisplayString($options.t('nextcloud-vue', 'Tables in scope')), 1 /* TEXT */),
|
|
40
|
+
createElementVNode("dd", _hoisted_3, toDisplayString($data.status.tableCount), 1 /* TEXT */)
|
|
41
|
+
]),
|
|
42
|
+
createElementVNode("div", null, [
|
|
43
|
+
createElementVNode("dt", null, toDisplayString($options.t('nextcloud-vue', 'Indexes on them')), 1 /* TEXT */),
|
|
44
|
+
createElementVNode("dd", _hoisted_4, toDisplayString($data.status.indexCount), 1 /* TEXT */)
|
|
45
|
+
]),
|
|
46
|
+
createElementVNode("div", null, [
|
|
47
|
+
createElementVNode("dt", null, toDisplayString($options.t('nextcloud-vue', 'Last run')), 1 /* TEXT */),
|
|
48
|
+
createElementVNode("dd", _hoisted_5, toDisplayString($options.lastRun), 1 /* TEXT */)
|
|
49
|
+
]),
|
|
50
|
+
createElementVNode("div", null, [
|
|
51
|
+
createElementVNode("dt", null, toDisplayString($options.t('nextcloud-vue', 'Rebuild without locking')), 1 /* TEXT */),
|
|
52
|
+
createElementVNode("dd", _hoisted_6, toDisplayString($options.concurrent), 1 /* TEXT */)
|
|
53
|
+
])
|
|
54
|
+
]),
|
|
55
|
+
createElementVNode("p", _hoisted_7, toDisplayString($options.t('nextcloud-vue', 'Run {command} status on the server for the same figures, and {command} rebuild --apply after a schema change.', { command: $props.command })), 1 /* TEXT */)
|
|
56
|
+
], 64 /* STABLE_FRAGMENT */))
|
|
57
|
+
]))
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export { render };
|
|
61
|
+
//# sourceMappingURL=CnSearchIndexStatus.vue3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CnSearchIndexStatus.vue3.js","sources":["../../../../src/components/CnSearchIndexStatus/CnSearchIndexStatus.vue?vue&type=template&id=52b442a4&lang.js"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n<template>\n\t<div class=\"cn-search-index-status\" data-testid=\"cn-search-index-status\">\n\t\t<NcLoadingIcon v-if=\"loading\" :size=\"24\" :name=\"t('nextcloud-vue', 'Loading')\" />\n\t\t<NcNoteCard v-else-if=\"error\" type=\"error\" data-testid=\"cn-search-index-error\">\n\t\t\t{{ error }}\n\t\t</NcNoteCard>\n\t\t<template v-else>\n\t\t\t<dl class=\"cn-search-index-status__figures\">\n\t\t\t\t<div>\n\t\t\t\t\t<dt>{{ t('nextcloud-vue', 'Tables in scope') }}</dt>\n\t\t\t\t\t<dd data-testid=\"cn-search-index-tables\">\n\t\t\t\t\t\t{{ status.tableCount }}\n\t\t\t\t\t</dd>\n\t\t\t\t</div>\n\t\t\t\t<div>\n\t\t\t\t\t<dt>{{ t('nextcloud-vue', 'Indexes on them') }}</dt>\n\t\t\t\t\t<dd data-testid=\"cn-search-index-indexes\">\n\t\t\t\t\t\t{{ status.indexCount }}\n\t\t\t\t\t</dd>\n\t\t\t\t</div>\n\t\t\t\t<div>\n\t\t\t\t\t<dt>{{ t('nextcloud-vue', 'Last run') }}</dt>\n\t\t\t\t\t<dd data-testid=\"cn-search-index-last-run\">\n\t\t\t\t\t\t{{ lastRun }}\n\t\t\t\t\t</dd>\n\t\t\t\t</div>\n\t\t\t\t<div>\n\t\t\t\t\t<dt>{{ t('nextcloud-vue', 'Rebuild without locking') }}</dt>\n\t\t\t\t\t<dd data-testid=\"cn-search-index-concurrent\">\n\t\t\t\t\t\t{{ concurrent }}\n\t\t\t\t\t</dd>\n\t\t\t\t</div>\n\t\t\t</dl>\n\t\t\t<p data-testid=\"cn-search-index-commands\">\n\t\t\t\t{{ t('nextcloud-vue', 'Run {command} status on the server for the same figures, and {command} rebuild --apply after a schema change.', { command }) }}\n\t\t\t</p>\n\t\t</template>\n\t</div>\n</template>\n\n<script>\nimport { getCanonicalLocale, translate as t } from '@nextcloud/l10n'\nimport { NcLoadingIcon, NcNoteCard } from '@nextcloud/vue'\nimport { fetchSearchIndexStatus, SEARCH_INDEX_COMMAND, SEARCH_INDEX_STATUS_URL } from './searchIndexStatus.js'\n\n/**\n * CnSearchIndexStatus: the state of OpenRegister's search indexes (tables in\n * scope, indexes on them, the last maintenance run, whether a rebuild locks a\n * table), read live and never copied. The acts are named, not offered: a\n * rebuild walks every table in scope and nothing stops one from a settings\n * page, so the occ verbs are printed for somebody with a shell.\n *\n * @spec openspec/changes/search-index-status/specs/search-index-status/spec.md\n */\nexport default {\n\tname: 'CnSearchIndexStatus',\n\n\tcomponents: { NcLoadingIcon, NcNoteCard },\n\n\tprops: {\n\t\t/** The app path OpenRegister reports its indexes at. */\n\t\tsource: { type: String, default: SEARCH_INDEX_STATUS_URL },\n\t\t/** The occ command that acts on the indexes. */\n\t\tcommand: { type: String, default: SEARCH_INDEX_COMMAND },\n\t},\n\n\tdata() {\n\t\treturn {\n\t\t\tloading: true,\n\t\t\terror: '',\n\t\t\tstatus: { concurrentRebuildSupported: false, tables: {}, tableCount: 0, indexCount: 0, lastRun: null },\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/** @return {string} When maintenance last ran, or that it never has. */\n\t\tlastRun() {\n\t\t\tif (!this.status.lastRun) {\n\t\t\t\treturn t('nextcloud-vue', 'Never')\n\t\t\t}\n\t\t\tconst when = new Date(this.status.lastRun)\n\t\t\tif (Number.isNaN(when.getTime())) {\n\t\t\t\treturn String(this.status.lastRun)\n\t\t\t}\n\t\t\treturn when.toLocaleString(getCanonicalLocale(), { dateStyle: 'medium', timeStyle: 'short' })\n\t\t},\n\n\t\t/** @return {string} Whether a rebuild locks the table, in words. */\n\t\tconcurrent() {\n\t\t\treturn this.status.concurrentRebuildSupported === true\n\t\t\t\t? t('nextcloud-vue', 'Yes')\n\t\t\t\t: t('nextcloud-vue', 'No, a rebuild locks the table it is on')\n\t\t},\n\t},\n\n\tmounted() {\n\t\tthis.load()\n\t},\n\n\tmethods: {\n\t\tt,\n\n\t\t/**\n\t\t * Read what OpenRegister says about its indexes.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync load() {\n\t\t\tthis.loading = true\n\t\t\tthis.error = ''\n\t\t\ttry {\n\t\t\t\tthis.status = await fetchSearchIndexStatus(this.source)\n\t\t\t} catch (e) {\n\t\t\t\tthis.error = String((e && e.message) || e)\n\t\t\t} finally {\n\t\t\t\tthis.loading = false\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n/* Label above value, and the label wraps: Nextcloud's settings stylesheet gives a `dt` a fixed width. */\n.cn-search-index-status__figures {\n\tdisplay: grid;\n\tgrid-template-columns: repeat(auto-fit, minmax(160px, 1fr));\n\tgap: 16px 24px;\n\tmargin-block: 0 12px;\n}\n\n.cn-search-index-status__figures > div {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 2px;\n\tmin-width: 0;\n}\n\n.cn-search-index-status__figures dt {\n\tdisplay: block;\n\tfloat: none;\n\twidth: auto;\n\tmargin: 0;\n\tpadding: 0;\n\ttext-align: start;\n\twhite-space: normal;\n\toverflow-wrap: anywhere;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-search-index-status__figures dd {\n\tfont-weight: bold;\n\tmargin: 0;\n\toverflow-wrap: anywhere;\n}\n</style>\n"],"names":["_createBlock","_createElementBlock","_createElementVNode","_toDisplayString"],"mappings":";;;AASM,EAAA,KAAK,EAAC,wBAAE;AAAA,EAAA,aAAA,EAAA,wBAAA;;AAMP,MAAA,UAAA,GAAA,EAAA,KAAK,EAAC,iCAAe,GAAA;AAGpB,MAAA,UAAA,GAAA,EAAA,aAAA,EAAA,wBAAA,GAAA;AAMA,MAAA,UAAA,GAAA,EAAA,aAAA,EAAA,yBAAA,GAAA;AAMA,MAAA,UAAA,GAAA,EAAA,aAAA,EAAA,0BAAA,GAAA;AAMD,MAAA,UAAA,GAAA,EAAA,aAAA,EAAA,4BAAA,GAAA;AAKD,MAAA,UAAA,GAAA,EAAA,aAAA,EAAA,0BAAA,GAAA;;;;;;;KA/BY,KAAA,CAAA,OAAA;sBAAhBA,WAAgB,CAAA,wBAAA,EAAA;;AAAA,UAAA,IAAA,EAAA,EAAA;AAAA,UAAA,IAAA,EAAA,QAAA,CAAA,CAAA,CAAA,eAAA,EAAA,SAAA,CAAA;;SACO,KAAK,CAAA,KAAA;wBAA3BA,WAEY,CAAA,qBAAA,EAAA;;AAFiB,YAAA,IAAI,EAAC,OAAO;AAAC,YAAA,aAAC,EAAA,uBAAA;;mCACtC;8CAAF,KAAE,CAAA,KAAA,CAAA,EAAA,CAAA,YAAA;;;;wBAEHC;AACC,YAAAC,kBAAA,CAyBE,MAzBF,UAyBE,EAAA;gCAnBE,CAAA,KAAA,EAAA,IAAA,EAAA;AAJL,gBAAAA,kBAAA,CAAI,4BAAA,QAAA,CAAA,CAAA,CAAA,eAAA,EAAA,iBAAA,CAAA,CAAA,EAAA,CAAA,YAAA;AACJ,gBAAAA,kBAAA,CAEK,IAFL,EAAA,UAEK,EADDC,eAAA,CAAA,KAAA,CAAA,MAAM,CAAC,UAAU,CAAA,EAAA,CAAA,YAAA;;gCAQhB,CAAA,KAAA,EAAA,IAAA,EAAA;AAJL,gBAAAD,kBAAA,CAAI,4BAAA,QAAA,CAAA,CAAA,CAAA,eAAA,EAAA,iBAAA,CAAA,CAAA,EAAA,CAAA,YAAA;AACJ,gBAAAA,kBAAA,CAEK,IAFL,EAAA,UAEK,EADDC,eAAA,CAAA,KAAA,CAAA,MAAM,CAAC,UAAU,CAAA,EAAA,CAAA,YAAA;;gCAQhB,CAAA,KAAA,EAAA,IAAA,EAAA;AAJL,gBAAAD,kBAAA,CAAI,4BAAA,QAAA,CAAA,CAAA,CAAA,eAAA,EAAA,UAAA,CAAA,CAAA,EAAA,CAAA,YAAA;gBACJA,kBAEK,CAAA,IAAA,EAFL,UAEK,EAAAC,eAAA,CADD,QAAO,CAAA,OAAA,CAAA,EAAA,CAAA,YAAA;;gCAQV,CAAA,KAAA,EAAA,IAAA,EAAA;AAJD,gBAAAD,kBAAA,CAAI,4BAAA,QAAA,CAAA,CAAA,CAAA,eAAA,EAAA,yBAAA,CAAA,CAAA,EAAA,CAAA,YAAA;gBACJA,kBAEK,CAAA,IAAA,EAFL,UAEK,EAAAC,eAAA,CADD,QAAU,CAAA,UAAA,CAAA,EAAA,CAAA,YAAA;;;AAIhB,YAAAD,kBAAA,IAAA,EAAA;;;;;;;"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import axios__default from '@nextcloud/axios';
|
|
2
|
+
import { generateUrl } from '@nextcloud/router';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* SPDX-FileCopyrightText: 2026 Conduction B.V.
|
|
6
|
+
* SPDX-License-Identifier: EUPL-1.2
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
/** The occ command that rebuilds, snapshots, restores and reports the indexes. */
|
|
11
|
+
const SEARCH_INDEX_COMMAND = 'occ openregister:tables:search-index';
|
|
12
|
+
|
|
13
|
+
/** Where OpenRegister reports its search indexes. */
|
|
14
|
+
const SEARCH_INDEX_STATUS_URL = '/apps/openregister/api/settings/search-index';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* When the last stored run finished, or started, or null when none ran.
|
|
18
|
+
*
|
|
19
|
+
* OpenRegister answers `lastRun` as the report of that run (`startedAt`,
|
|
20
|
+
* `finishedAt`) and as `[]` when nothing ran.
|
|
21
|
+
*
|
|
22
|
+
* @param {object|Array|string|null|undefined} report What OpenRegister answered as `lastRun`.
|
|
23
|
+
* @return {string|null} An ISO 8601 time, or null when no run is on record.
|
|
24
|
+
*/
|
|
25
|
+
function lastRunTime(report) {
|
|
26
|
+
if (typeof report === 'string') {
|
|
27
|
+
return report === '' ? null : report
|
|
28
|
+
}
|
|
29
|
+
if (report === null || typeof report !== 'object' || Array.isArray(report)) {
|
|
30
|
+
return null
|
|
31
|
+
}
|
|
32
|
+
const time = report.finishedAt || report.startedAt || '';
|
|
33
|
+
return typeof time === 'string' && time !== '' ? time : null
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* What OpenRegister says about the indexes behind object search. A failed
|
|
38
|
+
* read throws: an outage and an instance with no indexes look the same from
|
|
39
|
+
* the browser, and only one of them is somebody's problem.
|
|
40
|
+
*
|
|
41
|
+
* @param {string} [url] The app path to read.
|
|
42
|
+
* @return {Promise<{concurrentRebuildSupported: boolean, tables: object, tableCount: number, indexCount: number, lastRun: (string|null)}>}
|
|
43
|
+
* @throws {Error} When it cannot be read.
|
|
44
|
+
*/
|
|
45
|
+
async function fetchSearchIndexStatus(url = SEARCH_INDEX_STATUS_URL) {
|
|
46
|
+
const { data } = await axios__default.get(generateUrl(url));
|
|
47
|
+
if (data === null || typeof data !== 'object' || data.error !== undefined) {
|
|
48
|
+
throw new Error(String((data && data.error) ?? 'The search index status could not be read.'))
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
concurrentRebuildSupported: data.concurrentRebuildSupported === true,
|
|
52
|
+
tables: data.tables && typeof data.tables === 'object' ? data.tables : {},
|
|
53
|
+
tableCount: Number(data.tableCount ?? 0),
|
|
54
|
+
indexCount: Number(data.indexCount ?? 0),
|
|
55
|
+
lastRun: lastRunTime(data.lastRun),
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export { SEARCH_INDEX_COMMAND, SEARCH_INDEX_STATUS_URL, fetchSearchIndexStatus, lastRunTime };
|
|
60
|
+
//# sourceMappingURL=searchIndexStatus.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"searchIndexStatus.js","sources":["../../../../src/components/CnSearchIndexStatus/searchIndexStatus.js"],"sourcesContent":["/**\n * SPDX-FileCopyrightText: 2026 Conduction B.V.\n * SPDX-License-Identifier: EUPL-1.2\n */\n\nimport axios from '@nextcloud/axios'\nimport { generateUrl } from '@nextcloud/router'\n\n/** The occ command that rebuilds, snapshots, restores and reports the indexes. */\nexport const SEARCH_INDEX_COMMAND = 'occ openregister:tables:search-index'\n\n/** Where OpenRegister reports its search indexes. */\nexport const SEARCH_INDEX_STATUS_URL = '/apps/openregister/api/settings/search-index'\n\n/**\n * When the last stored run finished, or started, or null when none ran.\n *\n * OpenRegister answers `lastRun` as the report of that run (`startedAt`,\n * `finishedAt`) and as `[]` when nothing ran.\n *\n * @param {object|Array|string|null|undefined} report What OpenRegister answered as `lastRun`.\n * @return {string|null} An ISO 8601 time, or null when no run is on record.\n */\nexport function lastRunTime(report) {\n\tif (typeof report === 'string') {\n\t\treturn report === '' ? null : report\n\t}\n\tif (report === null || typeof report !== 'object' || Array.isArray(report)) {\n\t\treturn null\n\t}\n\tconst time = report.finishedAt || report.startedAt || ''\n\treturn typeof time === 'string' && time !== '' ? time : null\n}\n\n/**\n * What OpenRegister says about the indexes behind object search. A failed\n * read throws: an outage and an instance with no indexes look the same from\n * the browser, and only one of them is somebody's problem.\n *\n * @param {string} [url] The app path to read.\n * @return {Promise<{concurrentRebuildSupported: boolean, tables: object, tableCount: number, indexCount: number, lastRun: (string|null)}>}\n * @throws {Error} When it cannot be read.\n */\nexport async function fetchSearchIndexStatus(url = SEARCH_INDEX_STATUS_URL) {\n\tconst { data } = await axios.get(generateUrl(url))\n\tif (data === null || typeof data !== 'object' || data.error !== undefined) {\n\t\tthrow new Error(String((data && data.error) ?? 'The search index status could not be read.'))\n\t}\n\treturn {\n\t\tconcurrentRebuildSupported: data.concurrentRebuildSupported === true,\n\t\ttables: data.tables && typeof data.tables === 'object' ? data.tables : {},\n\t\ttableCount: Number(data.tableCount ?? 0),\n\t\tindexCount: Number(data.indexCount ?? 0),\n\t\tlastRun: lastRunTime(data.lastRun),\n\t}\n}\n"],"names":["axios"],"mappings":";;;AAAA;AACA;AACA;AACA;AACA;AAGA;AACA;AACY,MAAC,oBAAoB,GAAG,uCAAsC;AAC1E;AACA;AACY,MAAC,uBAAuB,GAAG,+CAA8C;AACrF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,WAAW,CAAC,MAAM,EAAE;AACpC,CAAC,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE;AACjC,EAAE,OAAO,MAAM,KAAK,EAAE,GAAG,IAAI,GAAG,MAAM;AACtC,EAAE;AACF,CAAC,IAAI,MAAM,KAAK,IAAI,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE;AAC7E,EAAE,OAAO,IAAI;AACb,EAAE;AACF,CAAC,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,IAAI,MAAM,CAAC,SAAS,IAAI,GAAE;AACzD,CAAC,OAAO,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,EAAE,GAAG,IAAI,GAAG,IAAI;AAC7D,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,eAAe,sBAAsB,CAAC,GAAG,GAAG,uBAAuB,EAAE;AAC5E,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,MAAMA,cAAK,CAAC,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,EAAC;AACnD,CAAC,IAAI,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,EAAE;AAC5E,EAAE,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,KAAK,4CAA4C,CAAC,CAAC;AAC/F,EAAE;AACF,CAAC,OAAO;AACR,EAAE,0BAA0B,EAAE,IAAI,CAAC,0BAA0B,KAAK,IAAI;AACtE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,GAAG,IAAI,CAAC,MAAM,GAAG,EAAE;AAC3E,EAAE,UAAU,EAAE,MAAM,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,CAAC;AAC1C,EAAE,UAAU,EAAE,MAAM,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,CAAC;AAC1C,EAAE,OAAO,EAAE,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC;AACpC,EAAE;AACF;;;;"}
|
package/dist/esm/components/CnShippedConfigurationSection/CnShippedConfigurationSection.vue.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import script from './CnShippedConfigurationSection.vue2.js';
|
|
2
|
+
export { SHIPPED_STATES } from './CnShippedConfigurationSection.vue2.js';
|
|
3
|
+
import { render } from './CnShippedConfigurationSection.vue3.js';
|
|
4
|
+
|
|
5
|
+
script.render = render;
|
|
6
|
+
script.__scopeId = "data-v-fd515054";
|
|
7
|
+
const __sfc_main = script;
|
|
8
|
+
|
|
9
|
+
export { __sfc_main as default };
|
|
10
|
+
//# sourceMappingURL=CnShippedConfigurationSection.vue.js.map
|
package/dist/esm/components/CnShippedConfigurationSection/CnShippedConfigurationSection.vue.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CnShippedConfigurationSection.vue.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;"}
|
package/dist/esm/components/CnShippedConfigurationSection/CnShippedConfigurationSection.vue2.js
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import axios__default from '@nextcloud/axios';
|
|
2
|
+
import { x as showSuccess } from '../../node_modules/@nextcloud/dialogs/dist/chunks/index.js';
|
|
3
|
+
import { translate } from '@nextcloud/l10n';
|
|
4
|
+
import { generateUrl } from '@nextcloud/router';
|
|
5
|
+
import { NcButton, NcNoteCard, NcSelect } from '@nextcloud/vue';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The states a seeded object can be in.
|
|
9
|
+
*
|
|
10
|
+
* @type {Readonly<Record<string, string>>}
|
|
11
|
+
*/
|
|
12
|
+
const SHIPPED_STATES = Object.freeze({
|
|
13
|
+
shipped: 'shipped',
|
|
14
|
+
changed: 'changed',
|
|
15
|
+
local: 'local',
|
|
16
|
+
removed: 'removed',
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* CnShippedConfigurationSection: what an app shipped, what this instance
|
|
21
|
+
* changed, and what it authored. One row per seeded object with the set and
|
|
22
|
+
* version it came from, its state, and the newer version offered per object.
|
|
23
|
+
* Taking a newer version over a local change says so on the button, because
|
|
24
|
+
* the change goes.
|
|
25
|
+
*
|
|
26
|
+
* The app's endpoint answers `GET {endpoint}/{schema}` with `{ items: [{
|
|
27
|
+
* targetObject, title, state, set, setVersion, latestVersion, updateAvailable
|
|
28
|
+
* }] }` and takes `POST {endpoint}/{schema}/{targetObject}/adopt` with `{ set,
|
|
29
|
+
* acceptLocalChangeLoss }`, refusing with `{ reason }`. An empty ledger beside
|
|
30
|
+
* a register that holds objects is said as such (`countUrl`), not as "nothing
|
|
31
|
+
* seeded".
|
|
32
|
+
*
|
|
33
|
+
* @spec openspec/changes/shipped-configuration-section/specs/shipped-configuration-section/spec.md
|
|
34
|
+
*/
|
|
35
|
+
var script = {
|
|
36
|
+
name: 'CnShippedConfigurationSection',
|
|
37
|
+
|
|
38
|
+
components: { NcButton, NcNoteCard, NcSelect },
|
|
39
|
+
|
|
40
|
+
inject: {
|
|
41
|
+
/** The host app's translate, for the texts the page declares. */
|
|
42
|
+
cnTranslate: { default: () => (key) => key },
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
props: {
|
|
46
|
+
/** The app path of the shipped ledger (`/apps/<app>/api/starter/shipped`). */
|
|
47
|
+
endpoint: { type: String, required: true },
|
|
48
|
+
/** The schemas to show, `[{ slug, label }]`; the first is shown first. */
|
|
49
|
+
schemas: { type: Array, default: () => [] },
|
|
50
|
+
/**
|
|
51
|
+
* An app path that counts a schema's objects, `{schema}` filled in
|
|
52
|
+
* (`/apps/openregister/api/objects/<register>/{schema}`), read with
|
|
53
|
+
* `_limit=1` for its `total`.
|
|
54
|
+
*/
|
|
55
|
+
countUrl: { type: String, default: '' },
|
|
56
|
+
/** A line above the table. */
|
|
57
|
+
description: { type: String, default: '' },
|
|
58
|
+
},
|
|
59
|
+
|
|
60
|
+
data() {
|
|
61
|
+
return {
|
|
62
|
+
schema: this.schemas.length > 0 ? String(this.schemas[0].slug) : '',
|
|
63
|
+
rows: [],
|
|
64
|
+
present: null,
|
|
65
|
+
loadError: '',
|
|
66
|
+
adoptError: '',
|
|
67
|
+
adopting: '',
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
computed: {
|
|
72
|
+
/** @return {Array<{id: string, label: string}>} The picker's options. */
|
|
73
|
+
schemaOptions() {
|
|
74
|
+
return this.schemas.map((option) => ({ id: String(option.slug), label: this.text(option.label || option.slug) }))
|
|
75
|
+
},
|
|
76
|
+
|
|
77
|
+
schemaOption: {
|
|
78
|
+
/** @return {object|null} The chosen schema. */
|
|
79
|
+
get() {
|
|
80
|
+
return this.schemaOptions.find((option) => option.id === this.schema) || null
|
|
81
|
+
},
|
|
82
|
+
|
|
83
|
+
/** @param {object|null} option The chosen schema. */
|
|
84
|
+
set(option) {
|
|
85
|
+
if (option) {
|
|
86
|
+
this.schema = option.id;
|
|
87
|
+
this.reload();
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
|
|
92
|
+
/** @return {string} What the empty table says, which depends on what the register holds. */
|
|
93
|
+
emptyLine() {
|
|
94
|
+
if (typeof this.present === 'number' && this.present > 0) {
|
|
95
|
+
return translate('nextcloud-vue', 'The register holds {count} of these. None came from a shipped set, so there is no shipped version to compare with.', { count: this.present })
|
|
96
|
+
}
|
|
97
|
+
return translate('nextcloud-vue', 'Nothing has been seeded yet.')
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
|
|
101
|
+
mounted() {
|
|
102
|
+
this.reload();
|
|
103
|
+
},
|
|
104
|
+
|
|
105
|
+
methods: {
|
|
106
|
+
t: translate,
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* @param {string} value A declared text.
|
|
110
|
+
* @return {string} It, translated by the host.
|
|
111
|
+
*/
|
|
112
|
+
text(value) {
|
|
113
|
+
return value ? String(this.cnTranslate(String(value))) : ''
|
|
114
|
+
},
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Read what shipped for the shown schema. A failed read empties the
|
|
118
|
+
* table: rows left beside an error would read as the current state.
|
|
119
|
+
*
|
|
120
|
+
* @return {Promise<void>}
|
|
121
|
+
*/
|
|
122
|
+
async reload() {
|
|
123
|
+
if (!this.schema) {
|
|
124
|
+
return
|
|
125
|
+
}
|
|
126
|
+
try {
|
|
127
|
+
const { data } = await axios__default.get(generateUrl(`${this.endpoint}/${encodeURIComponent(this.schema)}`));
|
|
128
|
+
this.rows = Array.isArray(data && data.items) ? data.items : [];
|
|
129
|
+
this.loadError = '';
|
|
130
|
+
this.present = null;
|
|
131
|
+
if (this.rows.length === 0) {
|
|
132
|
+
this.present = await this.count();
|
|
133
|
+
}
|
|
134
|
+
} catch {
|
|
135
|
+
this.rows = [];
|
|
136
|
+
this.present = null;
|
|
137
|
+
this.loadError = translate('nextcloud-vue', 'Could not read the shipped configuration.');
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* How many objects of the shown schema the register holds, whatever
|
|
143
|
+
* brought them.
|
|
144
|
+
*
|
|
145
|
+
* @return {Promise<number|null>} The count, or null when it cannot be read.
|
|
146
|
+
*/
|
|
147
|
+
async count() {
|
|
148
|
+
if (!this.countUrl) {
|
|
149
|
+
return null
|
|
150
|
+
}
|
|
151
|
+
try {
|
|
152
|
+
const { data } = await axios__default.get(generateUrl(this.countUrl.replace('{schema}', encodeURIComponent(this.schema))), { params: { _limit: 1 } });
|
|
153
|
+
const total = Number(data && data.total);
|
|
154
|
+
return Number.isFinite(total) ? total : null
|
|
155
|
+
} catch {
|
|
156
|
+
return null
|
|
157
|
+
}
|
|
158
|
+
},
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* @param {object} row A ledger row.
|
|
162
|
+
* @return {string} What an administrator reads beside the object.
|
|
163
|
+
*/
|
|
164
|
+
stateLabel(row) {
|
|
165
|
+
const state = (row && row.state) || SHIPPED_STATES.local;
|
|
166
|
+
return {
|
|
167
|
+
[SHIPPED_STATES.shipped]: translate('nextcloud-vue', 'Shipped, unchanged'),
|
|
168
|
+
[SHIPPED_STATES.changed]: translate('nextcloud-vue', 'Shipped, changed here'),
|
|
169
|
+
[SHIPPED_STATES.removed]: translate('nextcloud-vue', 'Shipped, removed here'),
|
|
170
|
+
}[state] || translate('nextcloud-vue', 'Yours')
|
|
171
|
+
},
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* @param {object} row A ledger row.
|
|
175
|
+
* @return {boolean} Whether a newer shipped version can be taken.
|
|
176
|
+
*/
|
|
177
|
+
updatable(row) {
|
|
178
|
+
return Boolean(row && row.updateAvailable && row.state !== SHIPPED_STATES.removed)
|
|
179
|
+
},
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* @param {object} row A ledger row.
|
|
183
|
+
* @return {boolean} Whether taking the newer version overwrites a local change.
|
|
184
|
+
*/
|
|
185
|
+
losesLocalChange(row) {
|
|
186
|
+
return Boolean(row && row.state === SHIPPED_STATES.changed)
|
|
187
|
+
},
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* @param {object} row A ledger row.
|
|
191
|
+
* @return {string} The button's words, which say when a local change goes.
|
|
192
|
+
*/
|
|
193
|
+
adoptLabel(row) {
|
|
194
|
+
return this.losesLocalChange(row)
|
|
195
|
+
? translate('nextcloud-vue', 'Take {version} and lose your change', { version: row.latestVersion })
|
|
196
|
+
: translate('nextcloud-vue', 'Take {version}', { version: row.latestVersion })
|
|
197
|
+
},
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Take the newer shipped version of one object, then read the ledger again.
|
|
201
|
+
*
|
|
202
|
+
* @param {object} row A ledger row.
|
|
203
|
+
* @return {Promise<void>}
|
|
204
|
+
*/
|
|
205
|
+
async adopt(row) {
|
|
206
|
+
this.adopting = row.targetObject;
|
|
207
|
+
this.adoptError = '';
|
|
208
|
+
try {
|
|
209
|
+
await axios__default.post(
|
|
210
|
+
generateUrl(`${this.endpoint}/${encodeURIComponent(this.schema)}/${encodeURIComponent(row.targetObject)}/adopt`),
|
|
211
|
+
{ set: row.set, acceptLocalChangeLoss: this.losesLocalChange(row) },
|
|
212
|
+
);
|
|
213
|
+
showSuccess(translate('nextcloud-vue', 'The newer version was taken.'));
|
|
214
|
+
await this.reload();
|
|
215
|
+
} catch (error) {
|
|
216
|
+
const data = error && error.response && error.response.data;
|
|
217
|
+
this.adoptError = String((data && (data.reason || data.message)) || translate('nextcloud-vue', 'The newer version was not taken.'));
|
|
218
|
+
} finally {
|
|
219
|
+
this.adopting = '';
|
|
220
|
+
}
|
|
221
|
+
},
|
|
222
|
+
},
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
export { SHIPPED_STATES, script as default };
|
|
226
|
+
//# sourceMappingURL=CnShippedConfigurationSection.vue2.js.map
|