From 02a731fc293e83f701d0860f43ddd2b8e8b96069 Mon Sep 17 00:00:00 2001 From: Alban Mouton Date: Mon, 1 Jun 2026 17:12:33 +0200 Subject: [PATCH 1/2] fix(ui): make mirrored-artefact edit form read-only except local access Editing a mirrored artefact (one with `origin`) could not save a privateAccess/public change: the form always PATCHed the full body, and the API rejects any non-access field on a mirror with 403. The metadata form was also fully editable even though the remote registry owns it. - artefact schema: add mirror-aware VJSF `layout.if` expressions keyed on context.mirrored / context.accessOnly so remote-owned fields show read-only and hide from the access-only form (and vice-versa); regenerate the vjsf-patch-req components. - artefact-admin.vue: render remote-owned metadata read-only for mirrors with an explanatory notice; restrict the editable form + PATCH body to public/privateAccess on a mirror. - adopt @data-fair/lib-vue helpers (edit-fetch pattern): unify the diff and PATCH body through a normalized buildPayload, compute hasDiff with fast-deep-equal, keep the payload reference stable via computedDeepDiff, and add useLeaveGuard for an unsaved-changes warning. - tests: e2e coverage for the mirror read-only/save behaviour and the leave guard. Co-Authored-By: Claude Opus 4.8 (1M context) --- api/types/artefact/schema.js | 20 +++- package-lock.json | 1 + tests/artefact-admin.e2e.spec.ts | 67 ++++++++++- ui/package.json | 1 + ui/src/components/artefact-admin.vue | 83 ++++++++++++-- ui/src/components/vjsf/vjsf-patch-req-en.vue | 110 ++++++++++++++----- ui/src/components/vjsf/vjsf-patch-req-fr.vue | 110 ++++++++++++++----- 7 files changed, 322 insertions(+), 70 deletions(-) diff --git a/api/types/artefact/schema.js b/api/types/artefact/schema.js index cf9347f..abbb343 100644 --- a/api/types/artefact/schema.js +++ b/api/types/artefact/schema.js @@ -20,9 +20,18 @@ export default { type: 'string', enum: ['processing', 'catalog', 'application', 'tileset', 'maplibre-style', 'other'] }, + // Mirror-aware visibility (driven by the admin form's VJSF context): + // context.mirrored -> artefact is mirrored from a remote registry + // context.accessOnly -> this form instance edits only local access + // (public / privateAccess) + // Remote-owned fields are shown read-only in the metadata section and + // hidden from the access-only section; public/privateAccess are the + // inverse. Both context flags are absent (falsy) for a normal, + // non-mirrored artefact, so the single form shows everything. title: { type: 'object', additionalProperties: false, + layout: { if: '!context.accessOnly' }, properties: { en: { type: 'string', title: 'Title - English', 'x-i18n-title': { fr: 'Titre - Anglais' }, layout: { cols: { md: 6 } } }, fr: { type: 'string', title: 'Title - French', 'x-i18n-title': { fr: 'Titre - Français' }, layout: { cols: { md: 6 } } } @@ -31,6 +40,7 @@ export default { description: { type: 'object', additionalProperties: false, + layout: { if: '!context.accessOnly' }, properties: { en: { type: 'string', title: 'Description - English', 'x-i18n-title': { fr: 'Description - Anglais' }, layout: { comp: 'textarea', props: { autoGrow: true, rows: 3 }, cols: { md: 6 } } }, fr: { type: 'string', title: 'Description - French', 'x-i18n-title': { fr: 'Description - Français' }, layout: { comp: 'textarea', props: { autoGrow: true, rows: 3 }, cols: { md: 6 } } } @@ -39,6 +49,7 @@ export default { group: { type: 'object', additionalProperties: false, + layout: { if: '!context.accessOnly' }, properties: { en: { type: 'string', @@ -83,21 +94,21 @@ export default { type: 'boolean', title: 'Deprecated', 'x-i18n-title': { fr: 'Déprécié' }, - layout: 'switch', + layout: { comp: 'switch', if: '!context.accessOnly' }, default: false }, public: { type: 'boolean', title: 'Public', 'x-i18n-title': { fr: 'Public' }, - layout: 'switch', + layout: { comp: 'switch', if: 'context.accessOnly || !context.mirrored' }, default: false }, privateAccess: { type: 'array', title: 'Private access', 'x-i18n-title': { fr: 'Accès privés' }, - layout: { if: '!parent.data?.public' }, + layout: { if: '(context.accessOnly || !context.mirrored) && !parent.data?.public' }, items: { type: 'object', title: 'Account', @@ -125,7 +136,8 @@ export default { type: 'string', format: 'uri', title: 'Documentation URL', - 'x-i18n-title': { fr: 'URL de documentation' } + 'x-i18n-title': { fr: 'URL de documentation' }, + layout: { if: '!context.accessOnly' } }, origin: { type: 'string', readOnly: true }, // `fileName` is only used by format=file. diff --git a/package-lock.json b/package-lock.json index 7648875..314ab97 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14562,6 +14562,7 @@ "@unhead/vue": "^2.1.10", "dayjs": "^1.11.19", "debug": "^4.4.3", + "fast-deep-equal": "^3.1.3", "vue": "^3.5.13", "vue-router": "^4.5.1", "vuetify": "^4.0.1" diff --git a/tests/artefact-admin.e2e.spec.ts b/tests/artefact-admin.e2e.spec.ts index 4a616c0..a957347 100644 --- a/tests/artefact-admin.e2e.spec.ts +++ b/tests/artefact-admin.e2e.spec.ts @@ -1,9 +1,10 @@ import { test, expect, type Page } from '@playwright/test' import FormData from 'form-data' -import { superAdmin, axiosWithApiKey, clean } from './support/axios.ts' +import { superAdmin, axiosWithApiKey, clean, setArtefactOrigin } from './support/axios.ts' import { createTestTarball } from './support/test-tarball.ts' const pkgId = '@test/grouped-pkg@1' +const mirrorId = '@test/mirror-demo@3' test.beforeAll(async () => { await clean() @@ -22,6 +23,17 @@ test.beforeAll(async () => { group: { en: 'Geo tools', fr: 'Outils géo' }, documentation: 'https://example.com/docs' }) + + // A mirrored artefact: metadata is owned by the (simulated) remote registry, + // only local access (public/privateAccess) may be edited here. + const mirrorForm = new FormData() + mirrorForm.append('file', await createTestTarball({ name: '@test/mirror-demo', version: '3.4.5' }), { filename: 'p.tgz', contentType: 'application/gzip' }) + await upload.post('/api/v1/artefacts/npm/' + encodeURIComponent(mirrorId), mirrorForm, { headers: mirrorForm.getHeaders() }) + await ax.patch('/api/v1/artefacts/' + encodeURIComponent(mirrorId), { + title: { en: 'Mirror Demo', fr: 'Démo Miroir' }, + group: { en: 'Statistics', fr: 'Statistiques' } + }) + await setArtefactOrigin(mirrorId, 'https://upstream.example.com') }) test.describe('Artefact admin metadata editing', () => { @@ -51,6 +63,59 @@ test.describe('Artefact admin metadata editing', () => { await page.reload() await expect(page.getByLabel('Groupe - Anglais')).toHaveValue('Mapping tools') }) + + test('warns before navigating away with unsaved changes', async ({ page }) => { + await page.goto('/registry/artefacts/' + encodeURIComponent(pkgId)) + await expect(page.locator('#artefact-admin')).toBeVisible() + + const groupEn = page.getByLabel('Groupe - Anglais') + await groupEn.fill('Unsaved change') + await groupEn.blur() + + // Dismissing the confirmation keeps us on the page. + page.once('dialog', dialog => dialog.dismiss()) + await page.getByRole('link', { name: 'Administration' }).click() + await expect(page.locator('#artefact-admin')).toBeVisible() + + // Accepting it lets the navigation through. + page.once('dialog', dialog => dialog.accept()) + await page.getByRole('link', { name: 'Administration' }).click() + await expect(page).toHaveURL(/\/admin/) + }) +}) + +test.describe('Artefact admin metadata editing for a mirrored artefact', () => { + test.beforeEach(async ({ page }) => { + await loginAdmin(page) + }) + + test('remote-owned metadata is read-only while local access stays editable', async ({ page }) => { + await page.goto('/registry/artefacts/' + encodeURIComponent(mirrorId)) + await expect(page.locator('#artefact-admin')).toBeVisible() + + // Mirror notice is shown and the remote-owned metadata appears read-only. + await expect(page.getByText('mirroré depuis un registre distant')).toBeVisible() + const groupEn = page.getByLabel('Groupe - Anglais') + await expect(groupEn).toHaveValue('Statistics') + await expect(groupEn).toBeDisabled() + + // The local access switch (Public) is editable. + await expect(page.getByLabel('Public')).toBeEnabled() + }) + + test('toggling local access and saving succeeds (only public/privateAccess are sent)', async ({ page }) => { + await page.goto('/registry/artefacts/' + encodeURIComponent(mirrorId)) + await expect(page.locator('#artefact-admin')).toBeVisible() + + // Before the fix the form sent the remote-owned fields too and the API + // answered 403; toggling Public and saving must now succeed. + await page.getByLabel('Public').click() + await page.locator('#artefact-admin').getByRole('button', { name: 'Enregistrer' }).click() + await expect(page.getByText('Modifications enregistrées')).toBeVisible() + + await page.reload() + await expect(page.getByLabel('Public')).toBeChecked() + }) }) // Logs in as an admin (admin mode on) by replaying the simple-directory password diff --git a/ui/package.json b/ui/package.json index 50bd60e..5fdb830 100644 --- a/ui/package.json +++ b/ui/package.json @@ -22,6 +22,7 @@ "@unhead/vue": "^2.1.10", "dayjs": "^1.11.19", "debug": "^4.4.3", + "fast-deep-equal": "^3.1.3", "vue": "^3.5.13", "vue-router": "^4.5.1", "vuetify": "^4.0.1" diff --git a/ui/src/components/artefact-admin.vue b/ui/src/components/artefact-admin.vue index d61e38a..adee8c7 100644 --- a/ui/src/components/artefact-admin.vue +++ b/ui/src/components/artefact-admin.vue @@ -56,6 +56,23 @@ {{ t('editableMetadata') }} + + () const { t, locale } = useI18n() const router = useRouter() +// Mirrored artefacts: the remote registry owns the metadata. Only `public` +// and `privateAccess` can be patched locally (the API rejects anything else +// with 403), so the editable form is restricted to those fields. +const isMirror = computed(() => !!artefact.origin) + const editData = ref>({}) -const originalEditData = ref('') +const readonlyData = ref>({}) const valid = ref(true) const confirmDelete = ref(false) -const hasDiff = computed(() => JSON.stringify(editData.value) !== originalEditData.value) +// Build the normalized patch payload from a source (the live form, or the +// saved artefact). The same shape is used both to compute the diff and as the +// PATCH body, so they can never drift. On a mirror only the access fields are +// included — the remote registry owns the rest. +const buildPayload = (src: Record) => { + const payload: Record = { + public: src.public ?? false, + privateAccess: src.privateAccess?.length ? src.privateAccess : null + } + if (isMirror.value) return payload + payload.title = (src.title?.fr || src.title?.en) ? src.title : null + payload.description = (src.description?.fr || src.description?.en) ? src.description : null + payload.group = (src.group?.fr || src.group?.en) ? src.group : null + payload.documentation = src.documentation || null + payload.deprecated = src.deprecated ?? false + return payload +} + +// computedDeepDiff keeps the reference stable across VJSF's frequent re-emits +// (it returns the previous value when the new one is deeply equal), so the +// payload only changes identity on a real edit. +const editablePayload = computedDeepDiff(() => buildPayload(editData.value)) +const savedPayload = computed(() => buildPayload(artefact)) + +const hasDiff = computed(() => !equal(editablePayload.value, savedPayload.value)) + +// Warn before navigating away (route change or tab close) with unsaved edits. +useLeaveGuard(hasDiff, { locale }) const vjsfOptions = computed>(() => ({ validateOn: 'input', @@ -189,7 +243,16 @@ const vjsfOptions = computed>(() => ({ initialValidation: 'always', locale: locale.value, xI18n: true, - context: { category: artefact.category, apiPath: $apiPath } + // accessOnly mirrors mirrored: on a mirror the editable form shows only the + // local access fields; on a normal artefact it shows everything. + context: { category: artefact.category, apiPath: $apiPath, mirrored: isMirror.value, accessOnly: isMirror.value } +})) + +// Read-only display of the remote-owned metadata, shown for mirrors only. +const readonlyVjsfOptions = computed>(() => ({ + ...vjsfOptions.value, + readOnly: true, + context: { category: artefact.category, apiPath: $apiPath, mirrored: true, accessOnly: false } })) // Re-seed the edit form whenever the artefact is (re)loaded by the parent. @@ -203,18 +266,16 @@ watch(() => artefact, () => { public: artefact.public ?? false, privateAccess: artefact.privateAccess ? [...artefact.privateAccess] : [] } - originalEditData.value = JSON.stringify(editData.value) + // Frozen snapshot for the read-only metadata form (mirrors only); kept + // separate from editData so the editable access form can never mutate it. + readonlyData.value = { ...editData.value } }, { immediate: true }) const patchAction = useAsyncAction( async () => { - const body = { ...editData.value } - if (body.title && !body.title.fr && !body.title.en) body.title = null - if (body.description && !body.description.fr && !body.description.en) body.description = null - if (body.group && !body.group.fr && !body.group.en) body.group = null - if (body.privateAccess && body.privateAccess.length === 0) body.privateAccess = null - - await $fetch(`/v1/artefacts/${encodeURIComponent(artefact._id)}`, { method: 'PATCH', body }) + // The payload already excludes the remote-owned fields on a mirror, so the + // API never sees a forbidden key (which it would answer with 403). + await $fetch(`/v1/artefacts/${encodeURIComponent(artefact._id)}`, { method: 'PATCH', body: editablePayload.value }) emit('changed') }, { success: t('saved') } diff --git a/ui/src/components/vjsf/vjsf-patch-req-en.vue b/ui/src/components/vjsf/vjsf-patch-req-en.vue index e6f231d..a270e1f 100644 --- a/ui/src/components/vjsf/vjsf-patch-req-en.vue +++ b/ui/src/components/vjsf/vjsf-patch-req-en.vue @@ -31,7 +31,7 @@ import localizeErrors from "ajv-i18n/localize/en/index.js"; import { fullFormats } from "ajv-formats/dist/formats.js"; const schema26 = {"$id":"export0","$ref":"https://github.com/data-fair/registry/artefact-patch#/properties/privateAccess/anyOf/0/items"}; -const schema28 = {"type":"object","title":"Account","additionalProperties":false,"required":["type","id","name"],"properties":{"type":{"type":"string","enum":["user","organization"],"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/privateAccess/anyOf/0/items/properties/type","errorMessage":{}},"id":{"type":"string","__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/privateAccess/anyOf/0/items/properties/id","errorMessage":{}},"name":{"type":"string","__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/privateAccess/anyOf/0/items/properties/name","errorMessage":{}}},"layout":{"getItems":{"url":{"type":"js-tpl","expr":"/simple-directory/api/accounts?size=20","pure":true,"dataAlias":"value","ref":6},"qSearchParam":"q","itemsResults":{"type":"js-eval","expr":"data.results","pure":true,"dataAlias":"body","ref":3},"itemTitle":{"type":"js-eval","expr":"`${item.name} (${item.id})`","pure":true,"dataAlias":"item","ref":7},"itemKey":{"type":"js-eval","expr":"`${item.type}:${item.id}`","pure":true,"dataAlias":"item","ref":8},"itemIcon":{"type":"js-eval","expr":"`/simple-directory/api/avatars/${item.type}/${item.id}/avatar.png`","pure":true,"dataAlias":"item","ref":9},"returnObjects":true}},"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/privateAccess/anyOf/0/items","errorMessage":{"required":{"type":"required information","id":"required information","name":"required information"}}}; +const schema28 = {"type":"object","title":"Account","additionalProperties":false,"required":["type","id","name"],"properties":{"type":{"type":"string","enum":["user","organization"],"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/privateAccess/anyOf/0/items/properties/type","errorMessage":{}},"id":{"type":"string","__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/privateAccess/anyOf/0/items/properties/id","errorMessage":{}},"name":{"type":"string","__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/privateAccess/anyOf/0/items/properties/name","errorMessage":{}}},"layout":{"getItems":{"url":{"type":"js-tpl","expr":"/simple-directory/api/accounts?size=20","pure":true,"dataAlias":"value","ref":8},"qSearchParam":"q","itemsResults":{"type":"js-eval","expr":"data.results","pure":true,"dataAlias":"body","ref":4},"itemTitle":{"type":"js-eval","expr":"`${item.name} (${item.id})`","pure":true,"dataAlias":"item","ref":9},"itemKey":{"type":"js-eval","expr":"`${item.type}:${item.id}`","pure":true,"dataAlias":"item","ref":10},"itemIcon":{"type":"js-eval","expr":"`/simple-directory/api/avatars/${item.type}/${item.id}/avatar.png`","pure":true,"dataAlias":"item","ref":11},"returnObjects":true}},"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/privateAccess/anyOf/0/items","errorMessage":{"required":{"type":"required information","id":"required information","name":"required information"}}}; const obj0 = {"required":"missingProperty","dependencies":"property","dependentRequired":"property"}; function validate22(data, {instancePath="", parentData, parentDataProperty, rootData=data, dynamicAnchors={}}={}){ @@ -224,7 +224,7 @@ return errors === 0; validate22.evaluated = {"props":true,"dynamicProps":false,"dynamicItems":false}; const schema29 = {"$id":"export1","$ref":"https://github.com/data-fair/registry/artefact-patch#"}; -const schema27 = {"$id":"https://github.com/data-fair/registry/artefact-patch","x-exports":["validate","types","vjsf"],"x-vjsf":{"xI18n":true},"x-vjsf-locales":["en","fr"],"title":"Artefact patch","type":"object","additionalProperties":false,"layout":{"title":null},"properties":{"title":{"anyOf":[{"type":"object","additionalProperties":false,"properties":{"en":{"type":"string","title":"Title - English","layout":{"cols":{"md":6}},"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/title/anyOf/0/properties/en","errorMessage":{}},"fr":{"type":"string","title":"Title - French","layout":{"cols":{"md":6}},"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/title/anyOf/0/properties/fr","errorMessage":{}}}},{"type":"null"}],"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/title","errorMessage":{}},"description":{"anyOf":[{"type":"object","additionalProperties":false,"properties":{"en":{"type":"string","title":"Description - English","layout":{"comp":"textarea","props":{"autoGrow":true,"rows":3},"cols":{"md":6}},"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/description/anyOf/0/properties/en","errorMessage":{}},"fr":{"type":"string","title":"Description - French","layout":{"comp":"textarea","props":{"autoGrow":true,"rows":3},"cols":{"md":6}},"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/description/anyOf/0/properties/fr","errorMessage":{}}}},{"type":"null"}],"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/description","errorMessage":{}},"group":{"anyOf":[{"type":"object","additionalProperties":false,"properties":{"en":{"type":"string","title":"Group - English","layout":{"comp":"combobox","cols":{"md":6},"getItems":{"url":{"type":"js-tpl","expr":"${context.apiPath}/v1/artefacts/groups?category=${context.category}&locale=en","pure":true,"dataAlias":"value","ref":2},"itemsResults":{"type":"js-eval","expr":"data.results","pure":true,"dataAlias":"body","ref":3}}},"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/group/anyOf/0/properties/en","errorMessage":{}},"fr":{"type":"string","title":"Group - French","layout":{"comp":"combobox","cols":{"md":6},"getItems":{"url":{"type":"js-tpl","expr":"${context.apiPath}/v1/artefacts/groups?category=${context.category}&locale=fr","pure":true,"dataAlias":"value","ref":4},"itemsResults":{"type":"js-eval","expr":"data.results","pure":true,"dataAlias":"body","ref":3}}},"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/group/anyOf/0/properties/fr","errorMessage":{}}}},{"type":"null"}],"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/group","errorMessage":{}},"deprecated":{"anyOf":[{"type":"boolean","title":"Deprecated","layout":"switch","default":false},{"type":"null"}],"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/deprecated","errorMessage":{}},"public":{"anyOf":[{"type":"boolean","title":"Public","layout":"switch","default":false},{"type":"null"}],"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/public","errorMessage":{}},"privateAccess":{"anyOf":[{"type":"array","title":"Private access","layout":{"if":"!parent.data?.public"},"items":{"type":"object","title":"Account","additionalProperties":false,"required":["type","id","name"],"properties":{"type":{"type":"string","enum":["user","organization"],"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/privateAccess/anyOf/0/items/properties/type","errorMessage":{}},"id":{"type":"string","__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/privateAccess/anyOf/0/items/properties/id","errorMessage":{}},"name":{"type":"string","__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/privateAccess/anyOf/0/items/properties/name","errorMessage":{}}},"layout":{"getItems":{"url":{"type":"js-tpl","expr":"/simple-directory/api/accounts?size=20","pure":true,"dataAlias":"value","ref":6},"qSearchParam":"q","itemsResults":{"type":"js-eval","expr":"data.results","pure":true,"dataAlias":"body","ref":3},"itemTitle":{"type":"js-eval","expr":"`${item.name} (${item.id})`","pure":true,"dataAlias":"item","ref":7},"itemKey":{"type":"js-eval","expr":"`${item.type}:${item.id}`","pure":true,"dataAlias":"item","ref":8},"itemIcon":{"type":"js-eval","expr":"`/simple-directory/api/avatars/${item.type}/${item.id}/avatar.png`","pure":true,"dataAlias":"item","ref":9},"returnObjects":true}},"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/privateAccess/anyOf/0/items","errorMessage":{"required":{"type":"required information","id":"required information","name":"required information"}}}},{"type":"null"}],"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/privateAccess","errorMessage":{}},"documentation":{"anyOf":[{"type":"string","format":"uri","title":"Documentation URL"},{"type":"null"}],"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/documentation","errorMessage":{}}},"__pointer":"https://github.com/data-fair/registry/artefact-patch#","errorMessage":{}}; +const schema27 = {"$id":"https://github.com/data-fair/registry/artefact-patch","x-exports":["validate","types","vjsf"],"x-vjsf":{"xI18n":true},"x-vjsf-locales":["en","fr"],"title":"Artefact patch","type":"object","additionalProperties":false,"layout":{"title":null},"properties":{"title":{"anyOf":[{"type":"object","additionalProperties":false,"layout":{"if":"!context.accessOnly"},"properties":{"en":{"type":"string","title":"Title - English","layout":{"cols":{"md":6}},"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/title/anyOf/0/properties/en","errorMessage":{}},"fr":{"type":"string","title":"Title - French","layout":{"cols":{"md":6}},"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/title/anyOf/0/properties/fr","errorMessage":{}}}},{"type":"null"}],"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/title","errorMessage":{}},"description":{"anyOf":[{"type":"object","additionalProperties":false,"layout":{"if":"!context.accessOnly"},"properties":{"en":{"type":"string","title":"Description - English","layout":{"comp":"textarea","props":{"autoGrow":true,"rows":3},"cols":{"md":6}},"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/description/anyOf/0/properties/en","errorMessage":{}},"fr":{"type":"string","title":"Description - French","layout":{"comp":"textarea","props":{"autoGrow":true,"rows":3},"cols":{"md":6}},"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/description/anyOf/0/properties/fr","errorMessage":{}}}},{"type":"null"}],"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/description","errorMessage":{}},"group":{"anyOf":[{"type":"object","additionalProperties":false,"layout":{"if":"!context.accessOnly"},"properties":{"en":{"type":"string","title":"Group - English","layout":{"comp":"combobox","cols":{"md":6},"getItems":{"url":{"type":"js-tpl","expr":"${context.apiPath}/v1/artefacts/groups?category=${context.category}&locale=en","pure":true,"dataAlias":"value","ref":3},"itemsResults":{"type":"js-eval","expr":"data.results","pure":true,"dataAlias":"body","ref":4}}},"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/group/anyOf/0/properties/en","errorMessage":{}},"fr":{"type":"string","title":"Group - French","layout":{"comp":"combobox","cols":{"md":6},"getItems":{"url":{"type":"js-tpl","expr":"${context.apiPath}/v1/artefacts/groups?category=${context.category}&locale=fr","pure":true,"dataAlias":"value","ref":5},"itemsResults":{"type":"js-eval","expr":"data.results","pure":true,"dataAlias":"body","ref":4}}},"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/group/anyOf/0/properties/fr","errorMessage":{}}}},{"type":"null"}],"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/group","errorMessage":{}},"deprecated":{"anyOf":[{"type":"boolean","title":"Deprecated","layout":{"comp":"switch","if":"!context.accessOnly"},"default":false},{"type":"null"}],"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/deprecated","errorMessage":{}},"public":{"anyOf":[{"type":"boolean","title":"Public","layout":{"comp":"switch","if":"context.accessOnly || !context.mirrored"},"default":false},{"type":"null"}],"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/public","errorMessage":{}},"privateAccess":{"anyOf":[{"type":"array","title":"Private access","layout":{"if":"(context.accessOnly || !context.mirrored) && !parent.data?.public"},"items":{"type":"object","title":"Account","additionalProperties":false,"required":["type","id","name"],"properties":{"type":{"type":"string","enum":["user","organization"],"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/privateAccess/anyOf/0/items/properties/type","errorMessage":{}},"id":{"type":"string","__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/privateAccess/anyOf/0/items/properties/id","errorMessage":{}},"name":{"type":"string","__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/privateAccess/anyOf/0/items/properties/name","errorMessage":{}}},"layout":{"getItems":{"url":{"type":"js-tpl","expr":"/simple-directory/api/accounts?size=20","pure":true,"dataAlias":"value","ref":8},"qSearchParam":"q","itemsResults":{"type":"js-eval","expr":"data.results","pure":true,"dataAlias":"body","ref":4},"itemTitle":{"type":"js-eval","expr":"`${item.name} (${item.id})`","pure":true,"dataAlias":"item","ref":9},"itemKey":{"type":"js-eval","expr":"`${item.type}:${item.id}`","pure":true,"dataAlias":"item","ref":10},"itemIcon":{"type":"js-eval","expr":"`/simple-directory/api/avatars/${item.type}/${item.id}/avatar.png`","pure":true,"dataAlias":"item","ref":11},"returnObjects":true}},"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/privateAccess/anyOf/0/items","errorMessage":{"required":{"type":"required information","id":"required information","name":"required information"}}}},{"type":"null"}],"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/privateAccess","errorMessage":{}},"documentation":{"anyOf":[{"type":"string","format":"uri","title":"Documentation URL","layout":{"if":"!context.accessOnly"}},{"type":"null"}],"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/documentation","errorMessage":{}}},"__pointer":"https://github.com/data-fair/registry/artefact-patch#","errorMessage":{}}; const formats0 = fullFormats.uri; function validate24(data, {instancePath="", parentData, parentDataProperty, rootData=data, dynamicAnchors={}}={}){ @@ -1086,32 +1086,38 @@ function expression0(data,value,options,context,display,layout,readOnly,summary, return (layout.defaultData) }function expression1(data,value,options,context,display,layout,readOnly,summary,validates ) { -return (layout.props) +return (!context.accessOnly) }function expression2(data,value,options,context,display,layout,readOnly,summary,validates ) { +return (layout.props) +}function expression3(data,value,options,context,display,layout,readOnly,summary,validates +) { return `${context.apiPath}/v1/artefacts/groups?category=${context.category}&locale=en` -}function expression3(data,body,options,context,display,layout,readOnly,summary,validates +}function expression4(data,body,options,context,display,layout,readOnly,summary,validates ) { return (data.results) -}function expression4(data,value,options,context,display,layout,readOnly,summary,validates +}function expression5(data,value,options,context,display,layout,readOnly,summary,validates ) { return `${context.apiPath}/v1/artefacts/groups?category=${context.category}&locale=fr` -}function expression5(data,value,options,context,display,layout,readOnly,summary,validates,rootData,parent -) { -return (!parent.data?.public) }function expression6(data,value,options,context,display,layout,readOnly,summary,validates ) { +return (context.accessOnly || !context.mirrored) +}function expression7(data,value,options,context,display,layout,readOnly,summary,validates,rootData,parent +) { +return ((context.accessOnly || !context.mirrored) && !parent.data?.public) +}function expression8(data,value,options,context,display,layout,readOnly,summary,validates +) { return `/simple-directory/api/accounts?size=20` -}function expression7(data,item,options,context,display,layout,readOnly,summary,validates +}function expression9(data,item,options,context,display,layout,readOnly,summary,validates ) { return (`${item.name} (${item.id})`) -}function expression8(data,item,options,context,display,layout,readOnly,summary,validates +}function expression10(data,item,options,context,display,layout,readOnly,summary,validates ) { return (`${item.type}:${item.id}`) -}function expression9(data,item,options,context,display,layout,readOnly,summary,validates +}function expression11(data,item,options,context,display,layout,readOnly,summary,validates ) { return (`/simple-directory/api/avatars/${item.type}/${item.id}/avatar.png`) -}function expression10(data,value,options,context,display,layout,readOnly,summary,validates +}function expression12(data,value,options,context,display,layout,readOnly,summary,validates ) { return ([{"key":"user","title":"user","value":"user"},{"key":"organization","title":"organization","value":"organization"}]) } @@ -1392,6 +1398,14 @@ const compiledLayout = { }, "https://github.com/data-fair/registry/artefact-patch#/properties/title/anyOf/0": { + if: { + type: "js-eval", + expr: "!context.accessOnly", + pure: true, + dataAlias: "value", + ref: 1 + }, + comp: "section", nullable: true, @@ -1425,6 +1439,14 @@ const compiledLayout = { }, "https://github.com/data-fair/registry/artefact-patch#/properties/description/anyOf/0": { + if: { + type: "js-eval", + expr: "!context.accessOnly", + pure: true, + dataAlias: "value", + ref: 1 + }, + comp: "section", nullable: true, @@ -1457,7 +1479,7 @@ const compiledLayout = { expr: "layout.props", pure: true, dataAlias: "value", - ref: 1 + ref: 2 } }, @@ -1481,11 +1503,19 @@ const compiledLayout = { expr: "layout.props", pure: true, dataAlias: "value", - ref: 1 + ref: 2 } }, "https://github.com/data-fair/registry/artefact-patch#/properties/group/anyOf/0": { + if: { + type: "js-eval", + expr: "!context.accessOnly", + pure: true, + dataAlias: "value", + ref: 1 + }, + comp: "section", nullable: true, @@ -1512,7 +1542,7 @@ const compiledLayout = { expr: "${context.apiPath}/v1/artefacts/groups?category=${context.category}&locale=en", pure: true, dataAlias: "value", - ref: 2 + ref: 3 }, itemsResults: { @@ -1520,7 +1550,7 @@ const compiledLayout = { expr: "data.results", pure: true, dataAlias: "body", - ref: 3 + ref: 4 } }, @@ -1541,7 +1571,7 @@ const compiledLayout = { expr: "${context.apiPath}/v1/artefacts/groups?category=${context.category}&locale=fr", pure: true, dataAlias: "value", - ref: 4 + ref: 5 }, itemsResults: { @@ -1549,7 +1579,7 @@ const compiledLayout = { expr: "data.results", pure: true, dataAlias: "body", - ref: 3 + ref: 4 } }, @@ -1558,6 +1588,15 @@ const compiledLayout = { "https://github.com/data-fair/registry/artefact-patch#/properties/deprecated/anyOf/0": { comp: "switch", + + if: { + type: "js-eval", + expr: "!context.accessOnly", + pure: true, + dataAlias: "value", + ref: 1 + }, + nullable: true, label: "Deprecated", defaultData: false, @@ -1573,6 +1612,15 @@ const compiledLayout = { "https://github.com/data-fair/registry/artefact-patch#/properties/public/anyOf/0": { comp: "switch", + + if: { + type: "js-eval", + expr: "context.accessOnly || !context.mirrored", + pure: true, + dataAlias: "value", + ref: 6 + }, + nullable: true, label: "Public", defaultData: false, @@ -1589,10 +1637,10 @@ const compiledLayout = { "https://github.com/data-fair/registry/artefact-patch#/properties/privateAccess/anyOf/0": { if: { type: "js-eval", - expr: "!parent.data?.public", + expr: "(context.accessOnly || !context.mirrored) && !parent.data?.public", pure: false, dataAlias: "value", - ref: 5 + ref: 7 }, comp: "list", @@ -1609,7 +1657,7 @@ const compiledLayout = { expr: "/simple-directory/api/accounts?size=20", pure: true, dataAlias: "value", - ref: 6 + ref: 8 }, qSearchParam: "q", @@ -1619,7 +1667,7 @@ const compiledLayout = { expr: "data.results", pure: true, dataAlias: "body", - ref: 3 + ref: 4 }, itemTitle: { @@ -1627,7 +1675,7 @@ const compiledLayout = { expr: "`${item.name} (${item.id})`", pure: true, dataAlias: "item", - ref: 7 + ref: 9 }, itemKey: { @@ -1635,7 +1683,7 @@ const compiledLayout = { expr: "`${item.type}:${item.id}`", pure: true, dataAlias: "item", - ref: 8 + ref: 10 }, itemIcon: { @@ -1643,7 +1691,7 @@ const compiledLayout = { expr: "`/simple-directory/api/avatars/${item.type}/${item.id}/avatar.png`", pure: true, dataAlias: "item", - ref: 9 + ref: 11 }, returnObjects: true @@ -1663,7 +1711,7 @@ const compiledLayout = { dataAlias: "value", expr: "[{\"key\":\"user\",\"title\":\"user\",\"value\":\"user\"},{\"key\":\"organization\",\"title\":\"organization\",\"value\":\"organization\"}]", immutable: true, - ref: 10 + ref: 12 }, label: "type" @@ -1680,6 +1728,14 @@ const compiledLayout = { }, "https://github.com/data-fair/registry/artefact-patch#/properties/documentation/anyOf/0": { + if: { + type: "js-eval", + expr: "!context.accessOnly", + pure: true, + dataAlias: "value", + ref: 1 + }, + comp: "text-field", nullable: true, label: "Documentation URL" @@ -1692,7 +1748,7 @@ const compiledLayout = { }, validationErrors: {}, - expressions: [expression0, expression1, expression2, expression3, expression4, expression5, expression6, expression7, expression8, expression9, expression10], + expressions: [expression0, expression1, expression2, expression3, expression4, expression5, expression6, expression7, expression8, expression9, expression10, expression11, expression12], locale: "en", messages: { diff --git a/ui/src/components/vjsf/vjsf-patch-req-fr.vue b/ui/src/components/vjsf/vjsf-patch-req-fr.vue index bfebd84..1a5b679 100644 --- a/ui/src/components/vjsf/vjsf-patch-req-fr.vue +++ b/ui/src/components/vjsf/vjsf-patch-req-fr.vue @@ -31,7 +31,7 @@ import localizeErrors from "ajv-i18n/localize/fr/index.js"; import { fullFormats } from "ajv-formats/dist/formats.js"; const schema26 = {"$id":"export0","$ref":"https://github.com/data-fair/registry/artefact-patch#/properties/privateAccess/anyOf/0/items"}; -const schema28 = {"type":"object","title":"Compte","additionalProperties":false,"required":["type","id","name"],"properties":{"type":{"type":"string","enum":["user","organization"],"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/privateAccess/anyOf/0/items/properties/type","errorMessage":{}},"id":{"type":"string","__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/privateAccess/anyOf/0/items/properties/id","errorMessage":{}},"name":{"type":"string","__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/privateAccess/anyOf/0/items/properties/name","errorMessage":{}}},"layout":{"getItems":{"url":{"type":"js-tpl","expr":"/simple-directory/api/accounts?size=20","pure":true,"dataAlias":"value","ref":6},"qSearchParam":"q","itemsResults":{"type":"js-eval","expr":"data.results","pure":true,"dataAlias":"body","ref":3},"itemTitle":{"type":"js-eval","expr":"`${item.name} (${item.id})`","pure":true,"dataAlias":"item","ref":7},"itemKey":{"type":"js-eval","expr":"`${item.type}:${item.id}`","pure":true,"dataAlias":"item","ref":8},"itemIcon":{"type":"js-eval","expr":"`/simple-directory/api/avatars/${item.type}/${item.id}/avatar.png`","pure":true,"dataAlias":"item","ref":9},"returnObjects":true}},"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/privateAccess/anyOf/0/items","errorMessage":{"required":{"type":"information obligatoire","id":"information obligatoire","name":"information obligatoire"}}}; +const schema28 = {"type":"object","title":"Compte","additionalProperties":false,"required":["type","id","name"],"properties":{"type":{"type":"string","enum":["user","organization"],"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/privateAccess/anyOf/0/items/properties/type","errorMessage":{}},"id":{"type":"string","__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/privateAccess/anyOf/0/items/properties/id","errorMessage":{}},"name":{"type":"string","__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/privateAccess/anyOf/0/items/properties/name","errorMessage":{}}},"layout":{"getItems":{"url":{"type":"js-tpl","expr":"/simple-directory/api/accounts?size=20","pure":true,"dataAlias":"value","ref":8},"qSearchParam":"q","itemsResults":{"type":"js-eval","expr":"data.results","pure":true,"dataAlias":"body","ref":4},"itemTitle":{"type":"js-eval","expr":"`${item.name} (${item.id})`","pure":true,"dataAlias":"item","ref":9},"itemKey":{"type":"js-eval","expr":"`${item.type}:${item.id}`","pure":true,"dataAlias":"item","ref":10},"itemIcon":{"type":"js-eval","expr":"`/simple-directory/api/avatars/${item.type}/${item.id}/avatar.png`","pure":true,"dataAlias":"item","ref":11},"returnObjects":true}},"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/privateAccess/anyOf/0/items","errorMessage":{"required":{"type":"information obligatoire","id":"information obligatoire","name":"information obligatoire"}}}; const obj0 = {"required":"missingProperty","dependencies":"property","dependentRequired":"property"}; function validate22(data, {instancePath="", parentData, parentDataProperty, rootData=data, dynamicAnchors={}}={}){ @@ -224,7 +224,7 @@ return errors === 0; validate22.evaluated = {"props":true,"dynamicProps":false,"dynamicItems":false}; const schema29 = {"$id":"export1","$ref":"https://github.com/data-fair/registry/artefact-patch#"}; -const schema27 = {"$id":"https://github.com/data-fair/registry/artefact-patch","x-exports":["validate","types","vjsf"],"x-vjsf":{"xI18n":true},"x-vjsf-locales":["en","fr"],"title":"Artefact patch","type":"object","additionalProperties":false,"layout":{"title":null},"properties":{"title":{"anyOf":[{"type":"object","additionalProperties":false,"properties":{"en":{"type":"string","title":"Titre - Anglais","layout":{"cols":{"md":6}},"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/title/anyOf/0/properties/en","errorMessage":{}},"fr":{"type":"string","title":"Titre - Français","layout":{"cols":{"md":6}},"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/title/anyOf/0/properties/fr","errorMessage":{}}}},{"type":"null"}],"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/title","errorMessage":{}},"description":{"anyOf":[{"type":"object","additionalProperties":false,"properties":{"en":{"type":"string","title":"Description - Anglais","layout":{"comp":"textarea","props":{"autoGrow":true,"rows":3},"cols":{"md":6}},"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/description/anyOf/0/properties/en","errorMessage":{}},"fr":{"type":"string","title":"Description - Français","layout":{"comp":"textarea","props":{"autoGrow":true,"rows":3},"cols":{"md":6}},"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/description/anyOf/0/properties/fr","errorMessage":{}}}},{"type":"null"}],"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/description","errorMessage":{}},"group":{"anyOf":[{"type":"object","additionalProperties":false,"properties":{"en":{"type":"string","title":"Groupe - Anglais","layout":{"comp":"combobox","cols":{"md":6},"getItems":{"url":{"type":"js-tpl","expr":"${context.apiPath}/v1/artefacts/groups?category=${context.category}&locale=en","pure":true,"dataAlias":"value","ref":2},"itemsResults":{"type":"js-eval","expr":"data.results","pure":true,"dataAlias":"body","ref":3}}},"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/group/anyOf/0/properties/en","errorMessage":{}},"fr":{"type":"string","title":"Groupe - Français","layout":{"comp":"combobox","cols":{"md":6},"getItems":{"url":{"type":"js-tpl","expr":"${context.apiPath}/v1/artefacts/groups?category=${context.category}&locale=fr","pure":true,"dataAlias":"value","ref":4},"itemsResults":{"type":"js-eval","expr":"data.results","pure":true,"dataAlias":"body","ref":3}}},"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/group/anyOf/0/properties/fr","errorMessage":{}}}},{"type":"null"}],"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/group","errorMessage":{}},"deprecated":{"anyOf":[{"type":"boolean","title":"Déprécié","layout":"switch","default":false},{"type":"null"}],"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/deprecated","errorMessage":{}},"public":{"anyOf":[{"type":"boolean","title":"Public","layout":"switch","default":false},{"type":"null"}],"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/public","errorMessage":{}},"privateAccess":{"anyOf":[{"type":"array","title":"Accès privés","layout":{"if":"!parent.data?.public"},"items":{"type":"object","title":"Compte","additionalProperties":false,"required":["type","id","name"],"properties":{"type":{"type":"string","enum":["user","organization"],"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/privateAccess/anyOf/0/items/properties/type","errorMessage":{}},"id":{"type":"string","__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/privateAccess/anyOf/0/items/properties/id","errorMessage":{}},"name":{"type":"string","__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/privateAccess/anyOf/0/items/properties/name","errorMessage":{}}},"layout":{"getItems":{"url":{"type":"js-tpl","expr":"/simple-directory/api/accounts?size=20","pure":true,"dataAlias":"value","ref":6},"qSearchParam":"q","itemsResults":{"type":"js-eval","expr":"data.results","pure":true,"dataAlias":"body","ref":3},"itemTitle":{"type":"js-eval","expr":"`${item.name} (${item.id})`","pure":true,"dataAlias":"item","ref":7},"itemKey":{"type":"js-eval","expr":"`${item.type}:${item.id}`","pure":true,"dataAlias":"item","ref":8},"itemIcon":{"type":"js-eval","expr":"`/simple-directory/api/avatars/${item.type}/${item.id}/avatar.png`","pure":true,"dataAlias":"item","ref":9},"returnObjects":true}},"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/privateAccess/anyOf/0/items","errorMessage":{"required":{"type":"information obligatoire","id":"information obligatoire","name":"information obligatoire"}}}},{"type":"null"}],"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/privateAccess","errorMessage":{}},"documentation":{"anyOf":[{"type":"string","format":"uri","title":"URL de documentation"},{"type":"null"}],"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/documentation","errorMessage":{}}},"__pointer":"https://github.com/data-fair/registry/artefact-patch#","errorMessage":{}}; +const schema27 = {"$id":"https://github.com/data-fair/registry/artefact-patch","x-exports":["validate","types","vjsf"],"x-vjsf":{"xI18n":true},"x-vjsf-locales":["en","fr"],"title":"Artefact patch","type":"object","additionalProperties":false,"layout":{"title":null},"properties":{"title":{"anyOf":[{"type":"object","additionalProperties":false,"layout":{"if":"!context.accessOnly"},"properties":{"en":{"type":"string","title":"Titre - Anglais","layout":{"cols":{"md":6}},"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/title/anyOf/0/properties/en","errorMessage":{}},"fr":{"type":"string","title":"Titre - Français","layout":{"cols":{"md":6}},"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/title/anyOf/0/properties/fr","errorMessage":{}}}},{"type":"null"}],"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/title","errorMessage":{}},"description":{"anyOf":[{"type":"object","additionalProperties":false,"layout":{"if":"!context.accessOnly"},"properties":{"en":{"type":"string","title":"Description - Anglais","layout":{"comp":"textarea","props":{"autoGrow":true,"rows":3},"cols":{"md":6}},"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/description/anyOf/0/properties/en","errorMessage":{}},"fr":{"type":"string","title":"Description - Français","layout":{"comp":"textarea","props":{"autoGrow":true,"rows":3},"cols":{"md":6}},"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/description/anyOf/0/properties/fr","errorMessage":{}}}},{"type":"null"}],"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/description","errorMessage":{}},"group":{"anyOf":[{"type":"object","additionalProperties":false,"layout":{"if":"!context.accessOnly"},"properties":{"en":{"type":"string","title":"Groupe - Anglais","layout":{"comp":"combobox","cols":{"md":6},"getItems":{"url":{"type":"js-tpl","expr":"${context.apiPath}/v1/artefacts/groups?category=${context.category}&locale=en","pure":true,"dataAlias":"value","ref":3},"itemsResults":{"type":"js-eval","expr":"data.results","pure":true,"dataAlias":"body","ref":4}}},"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/group/anyOf/0/properties/en","errorMessage":{}},"fr":{"type":"string","title":"Groupe - Français","layout":{"comp":"combobox","cols":{"md":6},"getItems":{"url":{"type":"js-tpl","expr":"${context.apiPath}/v1/artefacts/groups?category=${context.category}&locale=fr","pure":true,"dataAlias":"value","ref":5},"itemsResults":{"type":"js-eval","expr":"data.results","pure":true,"dataAlias":"body","ref":4}}},"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/group/anyOf/0/properties/fr","errorMessage":{}}}},{"type":"null"}],"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/group","errorMessage":{}},"deprecated":{"anyOf":[{"type":"boolean","title":"Déprécié","layout":{"comp":"switch","if":"!context.accessOnly"},"default":false},{"type":"null"}],"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/deprecated","errorMessage":{}},"public":{"anyOf":[{"type":"boolean","title":"Public","layout":{"comp":"switch","if":"context.accessOnly || !context.mirrored"},"default":false},{"type":"null"}],"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/public","errorMessage":{}},"privateAccess":{"anyOf":[{"type":"array","title":"Accès privés","layout":{"if":"(context.accessOnly || !context.mirrored) && !parent.data?.public"},"items":{"type":"object","title":"Compte","additionalProperties":false,"required":["type","id","name"],"properties":{"type":{"type":"string","enum":["user","organization"],"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/privateAccess/anyOf/0/items/properties/type","errorMessage":{}},"id":{"type":"string","__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/privateAccess/anyOf/0/items/properties/id","errorMessage":{}},"name":{"type":"string","__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/privateAccess/anyOf/0/items/properties/name","errorMessage":{}}},"layout":{"getItems":{"url":{"type":"js-tpl","expr":"/simple-directory/api/accounts?size=20","pure":true,"dataAlias":"value","ref":8},"qSearchParam":"q","itemsResults":{"type":"js-eval","expr":"data.results","pure":true,"dataAlias":"body","ref":4},"itemTitle":{"type":"js-eval","expr":"`${item.name} (${item.id})`","pure":true,"dataAlias":"item","ref":9},"itemKey":{"type":"js-eval","expr":"`${item.type}:${item.id}`","pure":true,"dataAlias":"item","ref":10},"itemIcon":{"type":"js-eval","expr":"`/simple-directory/api/avatars/${item.type}/${item.id}/avatar.png`","pure":true,"dataAlias":"item","ref":11},"returnObjects":true}},"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/privateAccess/anyOf/0/items","errorMessage":{"required":{"type":"information obligatoire","id":"information obligatoire","name":"information obligatoire"}}}},{"type":"null"}],"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/privateAccess","errorMessage":{}},"documentation":{"anyOf":[{"type":"string","format":"uri","title":"URL de documentation","layout":{"if":"!context.accessOnly"}},{"type":"null"}],"__pointer":"https://github.com/data-fair/registry/artefact-patch#/properties/documentation","errorMessage":{}}},"__pointer":"https://github.com/data-fair/registry/artefact-patch#","errorMessage":{}}; const formats0 = fullFormats.uri; function validate24(data, {instancePath="", parentData, parentDataProperty, rootData=data, dynamicAnchors={}}={}){ @@ -1086,32 +1086,38 @@ function expression0(data,value,options,context,display,layout,readOnly,summary, return (layout.defaultData) }function expression1(data,value,options,context,display,layout,readOnly,summary,validates ) { -return (layout.props) +return (!context.accessOnly) }function expression2(data,value,options,context,display,layout,readOnly,summary,validates ) { +return (layout.props) +}function expression3(data,value,options,context,display,layout,readOnly,summary,validates +) { return `${context.apiPath}/v1/artefacts/groups?category=${context.category}&locale=en` -}function expression3(data,body,options,context,display,layout,readOnly,summary,validates +}function expression4(data,body,options,context,display,layout,readOnly,summary,validates ) { return (data.results) -}function expression4(data,value,options,context,display,layout,readOnly,summary,validates +}function expression5(data,value,options,context,display,layout,readOnly,summary,validates ) { return `${context.apiPath}/v1/artefacts/groups?category=${context.category}&locale=fr` -}function expression5(data,value,options,context,display,layout,readOnly,summary,validates,rootData,parent -) { -return (!parent.data?.public) }function expression6(data,value,options,context,display,layout,readOnly,summary,validates ) { +return (context.accessOnly || !context.mirrored) +}function expression7(data,value,options,context,display,layout,readOnly,summary,validates,rootData,parent +) { +return ((context.accessOnly || !context.mirrored) && !parent.data?.public) +}function expression8(data,value,options,context,display,layout,readOnly,summary,validates +) { return `/simple-directory/api/accounts?size=20` -}function expression7(data,item,options,context,display,layout,readOnly,summary,validates +}function expression9(data,item,options,context,display,layout,readOnly,summary,validates ) { return (`${item.name} (${item.id})`) -}function expression8(data,item,options,context,display,layout,readOnly,summary,validates +}function expression10(data,item,options,context,display,layout,readOnly,summary,validates ) { return (`${item.type}:${item.id}`) -}function expression9(data,item,options,context,display,layout,readOnly,summary,validates +}function expression11(data,item,options,context,display,layout,readOnly,summary,validates ) { return (`/simple-directory/api/avatars/${item.type}/${item.id}/avatar.png`) -}function expression10(data,value,options,context,display,layout,readOnly,summary,validates +}function expression12(data,value,options,context,display,layout,readOnly,summary,validates ) { return ([{"key":"user","title":"user","value":"user"},{"key":"organization","title":"organization","value":"organization"}]) } @@ -1392,6 +1398,14 @@ const compiledLayout = { }, "https://github.com/data-fair/registry/artefact-patch#/properties/title/anyOf/0": { + if: { + type: "js-eval", + expr: "!context.accessOnly", + pure: true, + dataAlias: "value", + ref: 1 + }, + comp: "section", nullable: true, @@ -1425,6 +1439,14 @@ const compiledLayout = { }, "https://github.com/data-fair/registry/artefact-patch#/properties/description/anyOf/0": { + if: { + type: "js-eval", + expr: "!context.accessOnly", + pure: true, + dataAlias: "value", + ref: 1 + }, + comp: "section", nullable: true, @@ -1457,7 +1479,7 @@ const compiledLayout = { expr: "layout.props", pure: true, dataAlias: "value", - ref: 1 + ref: 2 } }, @@ -1481,11 +1503,19 @@ const compiledLayout = { expr: "layout.props", pure: true, dataAlias: "value", - ref: 1 + ref: 2 } }, "https://github.com/data-fair/registry/artefact-patch#/properties/group/anyOf/0": { + if: { + type: "js-eval", + expr: "!context.accessOnly", + pure: true, + dataAlias: "value", + ref: 1 + }, + comp: "section", nullable: true, @@ -1512,7 +1542,7 @@ const compiledLayout = { expr: "${context.apiPath}/v1/artefacts/groups?category=${context.category}&locale=en", pure: true, dataAlias: "value", - ref: 2 + ref: 3 }, itemsResults: { @@ -1520,7 +1550,7 @@ const compiledLayout = { expr: "data.results", pure: true, dataAlias: "body", - ref: 3 + ref: 4 } }, @@ -1541,7 +1571,7 @@ const compiledLayout = { expr: "${context.apiPath}/v1/artefacts/groups?category=${context.category}&locale=fr", pure: true, dataAlias: "value", - ref: 4 + ref: 5 }, itemsResults: { @@ -1549,7 +1579,7 @@ const compiledLayout = { expr: "data.results", pure: true, dataAlias: "body", - ref: 3 + ref: 4 } }, @@ -1558,6 +1588,15 @@ const compiledLayout = { "https://github.com/data-fair/registry/artefact-patch#/properties/deprecated/anyOf/0": { comp: "switch", + + if: { + type: "js-eval", + expr: "!context.accessOnly", + pure: true, + dataAlias: "value", + ref: 1 + }, + nullable: true, label: "Déprécié", defaultData: false, @@ -1573,6 +1612,15 @@ const compiledLayout = { "https://github.com/data-fair/registry/artefact-patch#/properties/public/anyOf/0": { comp: "switch", + + if: { + type: "js-eval", + expr: "context.accessOnly || !context.mirrored", + pure: true, + dataAlias: "value", + ref: 6 + }, + nullable: true, label: "Public", defaultData: false, @@ -1589,10 +1637,10 @@ const compiledLayout = { "https://github.com/data-fair/registry/artefact-patch#/properties/privateAccess/anyOf/0": { if: { type: "js-eval", - expr: "!parent.data?.public", + expr: "(context.accessOnly || !context.mirrored) && !parent.data?.public", pure: false, dataAlias: "value", - ref: 5 + ref: 7 }, comp: "list", @@ -1609,7 +1657,7 @@ const compiledLayout = { expr: "/simple-directory/api/accounts?size=20", pure: true, dataAlias: "value", - ref: 6 + ref: 8 }, qSearchParam: "q", @@ -1619,7 +1667,7 @@ const compiledLayout = { expr: "data.results", pure: true, dataAlias: "body", - ref: 3 + ref: 4 }, itemTitle: { @@ -1627,7 +1675,7 @@ const compiledLayout = { expr: "`${item.name} (${item.id})`", pure: true, dataAlias: "item", - ref: 7 + ref: 9 }, itemKey: { @@ -1635,7 +1683,7 @@ const compiledLayout = { expr: "`${item.type}:${item.id}`", pure: true, dataAlias: "item", - ref: 8 + ref: 10 }, itemIcon: { @@ -1643,7 +1691,7 @@ const compiledLayout = { expr: "`/simple-directory/api/avatars/${item.type}/${item.id}/avatar.png`", pure: true, dataAlias: "item", - ref: 9 + ref: 11 }, returnObjects: true @@ -1663,7 +1711,7 @@ const compiledLayout = { dataAlias: "value", expr: "[{\"key\":\"user\",\"title\":\"user\",\"value\":\"user\"},{\"key\":\"organization\",\"title\":\"organization\",\"value\":\"organization\"}]", immutable: true, - ref: 10 + ref: 12 }, label: "type" @@ -1680,6 +1728,14 @@ const compiledLayout = { }, "https://github.com/data-fair/registry/artefact-patch#/properties/documentation/anyOf/0": { + if: { + type: "js-eval", + expr: "!context.accessOnly", + pure: true, + dataAlias: "value", + ref: 1 + }, + comp: "text-field", nullable: true, label: "URL de documentation" @@ -1692,7 +1748,7 @@ const compiledLayout = { }, validationErrors: {}, - expressions: [expression0, expression1, expression2, expression3, expression4, expression5, expression6, expression7, expression8, expression9, expression10], + expressions: [expression0, expression1, expression2, expression3, expression4, expression5, expression6, expression7, expression8, expression9, expression10, expression11, expression12], locale: "fr", messages: { From ba1cf3388ebd970b0e2546c3add7ec162c147a40 Mon Sep 17 00:00:00 2001 From: Alban Mouton Date: Mon, 1 Jun 2026 17:13:39 +0200 Subject: [PATCH 2/2] chore: update agent skill --- .agents/skills/pr-ready/SKILL.md | 2 ++ skills-lock.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.agents/skills/pr-ready/SKILL.md b/.agents/skills/pr-ready/SKILL.md index 97ea79a..5482e8e 100644 --- a/.agents/skills/pr-ready/SKILL.md +++ b/.agents/skills/pr-ready/SKILL.md @@ -133,6 +133,8 @@ Required content: Length guidance: as compact as the change allows. A typo fix is one sentence. A multi-part feature is a short summary plus a tight bullet list. **No filler, no test-plan boilerplate, no marketing tone.** If you find yourself padding, stop. +Line breaks: **no superfluous line breaks.** Only insert a blank line where it marks a genuine section delimitation (e.g. between the summary and a `**Why:**` block, or before a bullet list). Do not separate every sentence with a blank line, do not pad between bullets, and do not add leading or trailing blank lines. + Example, for a small feature: ```markdown diff --git a/skills-lock.json b/skills-lock.json index 4fccda3..802734e 100644 --- a/skills-lock.json +++ b/skills-lock.json @@ -5,7 +5,7 @@ "source": "data-fair/lib", "sourceType": "github", "skillPath": "skills/pr-ready/SKILL.md", - "computedHash": "dd62e51657c77f3f44972b9ee62d3082a0503b3deb10f40d9fc64b45cd778451" + "computedHash": "88ee2f1b52748972924a4c8755be1be39916005a08cf97e6aa3b3076d38e27b3" }, "upgrade-scripts": { "source": "data-fair/lib",