diff --git a/api/config/development.mjs b/api/config/development.mjs index 9e37ef41..ee27bada 100644 --- a/api/config/development.mjs +++ b/api/config/development.mjs @@ -7,7 +7,7 @@ export default { }, port: 8082, privateDirectoryUrl: 'http://localhost:8080', - privateEventsUrl: 'http://localhost:8084', + privateEventsUrl: 'http://localhost:8083', secretKeys: { identities: 'secret-identities', events: 'secret-events' diff --git a/api/config/test.mjs b/api/config/test.mjs index aafec418..0c4481ef 100644 --- a/api/config/test.mjs +++ b/api/config/test.mjs @@ -7,7 +7,7 @@ export default { }, port: 8082, privateDirectoryUrl: 'http://localhost:8080', - privateEventsUrl: 'http://localhost:8084', + privateEventsUrl: 'http://localhost:8083', secretKeys: { identities: 'secret-identities', events: 'secret-events' diff --git a/api/package.json b/api/package.json index dcc67962..92e2b0a0 100644 --- a/api/package.json +++ b/api/package.json @@ -18,7 +18,6 @@ "@types/memoizee": "^0.4.11", "@types/multer": "^1.4.13", "@types/resolve-path": "^1.4.3", - "@types/semver": "^7.5.8", "@types/ws": "^8.5.12" }, "dependencies": { @@ -38,7 +37,7 @@ "multer": "^2.0.1", "nanoid": "^5.0.8", "resolve-path": "^1.4.0", - "semver": "^7.6.3", + "semver": "^7.7.4", "tmp-promise": "^3.0.3", "ws": "^8.18.0" } diff --git a/api/src/admin.ts b/api/src/admin/router.ts similarity index 76% rename from api/src/admin.ts rename to api/src/admin/router.ts index bc6ed9b6..260525fa 100644 --- a/api/src/admin.ts +++ b/api/src/admin/router.ts @@ -2,7 +2,8 @@ import { resolve } from 'node:path' import { readFile } from 'node:fs/promises' import { Router } from 'express' import { reqOrigin, session } from '@data-fair/lib-express' -import getApiDoc from './utils/api-docs.ts' +import { getStatus } from './status.ts' +import getApiDoc from '../misc/utils/api-docs.ts' const router = Router() export default router @@ -15,12 +16,17 @@ router.use(async (req, res, next) => { let info = { version: process.env.NODE_ENV } if (process.env.NODE_ENV === 'production') { - info = JSON.parse(await readFile(resolve(import.meta.dirname, '../../BUILD.json'), 'utf8')) + info = JSON.parse(await readFile(resolve(import.meta.dirname, '../../../BUILD.json'), 'utf8')) } router.get('/info', (req, res) => { res.send(info) }) +router.get('/status', async (req, res) => { + const status = await getStatus(req) + res.send(status) +}) + // Get the full API documentation of the service router.get('/api-docs.json', async (req, res) => { res.json(getApiDoc(reqOrigin(req))) diff --git a/api/src/admin/status.ts b/api/src/admin/status.ts new file mode 100644 index 00000000..2e03ddb1 --- /dev/null +++ b/api/src/admin/status.ts @@ -0,0 +1,55 @@ +import type { Request } from 'express' +import mongo from '#mongo' +import config from '#config' +import fs from 'node:fs/promises' + +const mongoStatus = async () => { await mongo.db.command({ ping: 1 }) } +const volumeStatus = async () => { + await fs.writeFile(`${config.dataDir}/check-access.txt`, 'ok') +} + +export const getStatus = async (req: Request) => + runHealthChecks(req, [ + { fn: mongoStatus, name: 'mongodb' }, + { fn: volumeStatus, name: 'data volume' } + ]) + +// Helper functions +const getSingleStatus = async (req: Request, fn: (req: Request) => Promise, name: string) => { + const start = performance.now() + try { + await fn(req) + return { + status: 'ok', + name, + timeInMs: Math.round(performance.now() - start) + } + } catch (err) { + return { + status: 'error', + message: err instanceof Error ? err.message : String(err), + name, + timeInMs: Math.round(performance.now() - start) + } + } +} +const runHealthChecks = async ( + req: Request, + checks: Array<{ fn: (req: Request) => Promise; name: string }> +) => { + let results + try { + results = await Promise.all(checks.map(({ fn, name }) => getSingleStatus(req, fn, name))) + } catch (err: any) { + return { + status: 'error', + details: err.toString() + } + } + const errors = results.filter(r => r.status === 'error') + return { + status: errors.length ? 'error' : 'ok', + message: errors.length ? ('Problem with : ' + errors.map(s => s.name).join(', ')) : 'Service is ok', + details: results + } +} diff --git a/api/src/app.ts b/api/src/app.ts index 44241549..c5846148 100644 --- a/api/src/app.ts +++ b/api/src/app.ts @@ -1,13 +1,13 @@ import { resolve } from 'node:path' import express from 'express' import { session, errorHandler, createSiteMiddleware, createSpaMiddleware, defaultNonceCSPDirectives } from '@data-fair/lib-express/index.js' -import identitiesRouter from './routers/identities.ts' -import limitsRouter from './routers/limits.ts' -import pluginsRegistryRouter from './routers/plugins-registry.ts' -import pluginsRouter from './routers/plugins.ts' -import processingsRouter from './routers/processings.ts' -import runsRouter from './routers/runs.ts' -import adminRouter from './admin.ts' +import identitiesRouter from './misc/routers/identities.ts' +import limitsRouter from './limits/router.ts' +import pluginsRegistryRouter from './plugins-registry/router.ts' +import pluginsRouter from './plugins/router.ts' +import processingsRouter from './processings/router.ts' +import runsRouter from './runs/router.ts' +import adminRouter from './admin/router.ts' import config, { uiConfig } from '#config' export const app = express() diff --git a/api/src/routers/limits.ts b/api/src/limits/router.ts similarity index 100% rename from api/src/routers/limits.ts rename to api/src/limits/router.ts diff --git a/api/src/routers/identities.ts b/api/src/misc/routers/identities.ts similarity index 100% rename from api/src/routers/identities.ts rename to api/src/misc/routers/identities.ts diff --git a/api/src/utils/api-docs.ts b/api/src/misc/utils/api-docs.ts similarity index 99% rename from api/src/utils/api-docs.ts rename to api/src/misc/utils/api-docs.ts index 932f0670..612a1af9 100644 --- a/api/src/utils/api-docs.ts +++ b/api/src/misc/utils/api-docs.ts @@ -4,7 +4,7 @@ import { type Plugin, resolvedSchema as PluginSchema } from '#types/plugin/index import { readFileSync } from 'node:fs' import path from 'path' -const packageJson = JSON.parse(readFileSync(path.resolve(import.meta.dirname, '../../package.json'), 'utf-8')) +const packageJson = JSON.parse(readFileSync(path.resolve(import.meta.dirname, '../../../package.json'), 'utf-8')) // CTRL + K CTRL + 4 to fold operations levels diff --git a/api/src/utils/find.ts b/api/src/misc/utils/find.ts similarity index 100% rename from api/src/utils/find.ts rename to api/src/misc/utils/find.ts diff --git a/api/src/utils/permissions.ts b/api/src/misc/utils/permissions.ts similarity index 100% rename from api/src/utils/permissions.ts rename to api/src/misc/utils/permissions.ts diff --git a/api/src/routers/plugins-registry.ts b/api/src/plugins-registry/router.ts similarity index 100% rename from api/src/routers/plugins-registry.ts rename to api/src/plugins-registry/router.ts diff --git a/api/src/routers/plugins.ts b/api/src/plugins/router.ts similarity index 98% rename from api/src/routers/plugins.ts rename to api/src/plugins/router.ts index ec976f54..e0e37a6a 100644 --- a/api/src/routers/plugins.ts +++ b/api/src/plugins/router.ts @@ -15,7 +15,7 @@ import multer from 'multer' import { session, httpError } from '@data-fair/lib-express' import mongo from '#mongo' import config from '#config' -import permissions from '../utils/permissions.ts' +import permissions from '../misc/utils/permissions.ts' // @ts-ignore const ajv = ajvFormats(new Ajv({ strict: false })) @@ -264,6 +264,7 @@ router.delete('/:id', permissions.isSuperAdmin, async (req, res) => { await fs.remove(path.join(pluginsDir, req.params.id)) await fs.remove(path.join(pluginsDir, req.params.id + '-config.json')) await fs.remove(path.join(pluginsDir, req.params.id + '-access.json')) + await fs.remove(path.join(pluginsDir, req.params.id + '-metadata.json')) res.status(204).send() }) diff --git a/api/src/routers/processings.ts b/api/src/processings/router.ts similarity index 98% rename from api/src/routers/processings.ts rename to api/src/processings/router.ts index a504e58f..1a4daf6a 100644 --- a/api/src/routers/processings.ts +++ b/api/src/processings/router.ts @@ -15,15 +15,15 @@ import eventsQueue from '@data-fair/lib-node/events-queue.js' import { reqOrigin, session } from '@data-fair/lib-express/index.js' import { httpError } from '@data-fair/lib-utils/http-errors.js' import { createNext } from '@data-fair/processings-shared/runs.ts' -import { applyProcessing, deleteProcessing } from '../utils/runs.ts' +import { applyProcessing, deleteProcessing } from '../runs/service.ts' import { cipher, decipher } from '@data-fair/processings-shared/cipher.ts' import mongo from '#mongo' import config from '#config' import locks from '#locks' import { resolvedSchema as processingSchema } from '#types/processing/index.ts' -import getApiDoc from '../utils/api-docs.ts' -import findUtils from '../utils/find.ts' -import permissions from '../utils/permissions.ts' +import getApiDoc from '../misc/utils/api-docs.ts' +import findUtils from '../misc/utils/find.ts' +import permissions from '../misc/utils/permissions.ts' const router = Router() export default router diff --git a/api/src/routers/runs.ts b/api/src/runs/router.ts similarity index 96% rename from api/src/routers/runs.ts rename to api/src/runs/router.ts index 4dcbbb4f..3120e38b 100644 --- a/api/src/routers/runs.ts +++ b/api/src/runs/router.ts @@ -5,8 +5,8 @@ import * as wsEmitter from '@data-fair/lib-node/ws-emitter.js' import { session } from '@data-fair/lib-express/index.js' import { Router } from 'express' import mongo from '#mongo' -import findUtils from '../utils/find.ts' -import permissions from '../utils/permissions.ts' +import findUtils from '../misc/utils/find.ts' +import permissions from '../misc/utils/permissions.ts' const router = Router() export default router diff --git a/api/src/utils/runs.ts b/api/src/runs/service.ts similarity index 100% rename from api/src/utils/runs.ts rename to api/src/runs/service.ts diff --git a/api/src/server.ts b/api/src/server.ts index 9726d97f..f2ab198f 100644 --- a/api/src/server.ts +++ b/api/src/server.ts @@ -13,7 +13,7 @@ import config from '#config' import mongo from '#mongo' import locks from '#locks' import http from 'http' -import permissions from './utils/permissions.ts' +import permissions from './misc/utils/permissions.ts' const exec = promisify(execCallback) const server = http.createServer(app) diff --git a/dev/resources/nginx.conf b/dev/resources/nginx.conf index 47881c69..e53f3211 100644 --- a/dev/resources/nginx.conf +++ b/dev/resources/nginx.conf @@ -98,11 +98,11 @@ http { } location /openapi-viewer { - proxy_pass http://localhost:8083; + proxy_pass http://localhost:8084; } location /events/ { - proxy_pass http://localhost:8084; + proxy_pass http://localhost:8083; } } } diff --git a/docker-compose.yml b/docker-compose.yml index f0a26534..d138fca4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -17,7 +17,7 @@ services: profiles: - dev - test - image: ghcr.io/data-fair/simple-directory:master + image: ghcr.io/data-fair/simple-directory:8 network_mode: host depends_on: - mongo @@ -52,27 +52,23 @@ services: condition: service_healthy environment: - PORT=8081 - - DEBUG=files - MONGO_URL=mongodb://localhost:27017/data-fair - - OPENAPI_VIEWER_URL=http://localhost:5600/openapi-viewer/ - DIRECTORY_URL=http://localhost:5600/simple-directory - - NOTIFY_URL=http://localhost:5600/events + - PRIVATE_EVENTS_URL=http://localhost:8083 + - PRIVATE_DIRECTORY_URL=http://localhost:8080 - PUBLIC_URL=http://localhost:5600/data-fair - WS_PUBLIC_URL=ws://localhost:5600/data-fair - - EXTRA_NAV_ITEMS=[{"id":"events","can":"admin","iframe":"http://localhost:5600/events/embed/events","basePath":"/events","icon":"mdi-clipboard-text-clock","title":"Traçabilité"}, {"id":"processings","can":"contrib","iframe":"http://localhost:5600/processings/processings","basePath":"/processings","icon":"mdi-cog-transfer-outline","title":"Traitements périodiques"}] - - EXTRA_ADMIN_NAV_ITEMS=[{"id":"processings","iframe":"http://localhost:5600/processings/admin","basePath":"/processings","icon":"mdi-cog-transfer-outline","title":"Plugins - Traitements"},{"id":"processingsAdminDoc","href":"http://localhost:5600/openapi-viewer?urlType=processingsAdmin","icon":"mdi-cog-transfer-outline","title":"API Traitements périodiques"}] - OBSERVER_ACTIVE=false + + - PRIVATE_PROCESSINGS_URL=http://localhost:8082 + - SECRET_EVENTS=secret-events + - EXTRA_ADMIN_NAV_ITEMS=[{"id":"processingsAdminDoc","href":"http://localhost:5600/openapi-viewer?urlType=processingsAdmin","icon":"mdi-cog-transfer-outline","title":"API Traitements périodiques"}] + - OPENAPI_VIEWER_URL=http://localhost:5600/openapi-viewer/ - OPENAPI_VIEWER_V2=true - openapi-viewer: - profiles: - - dev - image: ghcr.io/data-fair/openapi-viewer:master - ports: - - 8083:8080 - environment: - - USE_SIMPLE_DIRECTORY=true - - ALLOWED_URLS={"processings":"http://localhost:5600/processings/api/v1/api-docs.json","processingsId":"http://localhost:5600/processings/api/v1/processings/{id}/api-docs.json","processingsAdmin":"http://localhost:5600/processings/api/v1/admin/api-docs.json"} + ##### + # optional services + ##### events: profiles: @@ -80,13 +76,23 @@ services: image: ghcr.io/data-fair/events:main network_mode: host environment: - - PORT=8084 + - PORT=8083 + - MONGO_URL=mongodb://localhost:27017/data-fair-events - PRIVATE_DIRECTORY_URL=http://localhost:5600/simple-directory - SECRET_IDENTITIES=secret-identities - SECRET_EVENTS=secret-events - SECRET_SENDMAILS=secret-sendmails - OBSERVER_ACTIVE=false + openapi-viewer: + profiles: + - dev + image: ghcr.io/data-fair/openapi-viewer:master + environment: + - PORT=8084 + - USE_SIMPLE_DIRECTORY=true + - ALLOWED_URLS={"processings":"http://localhost:5600/processings/api/v1/api-docs.json","processingsId":"http://localhost:5600/processings/api/v1/processings/{id}/api-docs.json","processingsAdmin":"http://localhost:5600/processings/api/v1/admin/api-docs.json"} + ##### # db and search engine ##### diff --git a/package-lock.json b/package-lock.json index 4f5b45a2..8b23d640 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,9 +25,10 @@ "@data-fair/lib-utils": "^1.6.1", "@types/config": "^3.3.5", "@types/debug": "^4.1.12", + "@types/semver": "^7.7.1", "eslint": "^9.29.0", "eslint-plugin-vue": "^10.2.0", - "eslint-plugin-vuetify": "github:albanm/eslint-plugin-vuetify", + "eslint-plugin-vuetify": "^2.5.3", "husky": "^9.1.6", "neostandard": "^0.12.1", "tough-cookie": "^5.0.0", @@ -52,7 +53,7 @@ "multer": "^2.0.1", "nanoid": "^5.0.8", "resolve-path": "^1.4.0", - "semver": "^7.6.3", + "semver": "^7.7.4", "tmp-promise": "^3.0.3", "ws": "^8.18.0" }, @@ -61,7 +62,6 @@ "@types/memoizee": "^0.4.11", "@types/multer": "^1.4.13", "@types/resolve-path": "^1.4.3", - "@types/semver": "^7.5.8", "@types/ws": "^8.5.12" } }, @@ -581,9 +581,9 @@ } }, "node_modules/@data-fair/lib-vuetify": { - "version": "1.12.4", - "resolved": "https://registry.npmjs.org/@data-fair/lib-vuetify/-/lib-vuetify-1.12.4.tgz", - "integrity": "sha512-IjO5f7nqujEBC4m9DgaRnKTF9B35Wgtw7wbbKbq/fp+qKk7rKq9h79tEAzF3smA6TRRujmSMB1+P1otJgWDcRg==", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/@data-fair/lib-vuetify/-/lib-vuetify-1.13.1.tgz", + "integrity": "sha512-Cv6Vr6XJPn7vate+YZx//sh8YT1quMbtliNhV1Eh1jAo4Rb6BU98hJRBD2xIseGCtvsNuCfqw7f5LWA1o8fN/A==", "license": "MIT", "dependencies": { "@data-fair/lib-common-types": "^1.10.4", @@ -2262,10 +2262,9 @@ "license": "MIT" }, "node_modules/@types/semver": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.0.tgz", - "integrity": "sha512-k107IF4+Xr7UHjwDc7Cfd6PRQfbdkiRabXGRjo07b4WyPahFBZCZ1sE+BNxYIJPPg73UkfOsVOLwqVc/6ETrIA==", - "dev": true, + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==", "license": "MIT" }, "node_modules/@types/send": { @@ -5084,131 +5083,20 @@ } }, "node_modules/eslint-plugin-vuetify": { - "version": "2.4.0", - "resolved": "git+ssh://git@github.com/albanm/eslint-plugin-vuetify.git#e25c604300a03f8b852593c71a5ce9f4d25c2acd", + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-vuetify/-/eslint-plugin-vuetify-2.5.3.tgz", + "integrity": "sha512-HQQ3HSeg4lOQp+bImVuGsIQBgRexMGudZBZ8iK7ypQsNkKlVu2JSDDslOoTUGTj+QY/SE5PtXOwz0lMITuv8Rg==", "dev": true, "license": "MIT", "dependencies": { - "eslint-plugin-vue": "^9.6.0", + "eslint-plugin-vue": ">=9.6.0", "requireindex": "^1.2.0" }, "peerDependencies": { - "eslint": "^9.0.0", + "eslint": "^8.0.0 || ^9.0.0", "vuetify": "^3.0.0" } }, - "node_modules/eslint-plugin-vuetify/node_modules/eslint-plugin-vue": { - "version": "9.33.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.33.0.tgz", - "integrity": "sha512-174lJKuNsuDIlLpjeXc5E2Tss8P44uIimAfGD0b90k0NoirJqpG7stLuU9Vp/9ioTOrQdWVREc4mRd1BD+CvGw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "globals": "^13.24.0", - "natural-compare": "^1.4.0", - "nth-check": "^2.1.1", - "postcss-selector-parser": "^6.0.15", - "semver": "^7.6.3", - "vue-eslint-parser": "^9.4.3", - "xml-name-validator": "^4.0.0" - }, - "engines": { - "node": "^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0 || ^9.0.0" - } - }, - "node_modules/eslint-plugin-vuetify/node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-plugin-vuetify/node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-plugin-vuetify/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint-plugin-vuetify/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint-plugin-vuetify/node_modules/vue-eslint-parser": { - "version": "9.4.3", - "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.3.tgz", - "integrity": "sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.3.4", - "eslint-scope": "^7.1.1", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.1", - "esquery": "^1.4.0", - "lodash": "^4.17.21", - "semver": "^7.3.6" - }, - "engines": { - "node": "^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=6.0.0" - } - }, "node_modules/eslint-scope": { "version": "8.4.0", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", @@ -7216,9 +7104,9 @@ } }, "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", "license": "MIT" }, "node_modules/lodash.camelcase": { @@ -9332,9 +9220,9 @@ "license": "MIT" }, "node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -11283,19 +11171,21 @@ "@data-fair/frame": "^0.14.0", "@data-fair/lib-utils": "^1.6.1", "@data-fair/lib-vue": "^1.21.1", - "@data-fair/lib-vuetify": "^1.10.1", + "@data-fair/lib-vuetify": "^1.13.0", "@data-fair/processings-shared": "*", "@intlify/unplugin-vue-i18n": "^6.0.8", "@koumoul/v-iframe": "^2.4.5", "@koumoul/vjsf": "^3.20.4", "@mdi/js": "^7.4.47", "@types/config": "^3.3.5", + "@types/semver": "^7.7.1", "@vitejs/plugin-vue": "^5.1.4", "@vueuse/core": "^11.2.0", "cronstrue": "^3.2.0", "iframe-resizer": "^4.4.5", "reconnecting-websocket": "^4.4.0", "sass-embedded": "^1.80.5", + "semver": "^7.7.4", "timezones.json": "^1.7.1", "unplugin-auto-import": "^0.18.3", "unplugin-fonts": "^1.1.1", diff --git a/package.json b/package.json index 7eef919b..4f34f18d 100644 --- a/package.json +++ b/package.json @@ -49,9 +49,10 @@ "@data-fair/lib-utils": "^1.6.1", "@types/config": "^3.3.5", "@types/debug": "^4.1.12", + "@types/semver": "^7.7.1", "eslint": "^9.29.0", "eslint-plugin-vue": "^10.2.0", - "eslint-plugin-vuetify": "github:albanm/eslint-plugin-vuetify", + "eslint-plugin-vuetify": "^2.5.3", "husky": "^9.1.6", "neostandard": "^0.12.1", "tough-cookie": "^5.0.0", diff --git a/scripts/re-schedule-all.ts b/scripts/re-schedule-all.ts index e038eb02..a8c2af12 100644 --- a/scripts/re-schedule-all.ts +++ b/scripts/re-schedule-all.ts @@ -1,4 +1,4 @@ -import runs from '../api/src/utils/runs.ts' +import runs from '../api/src/runs/service.ts' async function main () { const { db } = await require('../api/utils/db').connect() diff --git a/ui/.gitignore b/ui/.gitignore index b6cdf575..55e510f1 100644 --- a/ui/.gitignore +++ b/ui/.gitignore @@ -12,6 +12,7 @@ dist dist-ssr *.local *.tsbuildinfo +dts # Editor directories and files .vscode/* diff --git a/ui/dts/auto-imports.d.ts b/ui/dts/auto-imports.d.ts deleted file mode 100644 index fc4303ad..00000000 --- a/ui/dts/auto-imports.d.ts +++ /dev/null @@ -1,272 +0,0 @@ -/* eslint-disable */ -/* prettier-ignore */ -// @ts-nocheck -// noinspection JSUnusedGlobalSymbols -// Generated by unplugin-auto-import -// biome-ignore lint: disable -export {} -declare global { - const $apiPath: typeof import('~/context')['$apiPath'] - const $cspNonce: typeof import('~/context')['$cspNonce'] - const $fetch: typeof import('~/context')['$fetch'] - const $sitePath: typeof import('~/context')['$sitePath'] - const $uiConfig: typeof import('~/context')['$uiConfig'] - const EffectScope: typeof import('vue')['EffectScope'] - const breadcrumbs: typeof import('../src/utils/breadcrumbs')['default'] - const computed: typeof import('vue')['computed'] - const computedDeepDiff: typeof import('@data-fair/lib-vue/deep-diff.js')['computedDeepDiff'] - const createApp: typeof import('vue')['createApp'] - const customRef: typeof import('vue')['customRef'] - const defineAsyncComponent: typeof import('vue')['defineAsyncComponent'] - const defineComponent: typeof import('vue')['defineComponent'] - const dfDateMatchFilter: typeof import('@data-fair/lib-vuetify/date-match-filter.vue')['default'] - const dfDateRangePicker: typeof import('@data-fair/lib-vuetify/date-range-picker.vue')['default'] - const dfLangSwitcher: typeof import('@data-fair/lib-vuetify/lang-switcher.vue')['default'] - const dfNavigationRight: typeof import('@data-fair/lib-vuetify/navigation-right.vue')['default'] - const dfOwnerAvatar: typeof import('@data-fair/lib-vuetify/owner-avatar.vue')['default'] - const dfOwnerPick: typeof import('@data-fair/lib-vuetify/owner-pick.vue')['default'] - const dfPersonalMenu: typeof import('@data-fair/lib-vuetify/personal-menu.vue')['default'] - const dfThemeSwitcher: typeof import('@data-fair/lib-vuetify/theme-switcher.vue')['default'] - const dfTutorialAlert: typeof import('@data-fair/lib-vuetify/tutorial-alert.vue')['default'] - const dfUiNotif: typeof import('@data-fair/lib-vuetify/ui-notif.vue')['default'] - const dfUiNotifAlert: typeof import('@data-fair/lib-vuetify/ui-notif-alert.vue')['default'] - const dfUserAvatar: typeof import('@data-fair/lib-vuetify/ui-user-avatar.vue')['default'] - const effectScope: typeof import('vue')['effectScope'] - const getCurrentInstance: typeof import('vue')['getCurrentInstance'] - const getCurrentScope: typeof import('vue')['getCurrentScope'] - const h: typeof import('vue')['h'] - const inject: typeof import('vue')['inject'] - const isProxy: typeof import('vue')['isProxy'] - const isReactive: typeof import('vue')['isReactive'] - const isReadonly: typeof import('vue')['isReadonly'] - const isRef: typeof import('vue')['isRef'] - const markRaw: typeof import('vue')['markRaw'] - const mdiAccount: typeof import('@mdi/js')['mdiAccount'] - const mdiAlert: typeof import('@mdi/js')['mdiAlert'] - const mdiAlertCircle: typeof import('@mdi/js')['mdiAlertCircle'] - const mdiBell: typeof import('@mdi/js')['mdiBell'] - const mdiBookOpenVariant: typeof import('@mdi/js')['mdiBookOpenVariant'] - const mdiCheckCircle: typeof import('@mdi/js')['mdiCheckCircle'] - const mdiClock: typeof import('@mdi/js')['mdiClock'] - const mdiCloud: typeof import('@mdi/js')['mdiCloud'] - const mdiContentDuplicate: typeof import('@mdi/js')['mdiContentDuplicate'] - const mdiDatabase: typeof import('@mdi/js')['mdiDatabase'] - const mdiDelete: typeof import('@mdi/js')['mdiDelete'] - const mdiDotsVertical: typeof import('@mdi/js')['mdiDotsVertical'] - const mdiDownload: typeof import('@mdi/js')['mdiDownload'] - const mdiInformation: typeof import('@mdi/js')['mdiInformation'] - const mdiMagnify: typeof import('@mdi/js')['mdiMagnify'] - const mdiOpenInNew: typeof import('@mdi/js')['mdiOpenInNew'] - const mdiPencil: typeof import('@mdi/js')['mdiPencil'] - const mdiPlay: typeof import('@mdi/js')['mdiPlay'] - const mdiPlayCircle: typeof import('@mdi/js')['mdiPlayCircle'] - const mdiPlug: typeof import('@mdi/js')['mdiPlug'] - const mdiPlusCircle: typeof import('@mdi/js')['mdiPlusCircle'] - const mdiPlusCircleOutline: typeof import('@mdi/js')['mdiPlusCircleOutline'] - const mdiPowerPlug: typeof import('@mdi/js')['mdiPowerPlug'] - const mdiStop: typeof import('@mdi/js')['mdiStop'] - const mdiToggleSwitch: typeof import('@mdi/js')['mdiToggleSwitch'] - const mdiToggleSwitchOff: typeof import('@mdi/js')['mdiToggleSwitchOff'] - const mdiUpdate: typeof import('@mdi/js')['mdiUpdate'] - const nextTick: typeof import('vue')['nextTick'] - const onActivated: typeof import('vue')['onActivated'] - const onBeforeMount: typeof import('vue')['onBeforeMount'] - const onBeforeRouteLeave: typeof import('vue-router')['onBeforeRouteLeave'] - const onBeforeRouteUpdate: typeof import('vue-router')['onBeforeRouteUpdate'] - const onBeforeUnmount: typeof import('vue')['onBeforeUnmount'] - const onBeforeUpdate: typeof import('vue')['onBeforeUpdate'] - const onDeactivated: typeof import('vue')['onDeactivated'] - const onErrorCaptured: typeof import('vue')['onErrorCaptured'] - const onMounted: typeof import('vue')['onMounted'] - const onRenderTracked: typeof import('vue')['onRenderTracked'] - const onRenderTriggered: typeof import('vue')['onRenderTriggered'] - const onScopeDispose: typeof import('vue')['onScopeDispose'] - const onServerPrefetch: typeof import('vue')['onServerPrefetch'] - const onUnmounted: typeof import('vue')['onUnmounted'] - const onUpdated: typeof import('vue')['onUpdated'] - const onWatcherCleanup: typeof import('vue')['onWatcherCleanup'] - const provide: typeof import('vue')['provide'] - const reactive: typeof import('vue')['reactive'] - const readonly: typeof import('vue')['readonly'] - const ref: typeof import('vue')['ref'] - const resolveComponent: typeof import('vue')['resolveComponent'] - const setBreadcrumbs: typeof import('../src/utils/breadcrumbs')['setBreadcrumbs'] - const shallowReactive: typeof import('vue')['shallowReactive'] - const shallowReadonly: typeof import('vue')['shallowReadonly'] - const shallowRef: typeof import('vue')['shallowRef'] - const toRaw: typeof import('vue')['toRaw'] - const toRef: typeof import('vue')['toRef'] - const toRefs: typeof import('vue')['toRefs'] - const toValue: typeof import('vue')['toValue'] - const triggerRef: typeof import('vue')['triggerRef'] - const unref: typeof import('vue')['unref'] - const useAsyncAction: typeof import('@data-fair/lib-vue/async-action.js')['useAsyncAction'] - const useAttrs: typeof import('vue')['useAttrs'] - const useBooleanSearchParam: typeof import('@data-fair/lib-vue/reactive-search-params.js')['useBooleanSearchParam'] - const useConceptFilters: typeof import('@data-fair/lib-vue/concept-filters.js')['useConceptFilters'] - const useCssModule: typeof import('vue')['useCssModule'] - const useCssVars: typeof import('vue')['useCssVars'] - const useFetch: typeof import('@data-fair/lib-vue/fetch.js')['useFetch'] - const useI18n: typeof import('vue-i18n')['useI18n'] - const useId: typeof import('vue')['useId'] - const useLink: typeof import('vue-router')['useLink'] - const useLocaleDayjs: typeof import('@data-fair/lib-vue/locale-dayjs.js')['useLocaleDayjs'] - const useModel: typeof import('vue')['useModel'] - const useNumberSearchParam: typeof import('@data-fair/lib-vue/reactive-search-params.js')['useNumberSearchParam'] - const usePluginFetch: typeof import('../src/composables/use-plugin-fetch')['default'] - const useReactiveSearchParams: typeof import('@data-fair/lib-vue/reactive-search-params.js')['useReactiveSearchParams'] - const useRoute: typeof import('vue-router')['useRoute'] - const useRouter: typeof import('vue-router')['useRouter'] - const useSession: typeof import('@data-fair/lib-vue/session.js')['useSession'] - const useSessionAuthenticated: typeof import('@data-fair/lib-vue/session.js')['useSessionAuthenticated'] - const useSlots: typeof import('vue')['useSlots'] - const useStringSearchParam: typeof import('@data-fair/lib-vue/reactive-search-params.js')['useStringSearchParam'] - const useStringsArraySearchParam: typeof import('@data-fair/lib-vue/reactive-search-params.js')['useStringsArraySearchParam'] - const useTemplateRef: typeof import('vue')['useTemplateRef'] - const useUiNotif: typeof import('@data-fair/lib-vue/ui-notif.js')['useUiNotif'] - const useWS: typeof import('@data-fair/lib-vue/ws.js')['useWS'] - const watch: typeof import('vue')['watch'] - const watchDeepDiff: typeof import('@data-fair/lib-vue/deep-diff.js')['watchDeepDiff'] - const watchEffect: typeof import('vue')['watchEffect'] - const watchPostEffect: typeof import('vue')['watchPostEffect'] - const watchSyncEffect: typeof import('vue')['watchSyncEffect'] - const withUiNotif: typeof import('@data-fair/lib-vue/ui-notif.js')['withUiNotif'] -} -// for type re-export -declare global { - // @ts-ignore - export type { Component, ComponentPublicInstance, ComputedRef, DirectiveBinding, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, MaybeRef, MaybeRefOrGetter, VNode, WritableComputedRef } from 'vue' - import('vue') -} - -// for vue template auto import -import { UnwrapRef } from 'vue' -declare module 'vue' { - interface GlobalComponents {} - interface ComponentCustomProperties { - readonly $apiPath: UnwrapRef - readonly $cspNonce: UnwrapRef - readonly $fetch: UnwrapRef - readonly $sitePath: UnwrapRef - readonly $uiConfig: UnwrapRef - readonly EffectScope: UnwrapRef - readonly breadcrumbs: UnwrapRef - readonly computed: UnwrapRef - readonly computedDeepDiff: UnwrapRef - readonly createApp: UnwrapRef - readonly customRef: UnwrapRef - readonly defineAsyncComponent: UnwrapRef - readonly defineComponent: UnwrapRef - readonly dfDateMatchFilter: UnwrapRef - readonly dfDateRangePicker: UnwrapRef - readonly dfLangSwitcher: UnwrapRef - readonly dfNavigationRight: UnwrapRef - readonly dfOwnerAvatar: UnwrapRef - readonly dfOwnerPick: UnwrapRef - readonly dfPersonalMenu: UnwrapRef - readonly dfThemeSwitcher: UnwrapRef - readonly dfTutorialAlert: UnwrapRef - readonly dfUiNotif: UnwrapRef - readonly dfUiNotifAlert: UnwrapRef - readonly dfUserAvatar: UnwrapRef - readonly effectScope: UnwrapRef - readonly getCurrentInstance: UnwrapRef - readonly getCurrentScope: UnwrapRef - readonly h: UnwrapRef - readonly inject: UnwrapRef - readonly isProxy: UnwrapRef - readonly isReactive: UnwrapRef - readonly isReadonly: UnwrapRef - readonly isRef: UnwrapRef - readonly markRaw: UnwrapRef - readonly mdiAccount: UnwrapRef - readonly mdiAlert: UnwrapRef - readonly mdiAlertCircle: UnwrapRef - readonly mdiBell: UnwrapRef - readonly mdiBookOpenVariant: UnwrapRef - readonly mdiCheckCircle: UnwrapRef - readonly mdiClock: UnwrapRef - readonly mdiCloud: UnwrapRef - readonly mdiContentDuplicate: UnwrapRef - readonly mdiDatabase: UnwrapRef - readonly mdiDelete: UnwrapRef - readonly mdiDotsVertical: UnwrapRef - readonly mdiDownload: UnwrapRef - readonly mdiInformation: UnwrapRef - readonly mdiMagnify: UnwrapRef - readonly mdiOpenInNew: UnwrapRef - readonly mdiPencil: UnwrapRef - readonly mdiPlay: UnwrapRef - readonly mdiPlayCircle: UnwrapRef - readonly mdiPlusCircle: UnwrapRef - readonly mdiPlusCircleOutline: UnwrapRef - readonly mdiPowerPlug: UnwrapRef - readonly mdiStop: UnwrapRef - readonly mdiToggleSwitch: UnwrapRef - readonly mdiToggleSwitchOff: UnwrapRef - readonly mdiUpdate: UnwrapRef - readonly nextTick: UnwrapRef - readonly onActivated: UnwrapRef - readonly onBeforeMount: UnwrapRef - readonly onBeforeRouteLeave: UnwrapRef - readonly onBeforeRouteUpdate: UnwrapRef - readonly onBeforeUnmount: UnwrapRef - readonly onBeforeUpdate: UnwrapRef - readonly onDeactivated: UnwrapRef - readonly onErrorCaptured: UnwrapRef - readonly onMounted: UnwrapRef - readonly onRenderTracked: UnwrapRef - readonly onRenderTriggered: UnwrapRef - readonly onScopeDispose: UnwrapRef - readonly onServerPrefetch: UnwrapRef - readonly onUnmounted: UnwrapRef - readonly onUpdated: UnwrapRef - readonly onWatcherCleanup: UnwrapRef - readonly provide: UnwrapRef - readonly reactive: UnwrapRef - readonly readonly: UnwrapRef - readonly ref: UnwrapRef - readonly resolveComponent: UnwrapRef - readonly setBreadcrumbs: UnwrapRef - readonly shallowReactive: UnwrapRef - readonly shallowReadonly: UnwrapRef - readonly shallowRef: UnwrapRef - readonly toRaw: UnwrapRef - readonly toRef: UnwrapRef - readonly toRefs: UnwrapRef - readonly toValue: UnwrapRef - readonly triggerRef: UnwrapRef - readonly unref: UnwrapRef - readonly useAsyncAction: UnwrapRef - readonly useAttrs: UnwrapRef - readonly useBooleanSearchParam: UnwrapRef - readonly useConceptFilters: UnwrapRef - readonly useCssModule: UnwrapRef - readonly useCssVars: UnwrapRef - readonly useFetch: UnwrapRef - readonly useI18n: UnwrapRef - readonly useId: UnwrapRef - readonly useLink: UnwrapRef - readonly useLocaleDayjs: UnwrapRef - readonly useModel: UnwrapRef - readonly useNumberSearchParam: UnwrapRef - readonly usePluginFetch: UnwrapRef - readonly useReactiveSearchParams: UnwrapRef - readonly useRoute: UnwrapRef - readonly useRouter: UnwrapRef - readonly useSession: UnwrapRef - readonly useSessionAuthenticated: UnwrapRef - readonly useSlots: UnwrapRef - readonly useStringSearchParam: UnwrapRef - readonly useStringsArraySearchParam: UnwrapRef - readonly useTemplateRef: UnwrapRef - readonly useUiNotif: UnwrapRef - readonly useWS: UnwrapRef - readonly watch: UnwrapRef - readonly watchDeepDiff: UnwrapRef - readonly watchEffect: UnwrapRef - readonly watchPostEffect: UnwrapRef - readonly watchSyncEffect: UnwrapRef - readonly withUiNotif: UnwrapRef - } -} \ No newline at end of file diff --git a/ui/dts/components.d.ts b/ui/dts/components.d.ts deleted file mode 100644 index f7a02057..00000000 --- a/ui/dts/components.d.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* eslint-disable */ -// @ts-nocheck -// Generated by unplugin-vue-components -// Read more: https://github.com/vuejs/core/pull/3399 -export {} - -/* prettier-ignore */ -declare module 'vue' { - export interface GlobalComponents { - LayoutActions: typeof import('./../src/components/layout/layout-actions.vue')['default'] - LayoutActionsButton: typeof import('./../src/components/layout/layout-actions-button.vue')['default'] - LayoutActionsRight: typeof import('./../src/components/layout/layout-actions-right.vue')['default'] - PrivateAccess: typeof import('./../src/components/private-access.vue')['default'] - ProcessingActions: typeof import('./../src/components/processing/processing-actions.vue')['default'] - ProcessingActivity: typeof import('./../src/components/processing/processing-activity.vue')['default'] - ProcessingCard: typeof import('./../src/components/processing/processing-card.vue')['default'] - ProcessingRuns: typeof import('./../src/components/processing/processing-runs.vue')['default'] - ProcessingsActions: typeof import('./../src/components/processings-actions.vue')['default'] - RouterLink: typeof import('vue-router')['RouterLink'] - RouterView: typeof import('vue-router')['RouterView'] - RunListItem: typeof import('./../src/components/run/run-list-item.vue')['default'] - RunLogsList: typeof import('./../src/components/run/run-logs-list.vue')['default'] - } -} diff --git a/ui/dts/typed-router.d.ts b/ui/dts/typed-router.d.ts deleted file mode 100644 index 0201f23b..00000000 --- a/ui/dts/typed-router.d.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* eslint-disable */ -/* prettier-ignore */ -// @ts-nocheck -// Generated by unplugin-vue-router. ‼️ DO NOT MODIFY THIS FILE ‼️ -// It's recommended to commit this file. -// Make sure to add this file to your tsconfig.json file as an "includes" or "files" entry. - -declare module 'vue-router/auto-routes' { - import type { - RouteRecordInfo, - ParamValue, - ParamValueOneOrMore, - ParamValueZeroOrMore, - ParamValueZeroOrOne, - } from 'vue-router' - - /** - * Route name map generated by unplugin-vue-router - */ - export interface RouteNamedMap { - '/admin/': RouteRecordInfo<'/admin/', '/admin', Record, Record>, - '/admin/plugins': RouteRecordInfo<'/admin/plugins', '/admin/plugins', Record, Record>, - '/processings/': RouteRecordInfo<'/processings/', '/processings', Record, Record>, - '/processings/[id]/': RouteRecordInfo<'/processings/[id]/', '/processings/:id', { id: ParamValue }, { id: ParamValue }>, - '/processings/[id]/runs/[runId]': RouteRecordInfo<'/processings/[id]/runs/[runId]', '/processings/:id/runs/:runId', { id: ParamValue, runId: ParamValue }, { id: ParamValue, runId: ParamValue }>, - '/processings/new': RouteRecordInfo<'/processings/new', '/processings/new', Record, Record>, - } -} diff --git a/ui/eslint.config.mjs b/ui/eslint.config.mjs index 04edcabe..e408dc5d 100644 --- a/ui/eslint.config.mjs +++ b/ui/eslint.config.mjs @@ -1,33 +1,25 @@ import neostandard from 'neostandard' import pluginVue from 'eslint-plugin-vue' +import pluginVuetify from 'eslint-plugin-vuetify' import dfLibRecommended from '@data-fair/lib-utils/eslint/recommended.js' -// cf https://github.com/vuetifyjs/eslint-plugin-vuetify/pull/98 -// @ts-ignore -import vuetify from 'eslint-plugin-vuetify/src/index.js' export default [ ...dfLibRecommended, ...pluginVue.configs['flat/recommended'], - { - rules: { - 'vue/multi-word-component-names': 'off' - } - }, + ...pluginVuetify.configs['flat/recommended'], { files: ['**/*.vue'], languageOptions: { parserOptions: { parser: '@typescript-eslint/parser' } - }, - plugins: { vuetify }, - rules: { - ...vuetify.configs.base.rules } }, ...neostandard({ ts: true }), { rules: { + 'vue/require-default-prop': 'off', + 'vue/multi-word-component-names': 'off', 'no-undef': 'off' // typescript takes care of this with autoImport support } }, diff --git a/ui/package.json b/ui/package.json index 009729e9..967c6374 100644 --- a/ui/package.json +++ b/ui/package.json @@ -3,12 +3,12 @@ "private": true, "type": "module", "scripts": { - "dev": "NODE_CONFIG_DIR=../api/config/ vite --port 3039", - "build": "vue-tsc -b && vite build", - "preview": "vite preview", + "build": "vite build", "check-types": "vue-tsc", + "dev": "NODE_CONFIG_DIR=../api/config/ vite --port 3039", "lint": "eslint .", - "lint-fix": "eslint --fix ." + "lint-fix": "eslint --fix .", + "preview": "vite preview" }, "imports": { "#api/doc": "../api/doc/index.ts", @@ -19,19 +19,21 @@ "@data-fair/frame": "^0.14.0", "@data-fair/lib-utils": "^1.6.1", "@data-fair/lib-vue": "^1.21.1", - "@data-fair/lib-vuetify": "^1.10.1", + "@data-fair/lib-vuetify": "^1.13.0", "@data-fair/processings-shared": "*", "@intlify/unplugin-vue-i18n": "^6.0.8", "@koumoul/v-iframe": "^2.4.5", "@koumoul/vjsf": "^3.20.4", "@mdi/js": "^7.4.47", "@types/config": "^3.3.5", + "@types/semver": "^7.7.1", "@vitejs/plugin-vue": "^5.1.4", "@vueuse/core": "^11.2.0", "cronstrue": "^3.2.0", "iframe-resizer": "^4.4.5", "reconnecting-websocket": "^4.4.0", "sass-embedded": "^1.80.5", + "semver": "^7.7.4", "timezones.json": "^1.7.1", "unplugin-auto-import": "^0.18.3", "unplugin-fonts": "^1.1.1", diff --git a/ui/src/components/layout/layout-actions-button.vue b/ui/src/components/layout/layout-actions-button.vue deleted file mode 100644 index 7641698d..00000000 --- a/ui/src/components/layout/layout-actions-button.vue +++ /dev/null @@ -1,21 +0,0 @@ - diff --git a/ui/src/components/layout/layout-actions-right.vue b/ui/src/components/layout/layout-actions-right.vue deleted file mode 100644 index 85d2f5b0..00000000 --- a/ui/src/components/layout/layout-actions-right.vue +++ /dev/null @@ -1,13 +0,0 @@ - diff --git a/ui/src/components/layout/layout-actions.vue b/ui/src/components/layout/layout-actions.vue deleted file mode 100644 index f2afab33..00000000 --- a/ui/src/components/layout/layout-actions.vue +++ /dev/null @@ -1,8 +0,0 @@ - diff --git a/ui/src/components/private-access.vue b/ui/src/components/private-access.vue index aaf18b9b..f737225a 100644 --- a/ui/src/components/private-access.vue +++ b/ui/src/components/private-access.vue @@ -103,6 +103,3 @@ function onChange () { loading.value = false } - - diff --git a/ui/src/components/processing/processing-actions.vue b/ui/src/components/processing/processing-actions.vue index 3ce6aead..3666a949 100644 --- a/ui/src/components/processing/processing-actions.vue +++ b/ui/src/components/processing/processing-actions.vue @@ -1,329 +1,322 @@ - + - - + Déclencher manuellement + + + + + + + + + Dupliquer + + + - - + + + + + + + + - - + + Oui + + + + + + + + + Changer le propriétaire + + + - - - + - - - - - - - - Annuler - - - Confirmer - - - - + variant="flat" + :disabled="!ownersReady" + :loading="confirmChangeOwner.loading.value" + @click="confirmChangeOwner.execute()" + > + Confirmer + + + + - - - Voir le jeu de données - + + + + Voir le jeu de données + - - - Tutoriel - + + + + Tutoriel + - - - Utiliser l'API - + + + + Utiliser l'API + - - - + + + + + + + + - - diff --git a/ui/src/components/processing/processing-card.vue b/ui/src/components/processing/processing-card.vue index 900e722f..980572da 100644 --- a/ui/src/components/processing/processing-card.vue +++ b/ui/src/components/processing/processing-card.vue @@ -6,16 +6,12 @@ @@ -56,9 +52,7 @@ - - {{ pluginFetch.data.value?.metadata.name }} - + {{ pluginFetch.data.value?.metadata.name }} diff --git a/ui/src/components/processing/processing-runs.vue b/ui/src/components/processing/processing-runs.vue index f0df5076..122f79f6 100644 --- a/ui/src/components/processing/processing-runs.vue +++ b/ui/src/components/processing/processing-runs.vue @@ -85,6 +85,3 @@ onUnmounted(() => { defineExpose({ refresh: () => runs.refresh() }) - - diff --git a/ui/src/components/processings-actions.vue b/ui/src/components/processings-actions.vue index aa95908a..30ef10ea 100644 --- a/ui/src/components/processings-actions.vue +++ b/ui/src/components/processings-actions.vue @@ -1,135 +1,128 @@ - + Créer un nouveau traitement + + + + + + + + + + + + + + + + + + + + + + + + + + - + +fr: + adminRequired: Vous n'avez pas la permission d'accéder à cette page, il faut avoir activé le mode super-administration. + authRequired: Authentification nécessaire + availablePluginsLabel: plugins disponibles + cancel: Annuler + install: Installer + installError: Erreur lors de l'installation du plugin + installSeparately: Installer séparément + installSuccess: Plugin installé ! + installedPluginsLabel: plugins installés + majorUpdateBody: Mettre à jour vers une nouvelle version majeure risque d'entraîner une rupture de compatibilité. Vous pouvez choisir de confirmer la montée en version, ou préférer l'installation de la nouvelle version séparée. + majorUpdateTitleWithVersions: "Mise à jour majeure - {from} vers {to}" + manualInstall: Installer manuellement + manualInstallDistTag: Tag de distribution + manualInstallFileLabel: Sélectionner un fichier .tgz + manualInstallFromFile: Installer depuis un fichier + manualInstallFromNpm: Installer depuis npm + manualInstallName: Nom du plugin + manualInstallTitle: Installation manuelle d'un plugin + manualInstallVersion: Version du plugin + no: Non + pluginsBreadcrumb: Plugins + searchPlaceholder: rechercher + showAllLabel: Afficher les versions de test des plugins + uninstall: Désinstaller + uninstallConfirm: Voulez-vous vraiment désinstaller le plugin "{name}" ? + uninstallError: Erreur lors de la désinstallation du plugin + uninstallSuccess: Plugin désinstallé ! + uninstallTitle: Désinstallation du plugin + update: Mettre à jour + updateWithVersion: Mettre à jour ({version}) + usageCount: Utilisé {count} fois + yes: Oui + diff --git a/ui/src/pages/dev.vue b/ui/src/pages/dev.vue index 57e88f48..2ba33140 100644 --- a/ui/src/pages/dev.vue +++ b/ui/src/pages/dev.vue @@ -1,9 +1,5 @@ + + en: + processingDisplayed: No processings | {displayed}/{count} processing displayed | {displayed}/{count} processings displayed + noProcessingsCreated: You haven't created any processings yet. + noProcessingsDisplayed: No results match the search criteria. + + fr: + processingDisplayed: Aucun traitement | {displayed}/{count} traitement affiché | {displayed}/{count} traitements affichés + noProcessingsCreated: Vous n'avez pas encore créé de traitement. + noProcessingsDisplayed: Aucun résultat ne correspond aux critères de recherche. + + + diff --git a/ui/src/pages/processings/new.vue b/ui/src/pages/processings/new.vue index a1d20712..7f12b545 100644 --- a/ui/src/pages/processings/new.vue +++ b/ui/src/pages/processings/new.vue @@ -7,7 +7,8 @@ > + + + + + + diff --git a/worker/config/development.mjs b/worker/config/development.mjs index c6dbb051..edffb4e8 100644 --- a/worker/config/development.mjs +++ b/worker/config/development.mjs @@ -12,7 +12,7 @@ export default { port: 9091 }, privateDataFairUrl: 'http://localhost:8081', - privateEventsUrl: 'http://localhost:8084', + privateEventsUrl: 'http://localhost:8083', runsRetention: 5, upgradeRoot: '../' }