From 5f4615f2c7c161c1f03904e093670d0f97827cae Mon Sep 17 00:00:00 2001 From: Arnei Date: Mon, 13 Apr 2026 16:34:22 +0200 Subject: [PATCH 01/14] Fix roles getting unselected in ACL tab In the access policy tab, when adding new roles, old roles would be removed. Basically, changing the roles in some manner would result in wonky behaviour. This patch fixes that, mostly by reverting 9d0a7b2203ee09e836bce57d08b230db87b2e32c and making sure the policy key id is more reliable than index. --- .../modals/ResourceDetailsAccessPolicyTab.tsx | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/components/shared/modals/ResourceDetailsAccessPolicyTab.tsx b/src/components/shared/modals/ResourceDetailsAccessPolicyTab.tsx index e23171dfc7..fdb1a86595 100644 --- a/src/components/shared/modals/ResourceDetailsAccessPolicyTab.tsx +++ b/src/components/shared/modals/ResourceDetailsAccessPolicyTab.tsx @@ -530,7 +530,7 @@ export const AccessPolicyTable = ({ {formik.values.policies.length > 0 && policiesFiltered.map( (policy, index) => ( - + {/* dropdown for policy.role */} {!transactions.readOnly ? ( @@ -547,11 +547,11 @@ export const AccessPolicyTable = ({ handleChange={element => { if (element) { const matchingRole = roles.find(role => role.name === element.value); - formik.setFieldValue(`policies.${index}.role`, element.value); - formik.setFieldValue( - `policies.${index}.user`, - matchingRole ? matchingRole.user : undefined, - ); + arrayHelpers.replace(formik.values.policies.findIndex(p => p === policy), { + ...policy, + role: element.value, + user: matchingRole ? matchingRole.user : undefined, + }); } }} placeholder={ @@ -591,7 +591,10 @@ export const AccessPolicyTable = ({ : "false" }`} onChange={(read: React.ChangeEvent) => - formik.setFieldValue(`policies.${index}.read`, read.target.checked) + arrayHelpers.replace(formik.values.policies.findIndex(p => p === policy), { + ...policy, + read: read.target.checked, + }) } /> @@ -615,7 +618,11 @@ export const AccessPolicyTable = ({ : "false" }`} onChange={(write: React.ChangeEvent) => - formik.setFieldValue(`policies.${index}.write`, write.target.checked) + arrayHelpers.replace(formik.values.policies.findIndex(p => p === policy), { + ...policy, + write: + write.target.checked, + }) } /> From 14f818f27feff5f90dfd0c2df4e3f16298200e6f Mon Sep 17 00:00:00 2001 From: Arnei Date: Thu, 23 Apr 2026 09:47:28 +0200 Subject: [PATCH 02/14] Always sort asc first for new column When sorting by a different column than before (e.g. by title instead of date), the sorting will now always be ascending first. Then on subsequent clicks on the same column you get descending and none. The goal for this patchis to improve the user experience through more intuitive behaviour. --- src/components/shared/Table.tsx | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/components/shared/Table.tsx b/src/components/shared/Table.tsx index bbcb32c15e..8648c643e4 100644 --- a/src/components/shared/Table.tsx +++ b/src/components/shared/Table.tsx @@ -222,10 +222,14 @@ const TableHeadRows = ({ forceDeselectAll }: { forceDeselectAll: () => unknown } forceDeselectAll(); dispatch(setSortBy(colName)); let direction: ReverseOptions = "ASC"; - if (reverse && reverse === "ASC") { - direction = "DESC"; - } else if (reverse && reverse === "DESC") { - direction = "NONE"; + if (sortBy !== colName) { + direction = "ASC"; + } else { + if (reverse && reverse === "ASC") { + direction = "DESC"; + } else if (reverse && reverse === "DESC") { + direction = "NONE"; + } } dispatch(reverseTable(direction)); dispatch(updatePages()); From 9a9a24428b3c1ee83fe6e3a4b24c061af26add92 Mon Sep 17 00:00:00 2001 From: Arnei Date: Thu, 23 Apr 2026 10:40:40 +0200 Subject: [PATCH 03/14] Fix warning wrongly appearing on template change When changing the template in the acl tab, if the current acl settings were invalid, a warning would appear *after* the template change about how the acl was invalid, when due to the template change it actually no longer wasn't. This fixes that. --- src/utils/aclUtils.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/utils/aclUtils.ts b/src/utils/aclUtils.ts index eb39e86fe5..9aab0406fe 100644 --- a/src/utils/aclUtils.ts +++ b/src/utils/aclUtils.ts @@ -102,6 +102,5 @@ export const handleTemplateChange = async Date: Fri, 24 Apr 2026 13:52:36 +0200 Subject: [PATCH 04/14] Update i18n to major version 26 Major version 26 has a breaking change that affects us, this patch should deal with that. --- package-lock.json | 80 +++++++++++++++++++++++++++++------------------ package.json | 8 ++--- src/i18n/i18n.ts | 34 +++++++++++++------- 3 files changed, 76 insertions(+), 46 deletions(-) diff --git a/package-lock.json b/package-lock.json index 80d1fd7862..9e54dd08b3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,16 +22,16 @@ "focus-trap-react": "^12.0.0", "formik": "^2.4.9", "http-proxy-middleware": "^3.0.5", - "i18next": "25.8.11", + "i18next": "26.0.7", "i18next-browser-languagedetector": "^8.2.1", - "i18next-http-backend": "^3.0.5", + "i18next-http-backend": "^3.0.6", "lodash": "^4.17.23", "react": "^19.2.4", "react-chartjs-2": "^5.3.1", "react-datepicker": "^8.8.0", "react-dom": "^19.2.4", "react-hotkeys-hook": "^5.2.4", - "react-i18next": "16.5.0", + "react-i18next": "17.0.4", "react-icons": "^5.5.0", "react-redux": "^9.2.0", "react-router": "^7.13.0", @@ -203,24 +203,24 @@ } }, "node_modules/@emnapi/core": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.2.tgz", - "integrity": "sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", + "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", "dev": true, - "license": "MIT", "optional": true, + "peer": true, "dependencies": { "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" } }, "node_modules/@emnapi/runtime": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.2.tgz", - "integrity": "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", + "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", "dev": true, - "license": "MIT", "optional": true, + "peer": true, "dependencies": { "tslib": "^2.4.0" } @@ -1534,6 +1534,29 @@ "node": "^20.19.0 || >=22.12.0" } }, + "node_modules/@rolldown/binding-wasm32-wasi/node_modules/@emnapi/core": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.2.tgz", + "integrity": "sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@rolldown/binding-wasm32-wasi/node_modules/@emnapi/runtime": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.2.tgz", + "integrity": "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@rolldown/binding-win32-arm64-msvc": { "version": "1.0.0-rc.16", "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.16.tgz", @@ -3927,29 +3950,26 @@ } }, "node_modules/i18next": { - "version": "25.8.11", - "resolved": "https://registry.npmjs.org/i18next/-/i18next-25.8.11.tgz", - "integrity": "sha512-LZ32llTLGludnddjLoijHV7TbmVubU5eJnsWf8taiuM3jmSfUuvBLuyDeubJKS1yBjLBgb7As124M4KWNcBvpw==", + "version": "26.0.7", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-26.0.7.tgz", + "integrity": "sha512-f7tL/iw0VQsx4nC5oNxBM2RjM8alNys5KzyiQTU6A9TI5TI89py4/Ez1cKFvHiLWsvzOXvuGUES+Kk/A2WiANQ==", "funding": [ { "type": "individual", - "url": "https://locize.com" + "url": "https://www.locize.com/i18next" }, { "type": "individual", - "url": "https://locize.com/i18next.html" + "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" }, { "type": "individual", - "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" + "url": "https://www.locize.com" } ], "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.28.4" - }, "peerDependencies": { - "typescript": "^5" + "typescript": "^5 || ^6" }, "peerDependenciesMeta": { "typescript": { @@ -3967,9 +3987,9 @@ } }, "node_modules/i18next-http-backend": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-3.0.5.tgz", - "integrity": "sha512-QaWHnsxieEDcqKe+vo/RFqpiIFRi/KBqlOSPcUlvinBaISCeiTRCbtrazHAjtHtsLC66oDsROAH8frWkQzfMMQ==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-3.0.6.tgz", + "integrity": "sha512-mBOqy8993jtqAoj6XaI1XeC/8/9v6EPS+681ziegrPvTB0DoaCY7PpTS0SpY56qLMoS4OI1TZEM2Zf59zNh05w==", "license": "MIT", "dependencies": { "cross-fetch": "4.1.0" @@ -5501,19 +5521,19 @@ } }, "node_modules/react-i18next": { - "version": "16.5.0", - "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-16.5.0.tgz", - "integrity": "sha512-IMpPTyCTKxEj8klCrLKUTIUa8uYTd851+jcu2fJuUB9Agkk9Qq8asw4omyeHVnOXHrLgQJGTm5zTvn8HpaPiqw==", + "version": "17.0.4", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-17.0.4.tgz", + "integrity": "sha512-hQipmK4EF0y6RO6tt6WuqnmWpWYEXmQUUzecmMBuNsIgYd3smXcG4GtYPWhvgxn0pqMOItKlEO8H24HCs5hc3g==", "license": "MIT", "dependencies": { - "@babel/runtime": "^7.27.6", + "@babel/runtime": "^7.29.2", "html-parse-stringify": "^3.0.1", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { - "i18next": ">= 25.6.2", + "i18next": ">= 26.0.1", "react": ">= 16.8.0", - "typescript": "^5" + "typescript": "^5 || ^6" }, "peerDependenciesMeta": { "react-dom": { diff --git a/package.json b/package.json index 034aaad995..5fe6120a62 100644 --- a/package.json +++ b/package.json @@ -19,16 +19,16 @@ "focus-trap-react": "^12.0.0", "formik": "^2.4.9", "http-proxy-middleware": "^3.0.5", - "i18next": "25.8.11", + "i18next": "26.0.7", "i18next-browser-languagedetector": "^8.2.1", - "i18next-http-backend": "^3.0.5", + "i18next-http-backend": "^3.0.6", "lodash": "^4.17.23", "react": "^19.2.4", "react-chartjs-2": "^5.3.1", "react-datepicker": "^8.8.0", "react-dom": "^19.2.4", "react-hotkeys-hook": "^5.2.4", - "react-i18next": "16.5.0", + "react-i18next": "17.0.4", "react-icons": "^5.5.0", "react-redux": "^9.2.0", "react-router": "^7.13.0", @@ -67,6 +67,7 @@ "@types/node": "^25.3.0", "@types/react-dom": "^19.2.3", "@types/uuid": "^11.0.0", + "@vitejs/plugin-react": "^6.0.1", "eslint": "^9.39.2", "prop-types": "^15.8.1", "sass": "^1.97.3", @@ -74,7 +75,6 @@ "typescript-eslint": "^8.56.0", "uuid": "^13.0.0", "vite": "^8.0.9", - "@vitejs/plugin-react": "^6.0.1", "vitest": "^4.0.18" } } diff --git a/src/i18n/i18n.ts b/src/i18n/i18n.ts index 0c6af4e310..4a8b19122e 100644 --- a/src/i18n/i18n.ts +++ b/src/i18n/i18n.ts @@ -1,4 +1,4 @@ -import i18n from "i18next"; +import i18n, { FormatterModule } from "i18next"; import { initReactI18next } from "react-i18next"; import HttpBackend, { HttpBackendOptions } from "i18next-http-backend"; @@ -23,7 +23,7 @@ import trTRTrans from "./org/opencastproject/adminui/languages/lang-tr_TR.json"; import zhCNTrans from "./org/opencastproject/adminui/languages/lang-zh_CN.json"; import zhTWTrans from "./org/opencastproject/adminui/languages/lang-zh_TW.json"; import { getCurrentLanguageInformation } from "../utils/utils"; -import { format } from "date-fns/format"; +import { format as dateFnsFormat } from "date-fns/format"; // Assignment of language code to translation file // !!! If translation file of a new language is added, please add assignment here, too !!! @@ -47,11 +47,29 @@ const resources = { "zh-TW": { translation: zhTWTrans }, } as const; +const myFormatter: FormatterModule = { + type: "formatter", + init(_services, _i18nextOptions) {}, + format(value, format, lng, _options) { + if (value instanceof Date && format && lng) { + return dateFnsFormat(value, format, { + locale: getCurrentLanguageInformation(lng)?.dateLocale, + }); + } + + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return value; + }, + add(_name, _fc) { }, + addCached(_name, _fc) { }, +}; + // Configuration of i18next i18n .use(HttpBackend) .use(LanguageDetector) .use(initReactI18next) + .use(myFormatter) .init({ resources, fallbackLng: "en-US", @@ -59,17 +77,9 @@ i18n interpolation: { escapeValue: false, - format: function (value, formatStr, lng) { - if (value instanceof Date && formatStr && lng) { - return format(value, formatStr, { - locale: getCurrentLanguageInformation(lng)?.dateLocale, - }); - } - - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return value; - }, + alwaysFormat: true, }, + react: { useSuspense: false, }, From d0392077c50a06e8a4107ba42f0a1cb4c88472a1 Mon Sep 17 00:00:00 2001 From: Arnei Date: Fri, 24 Apr 2026 14:55:45 +0200 Subject: [PATCH 05/14] Move to node 24 in gh workflows The maintenance window for node 20 is running out, we should probably update. --- .github/workflows/deploy-main-branches.yml | 2 +- .github/workflows/pr-deploy-test-branch.yml | 2 +- .github/workflows/pr-test-build.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/deploy-main-branches.yml b/.github/workflows/deploy-main-branches.yml index cd633c0fb4..cd2f424e96 100644 --- a/.github/workflows/deploy-main-branches.yml +++ b/.github/workflows/deploy-main-branches.yml @@ -47,7 +47,7 @@ jobs: - name: Get Node.js uses: actions/setup-node@v5 with: - node-version: 20 + node-version: 24 - name: Run npm ci run: npm ci diff --git a/.github/workflows/pr-deploy-test-branch.yml b/.github/workflows/pr-deploy-test-branch.yml index a534561288..796926f5f9 100644 --- a/.github/workflows/pr-deploy-test-branch.yml +++ b/.github/workflows/pr-deploy-test-branch.yml @@ -53,7 +53,7 @@ jobs: - name: Get Node.js uses: actions/setup-node@v5 with: - node-version: 20 + node-version: 24 - name: Run npm ci run: npm ci diff --git a/.github/workflows/pr-test-build.yml b/.github/workflows/pr-test-build.yml index d5e6165c61..a43d0b905e 100644 --- a/.github/workflows/pr-test-build.yml +++ b/.github/workflows/pr-test-build.yml @@ -16,7 +16,7 @@ jobs: - name: Get Node.js uses: actions/setup-node@v5 with: - node-version: 20 + node-version: 24 - name: Run npm ci run: npm ci From 150053afbb6dd1cae2765004dfbbbe8ba86fd818 Mon Sep 17 00:00:00 2001 From: Arnei Date: Tue, 28 Apr 2026 11:23:34 +0200 Subject: [PATCH 06/14] Improve acl tab performance for systems with many roles Memoization should prevent the dropdown options from getting recreated on every rerender. This should speed up non-dropdown related actions, such as adding new roles or changing access rights, on systems with many roles. --- .../modals/ResourceDetailsAccessPolicyTab.tsx | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/components/shared/modals/ResourceDetailsAccessPolicyTab.tsx b/src/components/shared/modals/ResourceDetailsAccessPolicyTab.tsx index e23171dfc7..28ba1ac5d7 100644 --- a/src/components/shared/modals/ResourceDetailsAccessPolicyTab.tsx +++ b/src/components/shared/modals/ResourceDetailsAccessPolicyTab.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from "react"; +import React, { useState, useEffect, useMemo } from "react"; import RenderMultiField from "../wizard/RenderMultiField"; import { Acl, @@ -434,6 +434,12 @@ export const AccessPolicyTable = ({ // eslint-disable-next-line react-hooks/exhaustive-deps }, []); + const dropdownOptions = useMemo(() => { + return roles.length > 0 + ? formatAclRolesForDropdown(rolesFilteredbyPolicies) + : []; + }, [roles, rolesFilteredbyPolicies]); + const createPolicy = (role: string, withUser: boolean): TransformedAcl => { const user = withUser ? { username: "", name: "", email: "" } : undefined; @@ -537,11 +543,7 @@ export const AccessPolicyTable = ({ 0 - ? formatAclRolesForDropdown(rolesFilteredbyPolicies) - : [] - } + options={dropdownOptions} required={true} creatable={true} handleChange={element => { From e8c37ffb52fe9ceff57bad9c60806e7741d9ec31 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 May 2026 13:44:16 +0000 Subject: [PATCH 07/14] Bump actions/github-script from 7 to 9 Bumps [actions/github-script](https://github.com/actions/github-script) from 7 to 9. - [Release notes](https://github.com/actions/github-script/releases) - [Commits](https://github.com/actions/github-script/compare/v7...v9) --- updated-dependencies: - dependency-name: actions/github-script dependency-version: '9' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/pr-deploy-test-branch.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr-deploy-test-branch.yml b/.github/workflows/pr-deploy-test-branch.yml index a534561288..e8bc5eeaa7 100644 --- a/.github/workflows/pr-deploy-test-branch.yml +++ b/.github/workflows/pr-deploy-test-branch.yml @@ -158,7 +158,7 @@ jobs: - name: Check for changes in translations if: steps.filter_locales.outputs.locales == true - uses: actions/github-script@v7 + uses: actions/github-script@v9 with: script: | core.setFailed('You should not alter translations outside of Crowdin.') From 6f26e6fb90816325d499247a2ad14cf2847a4062 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 May 2026 13:45:28 +0000 Subject: [PATCH 08/14] Bump react-tooltip from 5.30.1 to 6.0.0 Bumps [react-tooltip](https://github.com/ReactTooltip/react-tooltip) from 5.30.1 to 6.0.0. - [Release notes](https://github.com/ReactTooltip/react-tooltip/releases) - [Changelog](https://github.com/ReactTooltip/react-tooltip/blob/master/CHANGELOG.md) - [Commits](https://github.com/ReactTooltip/react-tooltip/compare/v5.30.1...v6.0.0) --- updated-dependencies: - dependency-name: react-tooltip dependency-version: 6.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- package-lock.json | 12 ++++++------ package.json | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index 80d1fd7862..25a2352df5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -37,7 +37,7 @@ "react-router": "^7.13.0", "react-select": "^5.10.2", "react-textarea-autosize": "^8.5.9", - "react-tooltip": "^5.30.0", + "react-tooltip": "^6.0.0", "react-window": "^2.2.7", "redux": "^5.0.1", "redux-persist": "^6.0.0", @@ -5626,13 +5626,13 @@ } }, "node_modules/react-tooltip": { - "version": "5.30.1", - "resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-5.30.1.tgz", - "integrity": "sha512-1lSPLQXuVooePxadUpmcwLgOsF1mIty7UZTJ9XnyfX4drOzStYs4JMXnazcDLguQr41W5OUZddOp9kfvArdpEQ==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-6.0.0.tgz", + "integrity": "sha512-J7m56tmdmhpjHz8YsQXGNaJdsYtrByKQvKj/Vcd0GBru1fcGRP2yv0ehCEuJbKTirlt3iBg9W5gcMWnM1dj67w==", "license": "MIT", "dependencies": { - "@floating-ui/dom": "^1.6.1", - "classnames": "^2.3.0" + "@floating-ui/dom": "1.7.6", + "clsx": "2.1.1" }, "peerDependencies": { "react": ">=16.14.0", diff --git a/package.json b/package.json index 034aaad995..5c6eb22b20 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "react-router": "^7.13.0", "react-select": "^5.10.2", "react-textarea-autosize": "^8.5.9", - "react-tooltip": "^5.30.0", + "react-tooltip": "^6.0.0", "react-window": "^2.2.7", "redux": "^5.0.1", "redux-persist": "^6.0.0", From 2446e77dc34e442f8ea36a141d240adcf26e141f Mon Sep 17 00:00:00 2001 From: Arnei Date: Thu, 7 May 2026 16:01:14 +0200 Subject: [PATCH 09/14] Add translation for "Needs Cutting" filter --- .../org/opencastproject/adminui/languages/lang-en_US.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/i18n/org/opencastproject/adminui/languages/lang-en_US.json b/src/i18n/org/opencastproject/adminui/languages/lang-en_US.json index 8c0fc418da..d273d2c096 100644 --- a/src/i18n/org/opencastproject/adminui/languages/lang-en_US.json +++ b/src/i18n/org/opencastproject/adminui/languages/lang-en_US.json @@ -1895,6 +1895,11 @@ }, "WRITE_ACCESS": { "LABEL": "Write Access" + }, + "NEEDS_CUTTING": { + "LABEL": "Needs cutting", + "YES": "Yes", + "NO": "No" } }, "JOBS": { From b1db88625b28c7b26f92713b02ff73b87976f582 Mon Sep 17 00:00:00 2001 From: Arnei Date: Fri, 8 May 2026 12:56:30 +0200 Subject: [PATCH 10/14] Fix Imprint/Privacy page breaking the app Opening one of the two about pages would crash the admin ui. This should fix that. --- src/components/shared/MainNav.tsx | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/components/shared/MainNav.tsx b/src/components/shared/MainNav.tsx index 6d126f647d..09c8ecd35e 100644 --- a/src/components/shared/MainNav.tsx +++ b/src/components/shared/MainNav.tsx @@ -174,14 +174,18 @@ const MainNav = ({ // current view is always the first element. Otherwise, NavLink will not // recognize the current view as active. if (firstPathFragment.length > 0) { - const arrToSort = linkMap[firstPathFragment as keyof typeof linkMap].links; - if (arrToSort != undefined && arrToSort.length > 1) { - arrToSort.forEach(item => { + const linkMapItem = linkMap[firstPathFragment as keyof typeof linkMap]; + + if (linkMapItem?.links && linkMapItem.links.length > 1) { + const arrToSort = linkMapItem.links; + if (arrToSort != undefined && arrToSort.length > 1) { + arrToSort.forEach(item => { + // @ts-expect-error: TODO: Someone else can fix this + if (item.path === pathname) { item.tmpIndex = 0; } else { item.tmpIndex = 1; } + }); // @ts-expect-error: TODO: Someone else can fix this - if (item.path === pathname) { item.tmpIndex = 0; } else { item.tmpIndex = 1; } - }); - // @ts-expect-error: TODO: Someone else can fix this - arrToSort.sort((a, b) => a.tmpIndex - b.tmpIndex); + arrToSort.sort((a, b) => a.tmpIndex - b.tmpIndex); + } } } From 3b327cc2335202f51dd218d469251b2a64e987cb Mon Sep 17 00:00:00 2001 From: Greg Logan Date: Tue, 12 May 2026 14:50:27 -0600 Subject: [PATCH 11/14] Removing automated PR filing in favour of https://github.com/opencast/opencast/pull/7637 --- .github/workflows/deploy-main-branches.yml | 61 ---------------------- 1 file changed, 61 deletions(-) diff --git a/.github/workflows/deploy-main-branches.yml b/.github/workflows/deploy-main-branches.yml index 5d534437d0..e51df8b0f5 100644 --- a/.github/workflows/deploy-main-branches.yml +++ b/.github/workflows/deploy-main-branches.yml @@ -97,64 +97,3 @@ jobs: - name: Push updates run: git push origin gh-pages --force - - - file-upstream-admin-pr: - name: Create upstream admin PR to incorporate build - runs-on: ubuntu-latest - needs: detect-repo-owner - permissions: - contents: write # For the release - pull-requests: write # For the PR in the upstream repo - - steps: - - name: Prepare git - run: | - git config --global user.name "Admin Interface Commit Bot" - git config --global user.email "cloud@opencast.org" - - - name: Prepare GitHub SSH key - env: - DEPLOY_KEY: ${{ secrets.MODULE_PR_DEPLOY_KEY }} - run: | - install -dm 700 ~/.ssh/ - echo "${DEPLOY_KEY}" > ~/.ssh/id_ed25519 - chmod 600 ~/.ssh/id_ed25519 - ssh-keyscan github.com >> ~/.ssh/known_hosts - - - name: Clone upstream repository - run: | - git clone -b ${{ github.ref_name }} "git@github.com:${{ github.repository_owner }}/opencast.git" opencast - cd opencast - git checkout -b t/admin-${{ needs.detect-repo-owner.outputs.branch }} - - - name: Update the admin submodule - working-directory: opencast - run: | - # Note: This could be a race condition in that rapid submodule pushes can trigger multiple PRs in short order - # and we don't have a guarantee that the update triggered by commit A does not end up finding commit B - # We are going to ignore this possibility since we almost universally want the *latest* commit, though this - # could end up causing the commit message, and the actual submodule hash to differ. - git submodule update --init --remote modules/admin - git add modules/admin - git commit -m "Updating admin-service to ${{ github.sha }}" - # This token is an account wide token which allows creation of PRs and pushes. - echo "${{ secrets.MODULE_PR_TOKEN }}" > token.txt - gh auth login --with-token < token.txt - export CURRENT_PR=$(gh pr list -R ${{ github.repository_owner }}/opencast --head t/admin-${{ needs.detect-repo-owner.outputs.branch }} --json number --jq '.[].number') - git push origin t/admin-${{ needs.detect-repo-owner.outputs.branch }} --force - if [ -n "$CURRENT_PR" ]; then - gh pr edit $CURRENT_PR \ - --body "Updating Opencast ${{ needs.detect-repo-owner.outputs.branch }} Admin Interface module to [${{ github.sha }}](https://github.com/${{ github.repository_owner }}/admin-interface/commit/${{ github.sha }})" \ - -R ${{ github.repository_owner }}/opencast - else - gh pr create \ - --title "Update ${{ needs.detect-repo-owner.outputs.branch }} Admin Interface" \ - --body "Updating Opencast ${{ needs.detect-repo-owner.outputs.branch }} Admin Interface module to [${{ github.sha }}](https://github.com/${{ github.repository_owner }}/admin-interface/commit/${{ github.sha }})" \ - --head=${{ github.repository_owner }}:t/admin-${{ needs.detect-repo-owner.outputs.branch }} \ - --base ${{ github.ref_name }} \ - -R ${{ github.repository_owner }}/opencast - #FIXME: fine grained PATs can't apply labels - #FIXME: classic PATs don't have the permissions because the PR isn't in an opencastproject (the user) repo - #--label admin-ui --label maintenance \ - fi From bc66a5a8918b706432318e65c3a862d1efccf321 Mon Sep 17 00:00:00 2001 From: Greg Logan Date: Tue, 5 May 2026 22:31:10 -0600 Subject: [PATCH 12/14] Using the parent pom's node version --- pom.xml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 48a5324801..e04b4a616e 100644 --- a/pom.xml +++ b/pom.xml @@ -13,8 +13,6 @@ ${project.basedir}/../.. false - v20.10.0 - @@ -101,7 +99,7 @@ com.github.eirslett frontend-maven-plugin - ${nodejs.version} + ${node.version} target /admin-ui From 2f355989cba265ad94b0ceb725b1e541132bf100 Mon Sep 17 00:00:00 2001 From: Greg Logan Date: Wed, 6 May 2026 10:17:23 -0600 Subject: [PATCH 13/14] Bumping node version, and ensuring that our version and the main parent version match --- .github/workflows/deploy-main-branches.yml | 10 +++++++++- .github/workflows/pr-deploy-test-branch.yml | 10 +++++++++- .github/workflows/pr-test-build.yml | 10 +++++++++- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/.github/workflows/deploy-main-branches.yml b/.github/workflows/deploy-main-branches.yml index 7ae1793db6..b95cc860ad 100644 --- a/.github/workflows/deploy-main-branches.yml +++ b/.github/workflows/deploy-main-branches.yml @@ -11,6 +11,9 @@ concurrency: group: ${{ github.workflow }} cancel-in-progress: false +env: + NODE_VERSION: 24 + jobs: detect-repo-owner: name: Detect branch and appropriate server @@ -44,10 +47,15 @@ jobs: - name: Checkout sources uses: actions/checkout@v5 + - name: Ensure our node version matches the main repo's version + run: | + [[ "$(curl -s https://raw.githubusercontent.com/opencast/opencast/refs/heads/${{ github.ref_name }}/pom.xml | \ + grep node.version | grep -Eo 'v[0-9.]+' | cut -f 1 -d '.' | cut -c 2-)" == "$NODE_VERSION" ]] && exit 0 || exit 1 + - name: Get Node.js uses: actions/setup-node@v5 with: - node-version: 24 + node-version: $NODE_VERSION - name: Run npm ci run: npm ci diff --git a/.github/workflows/pr-deploy-test-branch.yml b/.github/workflows/pr-deploy-test-branch.yml index bf56f5bdc6..637597398c 100644 --- a/.github/workflows/pr-deploy-test-branch.yml +++ b/.github/workflows/pr-deploy-test-branch.yml @@ -10,6 +10,9 @@ concurrency: group: pull-request-page cancel-in-progress: false +env: + NODE_VERSION: 24 + jobs: detect-repo-owner: if: github.repository_owner == 'opencast' @@ -50,10 +53,15 @@ jobs: ref: ${{github.event.pull_request.head.ref}} repository: ${{github.event.pull_request.head.repo.full_name}} + - name: Ensure our node version matches the main repo's version + run: | + [[ "$(curl -s https://raw.githubusercontent.com/opencast/opencast/refs/heads/${{ github.ref_name }}/pom.xml | \ + grep node.version | grep -Eo 'v[0-9.]+' | cut -f 1 -d '.' | cut -c 2-)" == "$NODE_VERSION" ]] && exit 0 || exit 1 + - name: Get Node.js uses: actions/setup-node@v5 with: - node-version: 24 + node-version: $NODE_VERSION - name: Run npm ci run: npm ci diff --git a/.github/workflows/pr-test-build.yml b/.github/workflows/pr-test-build.yml index a43d0b905e..d045558800 100644 --- a/.github/workflows/pr-test-build.yml +++ b/.github/workflows/pr-test-build.yml @@ -6,6 +6,9 @@ on: - 'dependabot/**' pull_request: +env: + NODE_VERSION: 24 + jobs: check-npm-build: runs-on: ubuntu-latest @@ -13,10 +16,15 @@ jobs: - name: Checkout sources uses: actions/checkout@v5 + - name: Ensure our node version matches the main repo's version + run: | + [[ "$(curl -s https://raw.githubusercontent.com/opencast/opencast/refs/heads/${{ github.ref_name }}/pom.xml | \ + grep node.version | grep -Eo 'v[0-9.]+' | cut -f 1 -d '.' | cut -c 2-)" == "$NODE_VERSION" ]] && exit 0 || exit 1 + - name: Get Node.js uses: actions/setup-node@v5 with: - node-version: 24 + node-version: $NODE_VERSION - name: Run npm ci run: npm ci From 8fd30041e8bc3e9d500f077a1b07b0eba37b8233 Mon Sep 17 00:00:00 2001 From: Greg Logan Date: Wed, 6 May 2026 11:49:24 -0600 Subject: [PATCH 14/14] Special handline for push vs pull request --- .github/workflows/deploy-main-branches.yml | 4 +++- .github/workflows/pr-deploy-test-branch.yml | 6 ++++-- .github/workflows/pr-test-build.yml | 12 +++++++++++- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/.github/workflows/deploy-main-branches.yml b/.github/workflows/deploy-main-branches.yml index b95cc860ad..a122a70d43 100644 --- a/.github/workflows/deploy-main-branches.yml +++ b/.github/workflows/deploy-main-branches.yml @@ -50,7 +50,9 @@ jobs: - name: Ensure our node version matches the main repo's version run: | [[ "$(curl -s https://raw.githubusercontent.com/opencast/opencast/refs/heads/${{ github.ref_name }}/pom.xml | \ - grep node.version | grep -Eo 'v[0-9.]+' | cut -f 1 -d '.' | cut -c 2-)" == "$NODE_VERSION" ]] && exit 0 || exit 1 + grep node.version | grep -Eo 'v[0-9.]+' | cut -f 1 -d '.' | cut -c 2-)" == "$NODE_VERSION" ]] \ + && exit 0 \ + || (echo "Node version does not match"; exit 1) - name: Get Node.js uses: actions/setup-node@v5 diff --git a/.github/workflows/pr-deploy-test-branch.yml b/.github/workflows/pr-deploy-test-branch.yml index 637597398c..d030591969 100644 --- a/.github/workflows/pr-deploy-test-branch.yml +++ b/.github/workflows/pr-deploy-test-branch.yml @@ -55,8 +55,10 @@ jobs: - name: Ensure our node version matches the main repo's version run: | - [[ "$(curl -s https://raw.githubusercontent.com/opencast/opencast/refs/heads/${{ github.ref_name }}/pom.xml | \ - grep node.version | grep -Eo 'v[0-9.]+' | cut -f 1 -d '.' | cut -c 2-)" == "$NODE_VERSION" ]] && exit 0 || exit 1 + [[ "$(curl -s https://raw.githubusercontent.com/opencast/opencast/refs/heads/${{ github.base_ref }}/pom.xml | \ + grep node.version | grep -Eo 'v[0-9.]+' | cut -f 1 -d '.' | cut -c 2-)" == "$NODE_VERSION" ]] \ + && exit 0 \ + || (echo "Node version does not match"; exit 1) - name: Get Node.js uses: actions/setup-node@v5 diff --git a/.github/workflows/pr-test-build.yml b/.github/workflows/pr-test-build.yml index d045558800..4ee04b614f 100644 --- a/.github/workflows/pr-test-build.yml +++ b/.github/workflows/pr-test-build.yml @@ -17,9 +17,19 @@ jobs: uses: actions/checkout@v5 - name: Ensure our node version matches the main repo's version + if: github.event_name == 'pull_request' + run: | + [[ "$(curl -s https://raw.githubusercontent.com/opencast/opencast/refs/heads/${{ github.base_ref }}/pom.xml | \ + grep node.version | grep -Eo 'v[0-9.]+' | cut -f 1 -d '.' | cut -c 2-)" == "$NODE_VERSION" ]] \ + && exit 0 \ + || (echo "Node version does not match"; exit 1) + - name: Ensure our node version matches the main repo's version + if: github.event_name == 'push' run: | [[ "$(curl -s https://raw.githubusercontent.com/opencast/opencast/refs/heads/${{ github.ref_name }}/pom.xml | \ - grep node.version | grep -Eo 'v[0-9.]+' | cut -f 1 -d '.' | cut -c 2-)" == "$NODE_VERSION" ]] && exit 0 || exit 1 + grep node.version | grep -Eo 'v[0-9.]+' | cut -f 1 -d '.' | cut -c 2-)" == "$NODE_VERSION" ]] \ + && exit 0 \ + || (echo "Node version does not match"; exit 1) - name: Get Node.js uses: actions/setup-node@v5