@conduction/nextcloud-vue 2.56.0-beta.5 → 2.56.0-beta.6
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/CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue2.js +100 -3
- package/dist/esm/components/CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue3.js.map +1 -1
- package/dist/nextcloud-vue.cjs.js +100 -3
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/package.json +1 -1
- package/src/components/CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue +100 -3
|
@@ -322,6 +322,26 @@ const CORE_TABS = ['files', 'notes', 'tags', 'tasks', 'auditTrail', 'shares']
|
|
|
322
322
|
/** One-time guard so the legacy-path deprecation warning logs only once. */
|
|
323
323
|
let legacyWarned = false
|
|
324
324
|
|
|
325
|
+
/**
|
|
326
|
+
* Schema titles by numeric schema id, shared by every widget on the page so a
|
|
327
|
+
* schema is asked for once. OpenRegister's `/uses` and `/used` answer
|
|
328
|
+
* `@self.schema` as that id ("120"), which is not a word anyone can read.
|
|
329
|
+
*
|
|
330
|
+
* @type {Map<string, Promise<string>>}
|
|
331
|
+
*/
|
|
332
|
+
const schemaTitleCache = new Map()
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Whether a value is a bare number, the way OpenRegister names a schema by id.
|
|
336
|
+
*
|
|
337
|
+
* @param {string|number|undefined|null} value The value.
|
|
338
|
+
* @return {boolean}
|
|
339
|
+
*/
|
|
340
|
+
function isNumericId(value) {
|
|
341
|
+
return (typeof value === 'number' && Number.isFinite(value))
|
|
342
|
+
|| (typeof value === 'string' && /^\d+$/.test(value.trim()))
|
|
343
|
+
}
|
|
344
|
+
|
|
325
345
|
/**
|
|
326
346
|
* Leaf groups surfaced by the aggregated `/relations` endpoint, in tab order.
|
|
327
347
|
* `responseKey` is the key in the `/relations` payload; `integrationId` is the
|
|
@@ -404,6 +424,14 @@ export default {
|
|
|
404
424
|
NcEmptyContent,
|
|
405
425
|
},
|
|
406
426
|
|
|
427
|
+
inject: {
|
|
428
|
+
/**
|
|
429
|
+
* The host app's translator (CnAppRoot provides it), so a schema title
|
|
430
|
+
* reads in the app's language. Without it a title reads as stored.
|
|
431
|
+
*/
|
|
432
|
+
cnTranslate: { default: () => (key) => key },
|
|
433
|
+
},
|
|
434
|
+
|
|
407
435
|
props: {
|
|
408
436
|
/** Widget title shown in the header. */
|
|
409
437
|
title: {
|
|
@@ -667,6 +695,8 @@ export default {
|
|
|
667
695
|
* @type {HTMLInputElement|null}
|
|
668
696
|
*/
|
|
669
697
|
fileInputEl: null,
|
|
698
|
+
/** Schema titles by numeric schema id, for object rows. */
|
|
699
|
+
schemaTitles: {},
|
|
670
700
|
/** Whether any section/tab is currently fetching. */
|
|
671
701
|
loading: false,
|
|
672
702
|
/** True once the first fetch has completed (gates the empty state). */
|
|
@@ -1359,9 +1389,74 @@ export default {
|
|
|
1359
1389
|
self.name,
|
|
1360
1390
|
raw.summary,
|
|
1361
1391
|
raw.description,
|
|
1362
|
-
].find((v) => typeof v === 'string' && v.trim() && !isUuid(v))
|
|
1363
|
-
|
|
1364
|
-
|
|
1392
|
+
].find((v) => typeof v === 'string' && v.trim() && !isUuid(v))
|
|
1393
|
+
|| [raw.givenName, raw.familyName].filter((v) => typeof v === 'string' && v.trim()).join(' ')
|
|
1394
|
+
// OpenRegister names the schema by numeric id: show its title, never the number.
|
|
1395
|
+
const schema = this.schemaName(self.schema || raw.schema)
|
|
1396
|
+
const finalLabel = label || schema || String(id)
|
|
1397
|
+
return { id, label: finalLabel, meta: schema === finalLabel ? '' : schema, raw }
|
|
1398
|
+
},
|
|
1399
|
+
|
|
1400
|
+
/**
|
|
1401
|
+
* How a row names its schema: the translated title for a numeric id
|
|
1402
|
+
* (empty until it is read, or when it cannot be), a slug as it is.
|
|
1403
|
+
*
|
|
1404
|
+
* @param {string|number|undefined|null} schema - `@self.schema` of the related object.
|
|
1405
|
+
* @return {string}
|
|
1406
|
+
*/
|
|
1407
|
+
schemaName(schema) {
|
|
1408
|
+
if (isNumericId(schema)) {
|
|
1409
|
+
const title = this.schemaTitles[String(schema).trim()]
|
|
1410
|
+
return title ? this.cnTranslate(title) : ''
|
|
1411
|
+
}
|
|
1412
|
+
return typeof schema === 'string' ? schema : ''
|
|
1413
|
+
},
|
|
1414
|
+
|
|
1415
|
+
/**
|
|
1416
|
+
* Read the titles of the numeric schema ids in these envelopes once,
|
|
1417
|
+
* before the rows are built, so no row shows a number first.
|
|
1418
|
+
*
|
|
1419
|
+
* @param {Array<object|null>} envelopes - The `{ results }` payloads.
|
|
1420
|
+
* @return {Promise<void>}
|
|
1421
|
+
*/
|
|
1422
|
+
async resolveSchemaTitles(envelopes) {
|
|
1423
|
+
const ids = new Set()
|
|
1424
|
+
for (const envelope of envelopes) {
|
|
1425
|
+
for (const raw of ((envelope && envelope.results) || [])) {
|
|
1426
|
+
const schema = (raw && (raw['@self'] || {}).schema) ?? (raw && raw.schema)
|
|
1427
|
+
if (isNumericId(schema)) {
|
|
1428
|
+
ids.add(String(schema).trim())
|
|
1429
|
+
}
|
|
1430
|
+
}
|
|
1431
|
+
}
|
|
1432
|
+
const titles = { ...this.schemaTitles }
|
|
1433
|
+
await Promise.all([...ids].filter((id) => !(id in titles)).map(async (id) => {
|
|
1434
|
+
if (!schemaTitleCache.has(id)) {
|
|
1435
|
+
schemaTitleCache.set(id, this.fetchSchemaTitle(id))
|
|
1436
|
+
}
|
|
1437
|
+
titles[id] = await schemaTitleCache.get(id)
|
|
1438
|
+
}))
|
|
1439
|
+
this.schemaTitles = titles
|
|
1440
|
+
},
|
|
1441
|
+
|
|
1442
|
+
/**
|
|
1443
|
+
* GET one schema's title; '' when it cannot be read.
|
|
1444
|
+
*
|
|
1445
|
+
* @param {string} id - The numeric schema id.
|
|
1446
|
+
* @return {Promise<string>}
|
|
1447
|
+
*/
|
|
1448
|
+
async fetchSchemaTitle(id) {
|
|
1449
|
+
try {
|
|
1450
|
+
const response = await fetch(generateUrl('/apps/openregister/api/schemas/{id}', { id }), { method: 'GET', headers: buildHeaders() })
|
|
1451
|
+
if (!response.ok) {
|
|
1452
|
+
return ''
|
|
1453
|
+
}
|
|
1454
|
+
const schema = await response.json()
|
|
1455
|
+
const title = schema && (schema.title || schema.slug)
|
|
1456
|
+
return typeof title === 'string' ? title : ''
|
|
1457
|
+
} catch {
|
|
1458
|
+
return ''
|
|
1459
|
+
}
|
|
1365
1460
|
},
|
|
1366
1461
|
|
|
1367
1462
|
/**
|
|
@@ -1465,6 +1560,7 @@ export default {
|
|
|
1465
1560
|
const groups = []
|
|
1466
1561
|
|
|
1467
1562
|
if (this.showObjects) {
|
|
1563
|
+
await this.resolveSchemaTitles([uses, used, contracts])
|
|
1468
1564
|
const objectItems = this.mergeObjectResults([uses, used, contracts])
|
|
1469
1565
|
groups.push({ key: 'objects', label: this.objectsLabel, icon: 'FileTreeOutline', integrationId: '', items: objectItems, total: objectItems.length })
|
|
1470
1566
|
}
|
|
@@ -1590,6 +1686,7 @@ export default {
|
|
|
1590
1686
|
calls.push(store.fetchContracts(type, id))
|
|
1591
1687
|
}
|
|
1592
1688
|
const groups = await Promise.all(calls)
|
|
1689
|
+
await this.resolveSchemaTitles(groups.map((results) => ({ results: results || [] })))
|
|
1593
1690
|
const seen = new Set()
|
|
1594
1691
|
const merged = []
|
|
1595
1692
|
for (const group of groups) {
|