From cf50938dad2c44978fc8fe8075dc33e9437e4258 Mon Sep 17 00:00:00 2001 From: Tim Bradgate Date: Mon, 8 Jun 2026 23:10:26 +0100 Subject: [PATCH 1/7] [npm] Update dependencies --- client-v3/package-lock.json | 218 +++++++++++++++++++++--------------- client-v3/package.json | 12 +- client/package-lock.json | 148 ++++++++++++------------ client/package.json | 8 +- electron/package-lock.json | 136 +++++++++++----------- electron/package.json | 4 +- 6 files changed, 280 insertions(+), 246 deletions(-) diff --git a/client-v3/package-lock.json b/client-v3/package-lock.json index 69ae23544..99ae0afac 100644 --- a/client-v3/package-lock.json +++ b/client-v3/package-lock.json @@ -20,7 +20,7 @@ "d3-zoom": "^3.0.0", "deep-object-diff": "1.1.9", "dompurify": "^3.4.8", - "fuse.js": "^7.4.1", + "fuse.js": "^7.4.2", "lodash": "^4.18.1", "loglevel": "^1.9.2", "marked": "^18.0.5", @@ -33,15 +33,15 @@ "vue-toast-notification": "^3.1.3" }, "devDependencies": { - "@emnapi/core": "1.10.0", - "@emnapi/runtime": "1.10.0", + "@emnapi/core": "1.11.0", + "@emnapi/runtime": "1.11.0", "@eslint/js": "^10.0.1", "@iconify-json/mdi": "^1.2.3", "@playwright/test": "^1.60.0", "@types/lodash": "~4.17.24", "@types/node": ">=22.12.0", - "@typescript-eslint/eslint-plugin": "^8.60.1", - "@typescript-eslint/parser": "^8.60.1", + "@typescript-eslint/eslint-plugin": "^8.61.0", + "@typescript-eslint/parser": "^8.61.0", "@vitejs/plugin-vue": "^6.0.7", "@vitest/ui": "^4.1.8", "@vue/test-utils": "^2.4.11", @@ -55,7 +55,7 @@ "prettier": "^3.8.3", "sass": "1.100.0", "typescript": "^6.0.3", - "typescript-eslint": "^8.60.1", + "typescript-eslint": "^8.61.0", "unplugin-icons": "^23.0.1", "unplugin-vue-components": "^32.1.0", "vite": "^8.0.16", @@ -397,21 +397,21 @@ } }, "node_modules/@emnapi/core": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", - "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.0.tgz", + "integrity": "sha512-l9Oo58x0HOP5znGzVhYW9U3e5wVuA4LAZU2AGezTmkhO1CgQRFDhDg4nneHsu/t3WniXg9QrG2nIXL/ZS8ln8Q==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@emnapi/wasi-threads": "1.2.1", + "@emnapi/wasi-threads": "1.2.2", "tslib": "^2.4.0" } }, "node_modules/@emnapi/runtime": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", - "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.0.tgz", + "integrity": "sha512-55coeOFKHv1ywEcUXJtWU5f+Jr/W5tZDvZig8DLKSwUN1JpROQ4rk/SNOQiFWmaR/VKF4zuFyW1B8JduOSv6Pg==", "dev": true, "license": "MIT", "peer": true, @@ -420,9 +420,9 @@ } }, "node_modules/@emnapi/wasi-threads": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", - "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.2.tgz", + "integrity": "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==", "dev": true, "license": "MIT", "dependencies": { @@ -1427,6 +1427,40 @@ "node": "^20.19.0 || >=22.12.0" } }, + "node_modules/@rolldown/binding-wasm32-wasi/node_modules/@emnapi/core": { + "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, + "dependencies": { + "@emnapi/wasi-threads": "1.2.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@rolldown/binding-wasm32-wasi/node_modules/@emnapi/runtime": { + "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, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@rolldown/binding-wasm32-wasi/node_modules/@emnapi/wasi-threads": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", + "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@rolldown/binding-win32-arm64-msvc": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.3.tgz", @@ -1574,9 +1608,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "25.9.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.9.1.tgz", - "integrity": "sha512-xfrlY7UD5rMJk3ZVJP8BNzS28J36YJg+xp+LPXV1TdWxr8uMH5A860QNxYDGQe/ylDSgjxE52Q9VnO7p75tJxg==", + "version": "25.9.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.9.2.tgz", + "integrity": "sha512-G05zqtJhcDLb8uslf5EjCxXg9G1KQxiV8OS0R26IC//Eoyitzqe8z37I7cqvnZlrlSfgocQRfSn/AHBZJJFyGw==", "dev": true, "license": "MIT", "peer": true, @@ -1598,17 +1632,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.60.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.60.1.tgz", - "integrity": "sha512-JQ4S5GB0tfjO8BuJ4fcX+HodkzJjYBV+7OJ+wLygaX7OGQ7FudyHL4NSCA6ob+w3Yn+5MkKIozOwQhXeM7opVg==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.61.0.tgz", + "integrity": "sha512-bFNvl9ZczlVb+wR2Akszf3gHfKVj/8WanXaGJ3UstTA7brNKg0cNdk6X1Psu5V7MZ2oQtzZKOEzIUehaoxbDGw==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.60.1", - "@typescript-eslint/type-utils": "8.60.1", - "@typescript-eslint/utils": "8.60.1", - "@typescript-eslint/visitor-keys": "8.60.1", + "@typescript-eslint/scope-manager": "8.61.0", + "@typescript-eslint/type-utils": "8.61.0", + "@typescript-eslint/utils": "8.61.0", + "@typescript-eslint/visitor-keys": "8.61.0", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" @@ -1621,23 +1655,23 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.60.1", + "@typescript-eslint/parser": "^8.61.0", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/parser": { - "version": "8.60.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.60.1.tgz", - "integrity": "sha512-A0M6ua6H252bVjPvvtSgl2QA4+ET9S5Mtkb2GDyTxIhH/C4qDItT7RQNO5PhMC6NXGYXOR9dIalcDDgBKT7oFA==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.61.0.tgz", + "integrity": "sha512-5B7PfA2e1NQGCnDHd/0lW7W3gvp3d59Ryw54FYO8Uswxo9f6ikw3AZV+Xj/TvpImmpsiYyUqAfhC6kJID1jF6w==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@typescript-eslint/scope-manager": "8.60.1", - "@typescript-eslint/types": "8.60.1", - "@typescript-eslint/typescript-estree": "8.60.1", - "@typescript-eslint/visitor-keys": "8.60.1", + "@typescript-eslint/scope-manager": "8.61.0", + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/typescript-estree": "8.61.0", + "@typescript-eslint/visitor-keys": "8.61.0", "debug": "^4.4.3" }, "engines": { @@ -1653,14 +1687,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.60.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.60.1.tgz", - "integrity": "sha512-eXkTH2bxmXlqD1RnOPmLZ9ZM9D3VwSx04JOwBnP9RQ+yUA5a2Mu7SfW8uaV2Aon53NJzZlZYuX7tn91Izf+xaw==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.61.0.tgz", + "integrity": "sha512-DV42F7MLJO6Rax7SK1yg43tcnEfGUrurSpSxKuVX+a3RCTzBlH3fuxprrOJXKCJGAaw82xXocikJ0uQaqwXgGA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.60.1", - "@typescript-eslint/types": "^8.60.1", + "@typescript-eslint/tsconfig-utils": "^8.61.0", + "@typescript-eslint/types": "^8.61.0", "debug": "^4.4.3" }, "engines": { @@ -1675,14 +1709,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.60.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.60.1.tgz", - "integrity": "sha512-gvI5OQoptnxQnchOirukCuQ55svJSTuD/4k5+pC267xyBtYry748R9/c3tYUzb/iE6RZfllRz2lVulLCHkTm4w==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.61.0.tgz", + "integrity": "sha512-IWdXFHFSb6mlC3HPc7QsLDm5zYEbUla6trDEHf32D3/dnuUyXd87plScSNXSbm0/RxMvObpI17sv/EDTGrGZkA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.60.1", - "@typescript-eslint/visitor-keys": "8.60.1" + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/visitor-keys": "8.61.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1693,9 +1727,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.60.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.60.1.tgz", - "integrity": "sha512-nh8w4qAteiKuZu3pSSzG/yGKpw0OlkrKnzFmbVRenKaD4qc+7i1GrmZaLVkr8rk4uipiPGMOW4YsM6WmKZ5CvA==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.61.0.tgz", + "integrity": "sha512-O5Amvdv9ztMpxpf+vmFULGG78IE6Qwdr3bCGvqwG4nwc9H2qXkOYJJnRbRHyMkQTjv1d03olqwwwzHLMqpFePQ==", "dev": true, "license": "MIT", "engines": { @@ -1710,15 +1744,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.60.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.60.1.tgz", - "integrity": "sha512-sdwTrpjosW7ANQYJ39ZBF1ZyEMEGVB2UsikrserVM/30a/F1dTLnu9bGxEdosugyu5caigjLrR2qiD11asjI1A==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.61.0.tgz", + "integrity": "sha512-TuBiQYIkd97yBfInHCTKVYMbX4kvEmpOEuixIuzCU9p8BGT1SfyyO0d0IfDMbPIHcjn/hWnusUX5e8v5Xg+X8A==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.60.1", - "@typescript-eslint/typescript-estree": "8.60.1", - "@typescript-eslint/utils": "8.60.1", + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/typescript-estree": "8.61.0", + "@typescript-eslint/utils": "8.61.0", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, @@ -1735,9 +1769,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.60.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.60.1.tgz", - "integrity": "sha512-4h0tY8ppCkdCzcrl2YM5M3my0xsE1Tf8om3owEu5oPWmXwkKRmk0j0LGDzYBGUcAlesEbxBhazqu/K4cu3Ug7w==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.61.0.tgz", + "integrity": "sha512-9QTQpZ5Iin4CdIodfbDQFSeiSJKidgYJYug1P9CC2xWgUTvlmixViqDZNciMjwLBZyJnG4tGmPl97rVAFb1AJg==", "dev": true, "license": "MIT", "engines": { @@ -1749,16 +1783,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.60.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.60.1.tgz", - "integrity": "sha512-alpRkfG8hlVE5kdJW2GkfgDgXxold3e8e4l6EnmhRmRLbekgAPCCGDVD++sABy9FcgPFroq+uFcCSM1vR57Cew==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.61.0.tgz", + "integrity": "sha512-42zatd5qSvvcV1JdDBCLxYRznvP4eIHpPoZXdkPFnAmanA4FuZ5dibSnCBggY8hQnqajPpoGjXFdZ7fIJKQnlA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.60.1", - "@typescript-eslint/tsconfig-utils": "8.60.1", - "@typescript-eslint/types": "8.60.1", - "@typescript-eslint/visitor-keys": "8.60.1", + "@typescript-eslint/project-service": "8.61.0", + "@typescript-eslint/tsconfig-utils": "8.61.0", + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/visitor-keys": "8.61.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", @@ -1777,16 +1811,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.60.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.60.1.tgz", - "integrity": "sha512-h2MPBLoNtjc3qZWfY3Tl51yPorQ2McHn8pJfcMNTcIvrrZrr90Ykffit0yjrPFWQcRcUxzH20+6OcVdW4yHtUg==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.61.0.tgz", + "integrity": "sha512-3bzFt7ImFMW/jVYwJamDoe/dMOdFLSC6pom6rRjdh4SZJEYupyMzem8e7vKZLclLfpHjlwSAXOUxtKxGXUiLqA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.60.1", - "@typescript-eslint/types": "8.60.1", - "@typescript-eslint/typescript-estree": "8.60.1" + "@typescript-eslint/scope-manager": "8.61.0", + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/typescript-estree": "8.61.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1801,13 +1835,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.60.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.60.1.tgz", - "integrity": "sha512-EbGRQg4FhrmwLodl+t3JNAnXHWVr9Vp+Zl1QBZVPY4ByfkzIT8cX3K6QWODHtkIZqqJVEWvhHSx3v5PDHsaQag==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.61.0.tgz", + "integrity": "sha512-QVLZu3ZPQEE+HICQyAMZ2yLQhxf0meY/wx6Hx14YcTNj13JB3qHlX3lJ02L3fLGHgERRH71kvYDwiXIguT3AjQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.60.1", + "@typescript-eslint/types": "8.61.0", "eslint-visitor-keys": "^5.0.0" }, "engines": { @@ -3438,9 +3472,9 @@ } }, "node_modules/fuse.js": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-7.4.1.tgz", - "integrity": "sha512-AY7lKAXK71hi3WgUvDy6oZL67UEHOOtvCAwVdOXHyJd6ZzftBy7QqxuXt4HxmmAhYjmp/YCuOELZtIvAdlZ+fw==", + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-7.4.2.tgz", + "integrity": "sha512-LVbzjD4WA6UP5B1UnP8wuaXJiLnqMdM/E4fiJXTJ5haJ5b/MBNsK29h2fm6swEoQaVQjvYFWKLE2RanyZIoRVQ==", "license": "Apache-2.0", "engines": { "node": ">=10" @@ -4861,9 +4895,9 @@ "license": "MIT" }, "node_modules/semver": { - "version": "7.8.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.2.tgz", - "integrity": "sha512-c8jsqUZm3omBOI66G90z1Dyw5z622G8oLG+omfsHBJf3CWQTlOcwOjvOG6wtiNfW6anKm/eA39LMwMtMez2TiQ==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.3.tgz", + "integrity": "sha512-wnilbGyMxzbY7dNOl7jpKbLSjcfeweJWU5j4+u5qW+6/wuGD9KzIGOyZnQVSBM9E7DtWaaH3CyHkppYrKYoxwg==", "dev": true, "license": "ISC", "bin": { @@ -5261,16 +5295,16 @@ } }, "node_modules/typescript-eslint": { - "version": "8.60.1", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.60.1.tgz", - "integrity": "sha512-6m5hkkRAp8lKvhVpcprAIn5KkehQEh+47oHH2VGnExEh7dhNxXlg6GPAOIu6TxbVQxhebrJDvjl3020ooiWCMA==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.61.0.tgz", + "integrity": "sha512-8y31Rd0eGTrDKqhy6vT0HtzhN+YLjQizwX3aA3hPXP/ynSfnrBXcQY5IzsP9/DM7+klX4IUncZZjkchP0z+rUw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.60.1", - "@typescript-eslint/parser": "8.60.1", - "@typescript-eslint/typescript-estree": "8.60.1", - "@typescript-eslint/utils": "8.60.1" + "@typescript-eslint/eslint-plugin": "8.61.0", + "@typescript-eslint/parser": "8.61.0", + "@typescript-eslint/typescript-estree": "8.61.0", + "@typescript-eslint/utils": "8.61.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -5291,9 +5325,9 @@ "license": "MIT" }, "node_modules/undici": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.27.1.tgz", - "integrity": "sha512-UDdpiex+mzigiyrXrGbiUaF4HzTNhKbh2vRNFaTMzcqmLIPrZxaCtwo/1TMSuWoM1Xz3WiTo9KdgI3kRqYzJGg==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.27.2.tgz", + "integrity": "sha512-uZsKNuzQxDMUY6M3pIMvy5tvlGmtq8XJ2oLAkfRKGNu+1VQAIvLy2xIVG5ATZl5wDXl/tddByAWCizRbOme+TA==", "dev": true, "license": "MIT", "engines": { @@ -5649,9 +5683,9 @@ } }, "node_modules/vue-component-type-helpers": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/vue-component-type-helpers/-/vue-component-type-helpers-3.3.3.tgz", - "integrity": "sha512-x4nsFpy5Pe8fqPzp/5vkTPeTTDBpAx4WVtV47Ejt0+2FQrq4pRRsJs7JmYRqMFzTu/LW+pCWEjQ3YVCkPV7f9g==", + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/vue-component-type-helpers/-/vue-component-type-helpers-3.3.4.tgz", + "integrity": "sha512-joip1uZTaQR0nD23N400gIdJ7xY+WiiiMA/BCKz842gvGBknqDQAzklUvDEhqFvvrhQY8S2ZANBMu4X70VMFGw==", "dev": true, "license": "MIT" }, diff --git a/client-v3/package.json b/client-v3/package.json index fcda5dfa1..3c763bfd7 100644 --- a/client-v3/package.json +++ b/client-v3/package.json @@ -42,7 +42,7 @@ "d3-zoom": "^3.0.0", "deep-object-diff": "1.1.9", "dompurify": "^3.4.8", - "fuse.js": "^7.4.1", + "fuse.js": "^7.4.2", "lodash": "^4.18.1", "loglevel": "^1.9.2", "marked": "^18.0.5", @@ -55,14 +55,14 @@ "vue-toast-notification": "^3.1.3" }, "devDependencies": { - "@emnapi/core": "1.10.0", - "@emnapi/runtime": "1.10.0", + "@emnapi/core": "1.11.0", + "@emnapi/runtime": "1.11.0", "@eslint/js": "^10.0.1", "@iconify-json/mdi": "^1.2.3", "@types/lodash": "~4.17.24", "@types/node": ">=22.12.0", - "@typescript-eslint/eslint-plugin": "^8.60.1", - "@typescript-eslint/parser": "^8.60.1", + "@typescript-eslint/eslint-plugin": "^8.61.0", + "@typescript-eslint/parser": "^8.61.0", "@vitejs/plugin-vue": "^6.0.7", "@vitest/ui": "^4.1.8", "@vue/test-utils": "^2.4.11", @@ -76,7 +76,7 @@ "prettier": "^3.8.3", "sass": "1.100.0", "typescript": "^6.0.3", - "typescript-eslint": "^8.60.1", + "typescript-eslint": "^8.61.0", "unplugin-icons": "^23.0.1", "unplugin-vue-components": "^32.1.0", "vite": "^8.0.16", diff --git a/client/package-lock.json b/client/package-lock.json index 259c91dc2..1a966cd8f 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -18,7 +18,7 @@ "d3-zoom": "^3.0.0", "deep-object-diff": "1.1.9", "dompurify": "3.4.8", - "fuse.js": "7.4.1", + "fuse.js": "7.4.2", "jquery": "3.7.1", "lodash": "4.18.1", "loglevel": "1.9.2", @@ -38,8 +38,8 @@ "@types/lodash": "~4.17.24", "@types/node": "~20.14.0", "@types/vuelidate": "^0.7.22", - "@typescript-eslint/eslint-plugin": "^8.60.1", - "@typescript-eslint/parser": "^8.60.1", + "@typescript-eslint/eslint-plugin": "^8.61.0", + "@typescript-eslint/parser": "^8.61.0", "@vitejs/plugin-vue2": "2.3.4", "@vitest/ui": "^4.1.8", "@vue/test-utils": "^2.4.11", @@ -53,7 +53,7 @@ "prettier": "^3.8.3", "sass": "1.100.0", "typescript": "^6.0.3", - "typescript-eslint": "^8.60.1", + "typescript-eslint": "^8.61.0", "vite": "^7.3.3", "vitest": "^4.1.8" }, @@ -1890,17 +1890,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.60.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.60.1.tgz", - "integrity": "sha512-JQ4S5GB0tfjO8BuJ4fcX+HodkzJjYBV+7OJ+wLygaX7OGQ7FudyHL4NSCA6ob+w3Yn+5MkKIozOwQhXeM7opVg==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.61.0.tgz", + "integrity": "sha512-bFNvl9ZczlVb+wR2Akszf3gHfKVj/8WanXaGJ3UstTA7brNKg0cNdk6X1Psu5V7MZ2oQtzZKOEzIUehaoxbDGw==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.60.1", - "@typescript-eslint/type-utils": "8.60.1", - "@typescript-eslint/utils": "8.60.1", - "@typescript-eslint/visitor-keys": "8.60.1", + "@typescript-eslint/scope-manager": "8.61.0", + "@typescript-eslint/type-utils": "8.61.0", + "@typescript-eslint/utils": "8.61.0", + "@typescript-eslint/visitor-keys": "8.61.0", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" @@ -1913,22 +1913,22 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.60.1", + "@typescript-eslint/parser": "^8.61.0", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/parser": { - "version": "8.60.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.60.1.tgz", - "integrity": "sha512-A0M6ua6H252bVjPvvtSgl2QA4+ET9S5Mtkb2GDyTxIhH/C4qDItT7RQNO5PhMC6NXGYXOR9dIalcDDgBKT7oFA==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.61.0.tgz", + "integrity": "sha512-5B7PfA2e1NQGCnDHd/0lW7W3gvp3d59Ryw54FYO8Uswxo9f6ikw3AZV+Xj/TvpImmpsiYyUqAfhC6kJID1jF6w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.60.1", - "@typescript-eslint/types": "8.60.1", - "@typescript-eslint/typescript-estree": "8.60.1", - "@typescript-eslint/visitor-keys": "8.60.1", + "@typescript-eslint/scope-manager": "8.61.0", + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/typescript-estree": "8.61.0", + "@typescript-eslint/visitor-keys": "8.61.0", "debug": "^4.4.3" }, "engines": { @@ -1944,14 +1944,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.60.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.60.1.tgz", - "integrity": "sha512-eXkTH2bxmXlqD1RnOPmLZ9ZM9D3VwSx04JOwBnP9RQ+yUA5a2Mu7SfW8uaV2Aon53NJzZlZYuX7tn91Izf+xaw==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.61.0.tgz", + "integrity": "sha512-DV42F7MLJO6Rax7SK1yg43tcnEfGUrurSpSxKuVX+a3RCTzBlH3fuxprrOJXKCJGAaw82xXocikJ0uQaqwXgGA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.60.1", - "@typescript-eslint/types": "^8.60.1", + "@typescript-eslint/tsconfig-utils": "^8.61.0", + "@typescript-eslint/types": "^8.61.0", "debug": "^4.4.3" }, "engines": { @@ -1966,14 +1966,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.60.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.60.1.tgz", - "integrity": "sha512-gvI5OQoptnxQnchOirukCuQ55svJSTuD/4k5+pC267xyBtYry748R9/c3tYUzb/iE6RZfllRz2lVulLCHkTm4w==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.61.0.tgz", + "integrity": "sha512-IWdXFHFSb6mlC3HPc7QsLDm5zYEbUla6trDEHf32D3/dnuUyXd87plScSNXSbm0/RxMvObpI17sv/EDTGrGZkA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.60.1", - "@typescript-eslint/visitor-keys": "8.60.1" + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/visitor-keys": "8.61.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1984,9 +1984,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.60.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.60.1.tgz", - "integrity": "sha512-nh8w4qAteiKuZu3pSSzG/yGKpw0OlkrKnzFmbVRenKaD4qc+7i1GrmZaLVkr8rk4uipiPGMOW4YsM6WmKZ5CvA==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.61.0.tgz", + "integrity": "sha512-O5Amvdv9ztMpxpf+vmFULGG78IE6Qwdr3bCGvqwG4nwc9H2qXkOYJJnRbRHyMkQTjv1d03olqwwwzHLMqpFePQ==", "dev": true, "license": "MIT", "engines": { @@ -2001,15 +2001,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.60.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.60.1.tgz", - "integrity": "sha512-sdwTrpjosW7ANQYJ39ZBF1ZyEMEGVB2UsikrserVM/30a/F1dTLnu9bGxEdosugyu5caigjLrR2qiD11asjI1A==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.61.0.tgz", + "integrity": "sha512-TuBiQYIkd97yBfInHCTKVYMbX4kvEmpOEuixIuzCU9p8BGT1SfyyO0d0IfDMbPIHcjn/hWnusUX5e8v5Xg+X8A==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.60.1", - "@typescript-eslint/typescript-estree": "8.60.1", - "@typescript-eslint/utils": "8.60.1", + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/typescript-estree": "8.61.0", + "@typescript-eslint/utils": "8.61.0", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, @@ -2026,9 +2026,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.60.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.60.1.tgz", - "integrity": "sha512-4h0tY8ppCkdCzcrl2YM5M3my0xsE1Tf8om3owEu5oPWmXwkKRmk0j0LGDzYBGUcAlesEbxBhazqu/K4cu3Ug7w==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.61.0.tgz", + "integrity": "sha512-9QTQpZ5Iin4CdIodfbDQFSeiSJKidgYJYug1P9CC2xWgUTvlmixViqDZNciMjwLBZyJnG4tGmPl97rVAFb1AJg==", "dev": true, "license": "MIT", "engines": { @@ -2040,16 +2040,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.60.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.60.1.tgz", - "integrity": "sha512-alpRkfG8hlVE5kdJW2GkfgDgXxold3e8e4l6EnmhRmRLbekgAPCCGDVD++sABy9FcgPFroq+uFcCSM1vR57Cew==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.61.0.tgz", + "integrity": "sha512-42zatd5qSvvcV1JdDBCLxYRznvP4eIHpPoZXdkPFnAmanA4FuZ5dibSnCBggY8hQnqajPpoGjXFdZ7fIJKQnlA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.60.1", - "@typescript-eslint/tsconfig-utils": "8.60.1", - "@typescript-eslint/types": "8.60.1", - "@typescript-eslint/visitor-keys": "8.60.1", + "@typescript-eslint/project-service": "8.61.0", + "@typescript-eslint/tsconfig-utils": "8.61.0", + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/visitor-keys": "8.61.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", @@ -2068,16 +2068,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.60.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.60.1.tgz", - "integrity": "sha512-h2MPBLoNtjc3qZWfY3Tl51yPorQ2McHn8pJfcMNTcIvrrZrr90Ykffit0yjrPFWQcRcUxzH20+6OcVdW4yHtUg==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.61.0.tgz", + "integrity": "sha512-3bzFt7ImFMW/jVYwJamDoe/dMOdFLSC6pom6rRjdh4SZJEYupyMzem8e7vKZLclLfpHjlwSAXOUxtKxGXUiLqA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.60.1", - "@typescript-eslint/types": "8.60.1", - "@typescript-eslint/typescript-estree": "8.60.1" + "@typescript-eslint/scope-manager": "8.61.0", + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/typescript-estree": "8.61.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2092,13 +2092,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.60.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.60.1.tgz", - "integrity": "sha512-EbGRQg4FhrmwLodl+t3JNAnXHWVr9Vp+Zl1QBZVPY4ByfkzIT8cX3K6QWODHtkIZqqJVEWvhHSx3v5PDHsaQag==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.61.0.tgz", + "integrity": "sha512-QVLZu3ZPQEE+HICQyAMZ2yLQhxf0meY/wx6Hx14YcTNj13JB3qHlX3lJ02L3fLGHgERRH71kvYDwiXIguT3AjQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.60.1", + "@typescript-eslint/types": "8.61.0", "eslint-visitor-keys": "^5.0.0" }, "engines": { @@ -3493,9 +3493,9 @@ } }, "node_modules/fuse.js": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-7.4.1.tgz", - "integrity": "sha512-AY7lKAXK71hi3WgUvDy6oZL67UEHOOtvCAwVdOXHyJd6ZzftBy7QqxuXt4HxmmAhYjmp/YCuOELZtIvAdlZ+fw==", + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-7.4.2.tgz", + "integrity": "sha512-LVbzjD4WA6UP5B1UnP8wuaXJiLnqMdM/E4fiJXTJ5haJ5b/MBNsK29h2fm6swEoQaVQjvYFWKLE2RanyZIoRVQ==", "license": "Apache-2.0", "engines": { "node": ">=10" @@ -4540,9 +4540,9 @@ } }, "node_modules/semver": { - "version": "7.8.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.2.tgz", - "integrity": "sha512-c8jsqUZm3omBOI66G90z1Dyw5z622G8oLG+omfsHBJf3CWQTlOcwOjvOG6wtiNfW6anKm/eA39LMwMtMez2TiQ==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.3.tgz", + "integrity": "sha512-wnilbGyMxzbY7dNOl7jpKbLSjcfeweJWU5j4+u5qW+6/wuGD9KzIGOyZnQVSBM9E7DtWaaH3CyHkppYrKYoxwg==", "dev": true, "license": "ISC", "bin": { @@ -4961,16 +4961,16 @@ } }, "node_modules/typescript-eslint": { - "version": "8.60.1", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.60.1.tgz", - "integrity": "sha512-6m5hkkRAp8lKvhVpcprAIn5KkehQEh+47oHH2VGnExEh7dhNxXlg6GPAOIu6TxbVQxhebrJDvjl3020ooiWCMA==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.61.0.tgz", + "integrity": "sha512-8y31Rd0eGTrDKqhy6vT0HtzhN+YLjQizwX3aA3hPXP/ynSfnrBXcQY5IzsP9/DM7+klX4IUncZZjkchP0z+rUw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.60.1", - "@typescript-eslint/parser": "8.60.1", - "@typescript-eslint/typescript-estree": "8.60.1", - "@typescript-eslint/utils": "8.60.1" + "@typescript-eslint/eslint-plugin": "8.61.0", + "@typescript-eslint/parser": "8.61.0", + "@typescript-eslint/typescript-estree": "8.61.0", + "@typescript-eslint/utils": "8.61.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -5185,9 +5185,9 @@ } }, "node_modules/vue-component-type-helpers": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/vue-component-type-helpers/-/vue-component-type-helpers-3.3.3.tgz", - "integrity": "sha512-x4nsFpy5Pe8fqPzp/5vkTPeTTDBpAx4WVtV47Ejt0+2FQrq4pRRsJs7JmYRqMFzTu/LW+pCWEjQ3YVCkPV7f9g==", + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/vue-component-type-helpers/-/vue-component-type-helpers-3.3.4.tgz", + "integrity": "sha512-joip1uZTaQR0nD23N400gIdJ7xY+WiiiMA/BCKz842gvGBknqDQAzklUvDEhqFvvrhQY8S2ZANBMu4X70VMFGw==", "dev": true, "license": "MIT" }, diff --git a/client/package.json b/client/package.json index 2152dd630..3cf9a111f 100644 --- a/client/package.json +++ b/client/package.json @@ -38,7 +38,7 @@ "d3-zoom": "^3.0.0", "deep-object-diff": "1.1.9", "dompurify": "3.4.8", - "fuse.js": "7.4.1", + "fuse.js": "7.4.2", "jquery": "3.7.1", "lodash": "4.18.1", "loglevel": "1.9.2", @@ -58,8 +58,8 @@ "@types/lodash": "~4.17.24", "@types/node": "~20.14.0", "@types/vuelidate": "^0.7.22", - "@typescript-eslint/eslint-plugin": "^8.60.1", - "@typescript-eslint/parser": "^8.60.1", + "@typescript-eslint/eslint-plugin": "^8.61.0", + "@typescript-eslint/parser": "^8.61.0", "@vitejs/plugin-vue2": "2.3.4", "@vitest/ui": "^4.1.8", "@vue/test-utils": "^2.4.11", @@ -73,7 +73,7 @@ "prettier": "^3.8.3", "sass": "1.100.0", "typescript": "^6.0.3", - "typescript-eslint": "^8.60.1", + "typescript-eslint": "^8.61.0", "vite": "^7.3.3", "vitest": "^4.1.8" }, diff --git a/electron/package-lock.json b/electron/package-lock.json index 4a93c7d1b..d216135a9 100644 --- a/electron/package-lock.json +++ b/electron/package-lock.json @@ -20,8 +20,8 @@ "@electron-forge/maker-zip": "^7.11.2", "@eslint/js": "^9.39.2", "@types/node": "^22.0.0", - "@typescript-eslint/eslint-plugin": "^8.60.1", - "@typescript-eslint/parser": "^8.60.1", + "@typescript-eslint/eslint-plugin": "^8.61.0", + "@typescript-eslint/parser": "^8.61.0", "electron": "^40.6.1", "eslint": "^9.39.2", "eslint-config-prettier": "^10.1.8", @@ -1537,9 +1537,9 @@ } }, "node_modules/@types/node": { - "version": "22.19.19", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.19.tgz", - "integrity": "sha512-dyh/xO2Fh5bYrfWaaqGrRQQGkNdmYw6AmaAUvYeUMNTWQtvb796ikLdmTchRmOlOiIJ1TDXfWgVx1QkUlQ6Hew==", + "version": "22.19.20", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.20.tgz", + "integrity": "sha512-6tELRwSDYWW9EdZhbeZmYGZ1/7Djkt+Ah3/ScEYT9cDord7UJzasR/4D3VONg9tQI5CDp+/CZC1AXj2pCFOvpw==", "dev": true, "license": "MIT", "dependencies": { @@ -1575,17 +1575,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.60.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.60.1.tgz", - "integrity": "sha512-JQ4S5GB0tfjO8BuJ4fcX+HodkzJjYBV+7OJ+wLygaX7OGQ7FudyHL4NSCA6ob+w3Yn+5MkKIozOwQhXeM7opVg==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.61.0.tgz", + "integrity": "sha512-bFNvl9ZczlVb+wR2Akszf3gHfKVj/8WanXaGJ3UstTA7brNKg0cNdk6X1Psu5V7MZ2oQtzZKOEzIUehaoxbDGw==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.60.1", - "@typescript-eslint/type-utils": "8.60.1", - "@typescript-eslint/utils": "8.60.1", - "@typescript-eslint/visitor-keys": "8.60.1", + "@typescript-eslint/scope-manager": "8.61.0", + "@typescript-eslint/type-utils": "8.61.0", + "@typescript-eslint/utils": "8.61.0", + "@typescript-eslint/visitor-keys": "8.61.0", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" @@ -1598,23 +1598,23 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.60.1", + "@typescript-eslint/parser": "^8.61.0", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/parser": { - "version": "8.60.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.60.1.tgz", - "integrity": "sha512-A0M6ua6H252bVjPvvtSgl2QA4+ET9S5Mtkb2GDyTxIhH/C4qDItT7RQNO5PhMC6NXGYXOR9dIalcDDgBKT7oFA==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.61.0.tgz", + "integrity": "sha512-5B7PfA2e1NQGCnDHd/0lW7W3gvp3d59Ryw54FYO8Uswxo9f6ikw3AZV+Xj/TvpImmpsiYyUqAfhC6kJID1jF6w==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@typescript-eslint/scope-manager": "8.60.1", - "@typescript-eslint/types": "8.60.1", - "@typescript-eslint/typescript-estree": "8.60.1", - "@typescript-eslint/visitor-keys": "8.60.1", + "@typescript-eslint/scope-manager": "8.61.0", + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/typescript-estree": "8.61.0", + "@typescript-eslint/visitor-keys": "8.61.0", "debug": "^4.4.3" }, "engines": { @@ -1630,14 +1630,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.60.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.60.1.tgz", - "integrity": "sha512-eXkTH2bxmXlqD1RnOPmLZ9ZM9D3VwSx04JOwBnP9RQ+yUA5a2Mu7SfW8uaV2Aon53NJzZlZYuX7tn91Izf+xaw==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.61.0.tgz", + "integrity": "sha512-DV42F7MLJO6Rax7SK1yg43tcnEfGUrurSpSxKuVX+a3RCTzBlH3fuxprrOJXKCJGAaw82xXocikJ0uQaqwXgGA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.60.1", - "@typescript-eslint/types": "^8.60.1", + "@typescript-eslint/tsconfig-utils": "^8.61.0", + "@typescript-eslint/types": "^8.61.0", "debug": "^4.4.3" }, "engines": { @@ -1652,14 +1652,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.60.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.60.1.tgz", - "integrity": "sha512-gvI5OQoptnxQnchOirukCuQ55svJSTuD/4k5+pC267xyBtYry748R9/c3tYUzb/iE6RZfllRz2lVulLCHkTm4w==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.61.0.tgz", + "integrity": "sha512-IWdXFHFSb6mlC3HPc7QsLDm5zYEbUla6trDEHf32D3/dnuUyXd87plScSNXSbm0/RxMvObpI17sv/EDTGrGZkA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.60.1", - "@typescript-eslint/visitor-keys": "8.60.1" + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/visitor-keys": "8.61.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1670,9 +1670,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.60.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.60.1.tgz", - "integrity": "sha512-nh8w4qAteiKuZu3pSSzG/yGKpw0OlkrKnzFmbVRenKaD4qc+7i1GrmZaLVkr8rk4uipiPGMOW4YsM6WmKZ5CvA==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.61.0.tgz", + "integrity": "sha512-O5Amvdv9ztMpxpf+vmFULGG78IE6Qwdr3bCGvqwG4nwc9H2qXkOYJJnRbRHyMkQTjv1d03olqwwwzHLMqpFePQ==", "dev": true, "license": "MIT", "engines": { @@ -1687,15 +1687,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.60.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.60.1.tgz", - "integrity": "sha512-sdwTrpjosW7ANQYJ39ZBF1ZyEMEGVB2UsikrserVM/30a/F1dTLnu9bGxEdosugyu5caigjLrR2qiD11asjI1A==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.61.0.tgz", + "integrity": "sha512-TuBiQYIkd97yBfInHCTKVYMbX4kvEmpOEuixIuzCU9p8BGT1SfyyO0d0IfDMbPIHcjn/hWnusUX5e8v5Xg+X8A==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.60.1", - "@typescript-eslint/typescript-estree": "8.60.1", - "@typescript-eslint/utils": "8.60.1", + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/typescript-estree": "8.61.0", + "@typescript-eslint/utils": "8.61.0", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, @@ -1712,9 +1712,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.60.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.60.1.tgz", - "integrity": "sha512-4h0tY8ppCkdCzcrl2YM5M3my0xsE1Tf8om3owEu5oPWmXwkKRmk0j0LGDzYBGUcAlesEbxBhazqu/K4cu3Ug7w==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.61.0.tgz", + "integrity": "sha512-9QTQpZ5Iin4CdIodfbDQFSeiSJKidgYJYug1P9CC2xWgUTvlmixViqDZNciMjwLBZyJnG4tGmPl97rVAFb1AJg==", "dev": true, "license": "MIT", "engines": { @@ -1726,16 +1726,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.60.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.60.1.tgz", - "integrity": "sha512-alpRkfG8hlVE5kdJW2GkfgDgXxold3e8e4l6EnmhRmRLbekgAPCCGDVD++sABy9FcgPFroq+uFcCSM1vR57Cew==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.61.0.tgz", + "integrity": "sha512-42zatd5qSvvcV1JdDBCLxYRznvP4eIHpPoZXdkPFnAmanA4FuZ5dibSnCBggY8hQnqajPpoGjXFdZ7fIJKQnlA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.60.1", - "@typescript-eslint/tsconfig-utils": "8.60.1", - "@typescript-eslint/types": "8.60.1", - "@typescript-eslint/visitor-keys": "8.60.1", + "@typescript-eslint/project-service": "8.61.0", + "@typescript-eslint/tsconfig-utils": "8.61.0", + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/visitor-keys": "8.61.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", @@ -1793,16 +1793,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.60.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.60.1.tgz", - "integrity": "sha512-h2MPBLoNtjc3qZWfY3Tl51yPorQ2McHn8pJfcMNTcIvrrZrr90Ykffit0yjrPFWQcRcUxzH20+6OcVdW4yHtUg==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.61.0.tgz", + "integrity": "sha512-3bzFt7ImFMW/jVYwJamDoe/dMOdFLSC6pom6rRjdh4SZJEYupyMzem8e7vKZLclLfpHjlwSAXOUxtKxGXUiLqA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.60.1", - "@typescript-eslint/types": "8.60.1", - "@typescript-eslint/typescript-estree": "8.60.1" + "@typescript-eslint/scope-manager": "8.61.0", + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/typescript-estree": "8.61.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1817,13 +1817,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.60.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.60.1.tgz", - "integrity": "sha512-EbGRQg4FhrmwLodl+t3JNAnXHWVr9Vp+Zl1QBZVPY4ByfkzIT8cX3K6QWODHtkIZqqJVEWvhHSx3v5PDHsaQag==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.61.0.tgz", + "integrity": "sha512-QVLZu3ZPQEE+HICQyAMZ2yLQhxf0meY/wx6Hx14YcTNj13JB3qHlX3lJ02L3fLGHgERRH71kvYDwiXIguT3AjQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.60.1", + "@typescript-eslint/types": "8.61.0", "eslint-visitor-keys": "^5.0.0" }, "engines": { @@ -2543,9 +2543,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001793", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001793.tgz", - "integrity": "sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA==", + "version": "1.0.30001797", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001797.tgz", + "integrity": "sha512-l8xKG+gwAIExZGl9FrF7KUwuOmk6wbEPC9Xoy/RtnWv1XG0Q4LFlagaLpUv3Kiza3W/wm27zy0yWJEieYKAP6w==", "dev": true, "funding": [ { @@ -3646,9 +3646,9 @@ } }, "node_modules/electron/node_modules/@types/node": { - "version": "24.13.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.13.0.tgz", - "integrity": "sha512-5vtOqGQr4NJKeEzV441FcOi2MeG9UTWq9LqVLGneDdu4vlX17H8kQ2PA2UmNwCUGPVDj4oBjNhS7ReVEIWJJrg==", + "version": "24.13.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.13.1.tgz", + "integrity": "sha512-RSpUJGmvsJ1ZeBehQZFhIdpsz+bIpES0nIQXko4Ybq+N+kX6XvOq3Jo+iJ82FWLdblFq85AsMikd3m35jgezYg==", "dev": true, "license": "MIT", "dependencies": { @@ -7009,9 +7009,9 @@ } }, "node_modules/semver": { - "version": "7.8.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.2.tgz", - "integrity": "sha512-c8jsqUZm3omBOI66G90z1Dyw5z622G8oLG+omfsHBJf3CWQTlOcwOjvOG6wtiNfW6anKm/eA39LMwMtMez2TiQ==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.3.tgz", + "integrity": "sha512-wnilbGyMxzbY7dNOl7jpKbLSjcfeweJWU5j4+u5qW+6/wuGD9KzIGOyZnQVSBM9E7DtWaaH3CyHkppYrKYoxwg==", "license": "ISC", "bin": { "semver": "bin/semver.js" diff --git a/electron/package.json b/electron/package.json index a4f6cae3b..7ee617267 100644 --- a/electron/package.json +++ b/electron/package.json @@ -37,8 +37,8 @@ "@electron-forge/maker-deb": "^7.11.2", "@electron-forge/maker-rpm": "^7.11.2", "@eslint/js": "^9.39.2", - "@typescript-eslint/eslint-plugin": "^8.60.1", - "@typescript-eslint/parser": "^8.60.1", + "@typescript-eslint/eslint-plugin": "^8.61.0", + "@typescript-eslint/parser": "^8.61.0", "@types/node": "^22.0.0", "eslint": "^9.39.2", "eslint-config-prettier": "^10.1.8", From 49dee54c98ec54766504d632afee0032108b3ac2 Mon Sep 17 00:00:00 2001 From: Tim Bradgate Date: Tue, 9 Jun 2026 01:29:51 +0100 Subject: [PATCH 2/7] Persist rows-per-page preferences per user across devices (#1175) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a table_page_sizes JSON column to UserSettings so each user's per-table pagination preference is stored server-side and follows them across devices (laptop during rehearsals → fixed station for live shows). The PATCH /api/v1/user/settings endpoint handles the new field automatically; the existing WS broadcast (GET_USER_SETTINGS) syncs changes to all open sessions for that user without any local state mutation. Co-authored-by: Claude Sonnet 4.6 --- .../src/components/config/ConfigShows.vue | 2 +- .../src/components/config/ConfigSystem.vue | 2 +- .../config/acts_and_scenes/ConfigActs.vue | 2 +- .../config/acts_and_scenes/ConfigScenes.vue | 2 +- .../config/characters/CharacterGroups.vue | 2 +- .../components/show/config/mics/MicList.vue | 2 +- .../config/script/StageDirectionStyles.vue | 2 +- .../show/config/sessions/SessionTagList.vue | 2 +- .../components/show/config/stage/CrewList.vue | 2 +- .../show/config/stage/PropsList.vue | 7 ++-- .../show/config/stage/SceneryList.vue | 10 ++++-- .../show/config/stage/StageManager.vue | 10 ++++-- .../user/settings/CueColourPreferences.vue | 2 +- .../user/settings/StageDirectionStyles.vue | 2 +- client-v3/src/composables/usePagination.ts | 17 +++++++-- client-v3/src/stores/user.ts | 9 +++++ client-v3/src/types/api/user.ts | 1 + .../src/views/show/config/ConfigCast.vue | 2 +- .../views/show/config/ConfigCharacters.vue | 2 +- .../src/views/show/config/ConfigCues.vue | 2 +- client/src/mixins/paginationMixin.ts | 26 +++++++++++++- client/src/store/modules/user/settings.ts | 13 +++++++ client/src/types/api/user.ts | 1 + client/src/views/show/config/ConfigCast.vue | 1 + .../views/show/config/ConfigCharacters.vue | 1 + client/src/views/show/config/ConfigCues.vue | 1 + .../src/vue_components/config/ConfigShows.vue | 1 + .../vue_components/config/ConfigSystem.vue | 1 + .../config/acts_and_scenes/ConfigActs.vue | 1 + .../config/acts_and_scenes/ConfigScenes.vue | 1 + .../config/characters/CharacterGroups.vue | 1 + .../show/config/mics/MicList.vue | 1 + .../config/script/StageDirectionStyles.vue | 5 +-- .../show/config/sessions/SessionTagList.vue | 1 + .../show/config/stage/CrewList.vue | 1 + .../show/config/stage/PropsList.vue | 10 +++++- .../show/config/stage/SceneryList.vue | 10 +++++- .../user/settings/CueColourPreferences.vue | 6 ++-- .../user/settings/StageDirectionStyles.vue | 5 +-- ...5_add_table_page_sizes_to_user_settings.py | 35 +++++++++++++++++++ server/models/user.py | 11 +++++- 41 files changed, 181 insertions(+), 34 deletions(-) create mode 100644 server/alembic_config/versions/390f0ab54425_add_table_page_sizes_to_user_settings.py diff --git a/client-v3/src/components/config/ConfigShows.vue b/client-v3/src/components/config/ConfigShows.vue index 62ca7a9d9..4da109e7d 100644 --- a/client-v3/src/components/config/ConfigShows.vue +++ b/client-v3/src/components/config/ConfigShows.vue @@ -143,7 +143,7 @@ const isSubmittingLoad = ref(false); const isSubmittingShow = ref(false); const isDeleting = ref(false); const deletingId = ref(null); -const { perPage, currentPage } = usePagination(); +const { perPage, currentPage } = usePagination(15, 'config_shows'); const showFields = [ { key: 'id', label: 'ID' }, diff --git a/client-v3/src/components/config/ConfigSystem.vue b/client-v3/src/components/config/ConfigSystem.vue index ecdb107a7..b10ba1da2 100644 --- a/client-v3/src/components/config/ConfigSystem.vue +++ b/client-v3/src/components/config/ConfigSystem.vue @@ -99,7 +99,7 @@ const { connectedSessions, versionStatus, serverInfo } = storeToRefs(systemStore const loading = ref(true); const isCheckingVersion = ref(false); -const { perPage, currentPage } = usePagination(); +const { perPage, currentPage } = usePagination(15, 'config_system_clients'); const clientsModal = ref>(); const clientFields = [ diff --git a/client-v3/src/components/show/config/acts_and_scenes/ConfigActs.vue b/client-v3/src/components/show/config/acts_and_scenes/ConfigActs.vue index 9bb104c4c..63c1ec04d 100644 --- a/client-v3/src/components/show/config/acts_and_scenes/ConfigActs.vue +++ b/client-v3/src/components/show/config/acts_and_scenes/ConfigActs.vue @@ -142,7 +142,7 @@ const showStore = useShowStore(); const { confirm } = useConfirm(); const loading = ref(true); -const { perPage, currentPage } = usePagination(); +const { perPage, currentPage } = usePagination(15, 'config_acts'); const submittingNewAct = ref(false); const submittingEditAct = ref(false); const deletingAct = ref(false); diff --git a/client-v3/src/components/show/config/acts_and_scenes/ConfigScenes.vue b/client-v3/src/components/show/config/acts_and_scenes/ConfigScenes.vue index 1d7680ffd..ae5ea4107 100644 --- a/client-v3/src/components/show/config/acts_and_scenes/ConfigScenes.vue +++ b/client-v3/src/components/show/config/acts_and_scenes/ConfigScenes.vue @@ -206,7 +206,7 @@ const showStore = useShowStore(); const { confirm } = useConfirm(); const loading = ref(true); -const { perPage, currentPage } = usePagination(); +const { perPage, currentPage } = usePagination(15, 'config_scenes'); const submittingNewScene = ref(false); const submittingEditScene = ref(false); const submittingFirstScene = ref(false); diff --git a/client-v3/src/components/show/config/characters/CharacterGroups.vue b/client-v3/src/components/show/config/characters/CharacterGroups.vue index 68a1f1956..cf7a2e41a 100644 --- a/client-v3/src/components/show/config/characters/CharacterGroups.vue +++ b/client-v3/src/components/show/config/characters/CharacterGroups.vue @@ -146,7 +146,7 @@ const showStore = useShowStore(); const { confirm } = useConfirm(); const loading = ref(true); -const { perPage, currentPage } = usePagination(); +const { perPage, currentPage } = usePagination(15, 'config_character_groups'); const submittingNewGroup = ref(false); const submittingEditGroup = ref(false); const deletingGroup = ref(false); diff --git a/client-v3/src/components/show/config/mics/MicList.vue b/client-v3/src/components/show/config/mics/MicList.vue index 005e886a1..4dca8a958 100644 --- a/client-v3/src/components/show/config/mics/MicList.vue +++ b/client-v3/src/components/show/config/mics/MicList.vue @@ -103,7 +103,7 @@ const systemStore = useSystemStore(); const { confirm } = useConfirm(); const { validationState } = useFormValidation(); -const { perPage, currentPage } = usePagination(); +const { perPage, currentPage } = usePagination(15, 'config_mics'); const isSubmitting = ref(false); const newModal = ref>(); diff --git a/client-v3/src/components/show/config/script/StageDirectionStyles.vue b/client-v3/src/components/show/config/script/StageDirectionStyles.vue index a23180d72..a38e660b4 100644 --- a/client-v3/src/components/show/config/script/StageDirectionStyles.vue +++ b/client-v3/src/components/show/config/script/StageDirectionStyles.vue @@ -156,7 +156,7 @@ const systemStore = useSystemStore(); const { confirm } = useConfirm(); const { validationState } = useFormValidation(); -const { perPage, currentPage } = usePagination(); +const { perPage, currentPage } = usePagination(15, 'show_stage_direction_styles'); const isSubmittingNew = ref(false); const isSubmittingEdit = ref(false); const isDeleting = ref(false); diff --git a/client-v3/src/components/show/config/sessions/SessionTagList.vue b/client-v3/src/components/show/config/sessions/SessionTagList.vue index a0e6b34b6..176edca8e 100644 --- a/client-v3/src/components/show/config/sessions/SessionTagList.vue +++ b/client-v3/src/components/show/config/sessions/SessionTagList.vue @@ -203,7 +203,7 @@ const systemStore = useSystemStore(); const showStore = useShowStore(); const { confirm } = useConfirm(); -const { perPage, currentPage } = usePagination(); +const { perPage, currentPage } = usePagination(15, 'config_session_tags'); const isSubmittingNewTag = ref(false); const isSubmittingEditTag = ref(false); const isSubmittingDeleteTag = ref(false); diff --git a/client-v3/src/components/show/config/stage/CrewList.vue b/client-v3/src/components/show/config/stage/CrewList.vue index b1be46b3d..ecdca5623 100644 --- a/client-v3/src/components/show/config/stage/CrewList.vue +++ b/client-v3/src/components/show/config/stage/CrewList.vue @@ -111,7 +111,7 @@ const systemStore = useSystemStore(); const { confirm } = useConfirm(); const { validationState } = useFormValidation(); -const { perPage, currentPage } = usePagination(); +const { perPage, currentPage } = usePagination(15, 'config_crew'); const isSubmitting = ref(false); const newModal = ref>(); diff --git a/client-v3/src/components/show/config/stage/PropsList.vue b/client-v3/src/components/show/config/stage/PropsList.vue index 7e65e62a3..2b167566a 100644 --- a/client-v3/src/components/show/config/stage/PropsList.vue +++ b/client-v3/src/components/show/config/stage/PropsList.vue @@ -220,8 +220,11 @@ const systemStore = useSystemStore(); const { confirm } = useConfirm(); const { validationState } = useFormValidation(); -const { perPage: propTypesPerPage, currentPage: currentPropTypesPage } = usePagination(); -const { perPage: propsPerPage, currentPage: currentPropsPage } = usePagination(); +const { perPage: propTypesPerPage, currentPage: currentPropTypesPage } = usePagination( + 15, + 'config_prop_types' +); +const { perPage: propsPerPage, currentPage: currentPropsPage } = usePagination(15, 'config_props'); const isSubmitting = ref(false); const newPropTypeModal = ref>(); diff --git a/client-v3/src/components/show/config/stage/SceneryList.vue b/client-v3/src/components/show/config/stage/SceneryList.vue index bad527bb5..6fe9ceaed 100644 --- a/client-v3/src/components/show/config/stage/SceneryList.vue +++ b/client-v3/src/components/show/config/stage/SceneryList.vue @@ -222,8 +222,14 @@ const systemStore = useSystemStore(); const { confirm } = useConfirm(); const { validationState } = useFormValidation(); -const { perPage: sceneryTypesPerPage, currentPage: currentSceneryTypesPage } = usePagination(); -const { perPage: sceneryPerPage, currentPage: currentSceneryPage } = usePagination(); +const { perPage: sceneryTypesPerPage, currentPage: currentSceneryTypesPage } = usePagination( + 15, + 'config_scenery_types' +); +const { perPage: sceneryPerPage, currentPage: currentSceneryPage } = usePagination( + 15, + 'config_scenery' +); const isSubmitting = ref(false); const newSceneryTypeModal = ref>(); diff --git a/client-v3/src/components/show/config/stage/StageManager.vue b/client-v3/src/components/show/config/stage/StageManager.vue index cbd298eda..7193c8834 100644 --- a/client-v3/src/components/show/config/stage/StageManager.vue +++ b/client-v3/src/components/show/config/stage/StageManager.vue @@ -450,8 +450,14 @@ const setExpanded = ref(false); const strikeExpanded = ref(false); const savingAssignment = ref(false); const newCrewSelections = ref>({}); -const { perPage: sceneryAllocPerPage, currentPage: currentSceneryAllocPage } = usePagination(); -const { perPage: propsAllocPerPage, currentPage: currentPropsAllocPage } = usePagination(); +const { perPage: sceneryAllocPerPage, currentPage: currentSceneryAllocPage } = usePagination( + 15, + 'config_stage_scenery_alloc' +); +const { perPage: propsAllocPerPage, currentPage: currentPropsAllocPage } = usePagination( + 15, + 'config_stage_props_alloc' +); const goToSceneModal = ref>(); const addSceneryModal = ref>(); diff --git a/client-v3/src/components/user/settings/CueColourPreferences.vue b/client-v3/src/components/user/settings/CueColourPreferences.vue index 8b36b354c..90e574383 100644 --- a/client-v3/src/components/user/settings/CueColourPreferences.vue +++ b/client-v3/src/components/user/settings/CueColourPreferences.vue @@ -187,7 +187,7 @@ const columns = [ { key: 'example', label: 'Example Cue Button' }, { key: 'btn', label: '' }, ]; -const { perPage, currentPage } = usePagination(); +const { perPage, currentPage } = usePagination(15, 'user_cue_colour_prefs'); const cueTypes = ref([]); const isSubmittingNew = ref(false); diff --git a/client-v3/src/components/user/settings/StageDirectionStyles.vue b/client-v3/src/components/user/settings/StageDirectionStyles.vue index a0bcc42ba..23cb536dd 100644 --- a/client-v3/src/components/user/settings/StageDirectionStyles.vue +++ b/client-v3/src/components/user/settings/StageDirectionStyles.vue @@ -273,7 +273,7 @@ const columns = [ { key: 'example', label: 'Example Stage Direction' }, { key: 'btn', label: '' }, ]; -const { perPage, currentPage } = usePagination(); +const { perPage, currentPage } = usePagination(15, 'user_stage_direction_styles'); const stageDirectionStyles = ref([]); const isSubmittingNew = ref(false); diff --git a/client-v3/src/composables/usePagination.ts b/client-v3/src/composables/usePagination.ts index 4a6e1ca30..9a37d38c8 100644 --- a/client-v3/src/composables/usePagination.ts +++ b/client-v3/src/composables/usePagination.ts @@ -1,4 +1,6 @@ import { ref, watch } from 'vue'; +import { useUserStore } from '@/stores/user'; +import type { UserSettings } from '@/types/api/user'; export const PER_PAGE_OPTIONS = [ { value: 10, text: '10' }, @@ -8,12 +10,21 @@ export const PER_PAGE_OPTIONS = [ { value: 0, text: 'All' }, ] as const; -export function usePagination(defaultPerPage = 15) { - const perPage = ref(defaultPerPage); +export function usePagination(defaultPerPage = 15, tableKey?: string) { + const userStore = useUserStore(); + + const storedValue = tableKey + ? ((userStore.userSettings as UserSettings).table_page_sizes?.[tableKey] ?? defaultPerPage) + : defaultPerPage; + + const perPage = ref(storedValue); const currentPage = ref(1); - watch(perPage, () => { + watch(perPage, (newValue) => { currentPage.value = 1; + if (tableKey) { + userStore.updateTablePageSize(tableKey, newValue); + } }); return { perPage, currentPage }; diff --git a/client-v3/src/stores/user.ts b/client-v3/src/stores/user.ts index ecf925e4c..728739f8d 100644 --- a/client-v3/src/stores/user.ts +++ b/client-v3/src/stores/user.ts @@ -246,6 +246,15 @@ export const useUserStore = defineStore('user', { } }, + async updateTablePageSize(tableKey: string, value: number): Promise { + const current = (this.userSettings as UserSettings).table_page_sizes ?? {}; + await fetch(makeURL('/api/v1/user/settings'), { + method: 'PATCH', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ table_page_sizes: { ...current, [tableKey]: value } }), + }); + }, + async setupTokenRefresh(): Promise { if (this.tokenRefreshInterval) clearInterval(this.tokenRefreshInterval); const refreshInterval = setInterval( diff --git a/client-v3/src/types/api/user.ts b/client-v3/src/types/api/user.ts index bdb8d3117..50eb57915 100644 --- a/client-v3/src/types/api/user.ts +++ b/client-v3/src/types/api/user.ts @@ -24,4 +24,5 @@ export interface UserSettings { character_mru_sort: boolean; character_combined_dropdown: boolean; preferred_ui: string | null; + table_page_sizes: Record | null; } diff --git a/client-v3/src/views/show/config/ConfigCast.vue b/client-v3/src/views/show/config/ConfigCast.vue index d3bc61316..eaeebb8a6 100644 --- a/client-v3/src/views/show/config/ConfigCast.vue +++ b/client-v3/src/views/show/config/ConfigCast.vue @@ -132,7 +132,7 @@ const systemStore = useSystemStore(); const showStore = useShowStore(); const { confirm } = useConfirm(); -const { perPage, currentPage } = usePagination(); +const { perPage, currentPage } = usePagination(15, 'config_cast'); const submittingNewCast = ref(false); const submittingEditCast = ref(false); const deletingCast = ref(false); diff --git a/client-v3/src/views/show/config/ConfigCharacters.vue b/client-v3/src/views/show/config/ConfigCharacters.vue index b72a6b604..5df0f2ffa 100644 --- a/client-v3/src/views/show/config/ConfigCharacters.vue +++ b/client-v3/src/views/show/config/ConfigCharacters.vue @@ -187,7 +187,7 @@ const systemStore = useSystemStore(); const showStore = useShowStore(); const { confirm } = useConfirm(); -const { perPage, currentPage } = usePagination(); +const { perPage, currentPage } = usePagination(15, 'config_characters'); const submittingNewCharacter = ref(false); const submittingEditCharacter = ref(false); const deletingCharacter = ref(false); diff --git a/client-v3/src/views/show/config/ConfigCues.vue b/client-v3/src/views/show/config/ConfigCues.vue index 9958698f9..14b5d0594 100644 --- a/client-v3/src/views/show/config/ConfigCues.vue +++ b/client-v3/src/views/show/config/ConfigCues.vue @@ -228,7 +228,7 @@ const systemStore = useSystemStore(); const showStore = useShowStore(); const { confirm } = useConfirm(); -const { perPage, currentPage } = usePagination(); +const { perPage, currentPage } = usePagination(15, 'config_cues'); const submittingNewCueType = ref(false); const submittingEditCueType = ref(false); const deletingCueType = ref(false); diff --git a/client/src/mixins/paginationMixin.ts b/client/src/mixins/paginationMixin.ts index 3ffd58a35..21dfe0c60 100644 --- a/client/src/mixins/paginationMixin.ts +++ b/client/src/mixins/paginationMixin.ts @@ -1,15 +1,39 @@ import { defineComponent } from 'vue'; +import type { UserSettings } from '@/types/api/user'; export default defineComponent({ data() { return { rowsPerPage: 15 as number, currentPage: 1 as number, + tableKey: '' as string, }; }, watch: { - rowsPerPage(this: { currentPage: number }) { + rowsPerPage( + this: { + currentPage: number; + tableKey: string; + $store: { dispatch: (a: string, p: unknown) => void }; + }, + newValue: number + ) { this.currentPage = 1; + if (this.tableKey) { + this.$store.dispatch('UPDATE_TABLE_PAGE_SIZE', { + tableKey: this.tableKey, + value: newValue, + }); + } }, }, + created() { + if (this.tableKey) { + const settings = this.$store.getters.USER_SETTINGS as UserSettings | null; + const stored = settings?.table_page_sizes?.[this.tableKey]; + if (stored != null) { + this.rowsPerPage = stored; + } + } + }, }); diff --git a/client/src/store/modules/user/settings.ts b/client/src/store/modules/user/settings.ts index 1b5a5c2cf..7386fcb57 100644 --- a/client/src/store/modules/user/settings.ts +++ b/client/src/store/modules/user/settings.ts @@ -47,6 +47,19 @@ const module: Module = { log.error('Unable to fetch user settings'); } }, + async UPDATE_TABLE_PAGE_SIZE( + context, + { tableKey, value }: { tableKey: string; value: number } + ) { + const current = + (context.state.userSettings as { table_page_sizes?: Record }) + .table_page_sizes ?? {}; + await fetch(makeURL('/api/v1/user/settings'), { + method: 'PATCH', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ table_page_sizes: { ...current, [tableKey]: value } }), + }); + }, async UPDATE_SETTINGS(context, payload) { context.commit('UPDATE_SETTINGS', payload); await context.dispatch('SETTINGS_CHANGED'); diff --git a/client/src/types/api/user.ts b/client/src/types/api/user.ts index d0ee62616..9795e389e 100644 --- a/client/src/types/api/user.ts +++ b/client/src/types/api/user.ts @@ -23,4 +23,5 @@ export interface UserSettings { console_log_level: string; character_mru_sort: boolean; character_combined_dropdown: boolean; + table_page_sizes: Record | null; } diff --git a/client/src/views/show/config/ConfigCast.vue b/client/src/views/show/config/ConfigCast.vue index e03a2fae6..aae0638f1 100644 --- a/client/src/views/show/config/ConfigCast.vue +++ b/client/src/views/show/config/ConfigCast.vue @@ -156,6 +156,7 @@ export default defineComponent({ mixins: [formValidationMixin, paginationMixin], data() { return { + tableKey: 'config_cast', castFields: ['first_name', 'last_name', { key: 'btn', label: '' }], newFormState: { firstName: '', diff --git a/client/src/views/show/config/ConfigCharacters.vue b/client/src/views/show/config/ConfigCharacters.vue index 0e846fa1a..750680c8f 100644 --- a/client/src/views/show/config/ConfigCharacters.vue +++ b/client/src/views/show/config/ConfigCharacters.vue @@ -213,6 +213,7 @@ export default defineComponent({ mixins: [formValidationMixin, paginationMixin], data() { return { + tableKey: 'config_characters', characterFields: [ 'name', 'description', diff --git a/client/src/views/show/config/ConfigCues.vue b/client/src/views/show/config/ConfigCues.vue index 1879e4ccc..c5984e1db 100644 --- a/client/src/views/show/config/ConfigCues.vue +++ b/client/src/views/show/config/ConfigCues.vue @@ -236,6 +236,7 @@ export default defineComponent({ mixins: [paginationMixin], data() { return { + tableKey: 'config_cues', cueTypeFields: ['prefix', 'description', 'colour', { key: 'btn', label: '' }], newCueTypeForm: { prefix: '', diff --git a/client/src/vue_components/config/ConfigShows.vue b/client/src/vue_components/config/ConfigShows.vue index 775ee5135..f84647163 100644 --- a/client/src/vue_components/config/ConfigShows.vue +++ b/client/src/vue_components/config/ConfigShows.vue @@ -157,6 +157,7 @@ export default defineComponent({ mixins: [paginationMixin], data() { return { + tableKey: 'config_shows', loaded: false, showFields: [ { key: 'id', label: 'ID' }, diff --git a/client/src/vue_components/config/ConfigSystem.vue b/client/src/vue_components/config/ConfigSystem.vue index d99453293..99586a5ab 100644 --- a/client/src/vue_components/config/ConfigSystem.vue +++ b/client/src/vue_components/config/ConfigSystem.vue @@ -118,6 +118,7 @@ export default defineComponent({ mixins: [paginationMixin], data() { return { + tableKey: 'config_system_clients', connectedClients: [] as unknown[], clientFields: [ { key: 'internal_id', label: 'UUID' }, diff --git a/client/src/vue_components/show/config/acts_and_scenes/ConfigActs.vue b/client/src/vue_components/show/config/acts_and_scenes/ConfigActs.vue index cbe583405..1be7d11c9 100644 --- a/client/src/vue_components/show/config/acts_and_scenes/ConfigActs.vue +++ b/client/src/vue_components/show/config/acts_and_scenes/ConfigActs.vue @@ -172,6 +172,7 @@ export default defineComponent({ mixins: [formValidationMixin, paginationMixin], data() { return { + tableKey: 'config_acts', loading: true, actFields: [ 'name', diff --git a/client/src/vue_components/show/config/acts_and_scenes/ConfigScenes.vue b/client/src/vue_components/show/config/acts_and_scenes/ConfigScenes.vue index 6b85b3df2..e2bb715c0 100644 --- a/client/src/vue_components/show/config/acts_and_scenes/ConfigScenes.vue +++ b/client/src/vue_components/show/config/acts_and_scenes/ConfigScenes.vue @@ -222,6 +222,7 @@ export default defineComponent({ mixins: [formValidationMixin, paginationMixin], data() { return { + tableKey: 'config_scenes', loading: true, sceneFields: [ 'name', diff --git a/client/src/vue_components/show/config/characters/CharacterGroups.vue b/client/src/vue_components/show/config/characters/CharacterGroups.vue index e21670363..ddadd42a9 100644 --- a/client/src/vue_components/show/config/characters/CharacterGroups.vue +++ b/client/src/vue_components/show/config/characters/CharacterGroups.vue @@ -175,6 +175,7 @@ export default defineComponent({ mixins: [formValidationMixin, paginationMixin], data() { return { + tableKey: 'config_character_groups', loading: true, characterGroupFields: ['name', 'description', 'characters', { key: 'btn', label: '' }], tempCharacterList: [] as any[], diff --git a/client/src/vue_components/show/config/mics/MicList.vue b/client/src/vue_components/show/config/mics/MicList.vue index ca502ed57..b45336996 100644 --- a/client/src/vue_components/show/config/mics/MicList.vue +++ b/client/src/vue_components/show/config/mics/MicList.vue @@ -147,6 +147,7 @@ export default defineComponent({ mixins: [paginationMixin], data() { return { + tableKey: 'config_mics', micFields: ['name', 'description', { key: 'btn', label: '' }], newMicrophoneForm: { name: '', diff --git a/client/src/vue_components/show/config/script/StageDirectionStyles.vue b/client/src/vue_components/show/config/script/StageDirectionStyles.vue index f48a71c9d..4024ea407 100644 --- a/client/src/vue_components/show/config/script/StageDirectionStyles.vue +++ b/client/src/vue_components/show/config/script/StageDirectionStyles.vue @@ -347,11 +347,14 @@ import { defineComponent } from 'vue'; import { mapGetters, mapActions } from 'vuex'; import { required } from 'vuelidate/lib/validators'; import log from 'loglevel'; +import paginationMixin from '@/mixins/paginationMixin'; export default defineComponent({ name: 'StageDirectionConfigs', + mixins: [paginationMixin], data() { return { + tableKey: 'show_stage_direction_styles', exampleText: 'Your stage direction will look like this when formatted in the script!', columns: [ 'description', @@ -363,8 +366,6 @@ export default defineComponent({ { key: 'example', label: 'Example Stage Direction' }, { key: 'btn', label: '' }, ], - rowsPerPage: 15, - currentPage: 1, newStyleFormState: { description: '', styleOptions: [ diff --git a/client/src/vue_components/show/config/sessions/SessionTagList.vue b/client/src/vue_components/show/config/sessions/SessionTagList.vue index 45c441a65..9583acddc 100644 --- a/client/src/vue_components/show/config/sessions/SessionTagList.vue +++ b/client/src/vue_components/show/config/sessions/SessionTagList.vue @@ -243,6 +243,7 @@ export default defineComponent({ mixins: [paginationMixin], data() { return { + tableKey: 'config_session_tags', tagFields: [ { key: 'tag', label: 'Tag' }, { key: 'session_count', label: 'Sessions' }, diff --git a/client/src/vue_components/show/config/stage/CrewList.vue b/client/src/vue_components/show/config/stage/CrewList.vue index cf0b2ff53..e0e9bf50b 100644 --- a/client/src/vue_components/show/config/stage/CrewList.vue +++ b/client/src/vue_components/show/config/stage/CrewList.vue @@ -128,6 +128,7 @@ export default defineComponent({ mixins: [formValidationMixin, paginationMixin], data() { return { + tableKey: 'config_crew', crewFields: ['first_name', 'last_name', { key: 'btn', label: '' }], newFormState: { firstName: '', diff --git a/client/src/vue_components/show/config/stage/PropsList.vue b/client/src/vue_components/show/config/stage/PropsList.vue index f5f632b13..d5cd8ef10 100644 --- a/client/src/vue_components/show/config/stage/PropsList.vue +++ b/client/src/vue_components/show/config/stage/PropsList.vue @@ -355,11 +355,19 @@ export default defineComponent({ ...mapGetters(['PROPS_LIST', 'PROP_TYPES', 'IS_SHOW_EDITOR', 'PROP_TYPE_BY_ID']), }, watch: { - rowsPerPage() { + rowsPerPage(newValue: number) { this.currentPropPage = 1; this.currentPropTypePage = 1; + (this as any).$store.dispatch('UPDATE_TABLE_PAGE_SIZE', { + tableKey: 'config_props', + value: newValue, + }); }, }, + created() { + const stored = (this as any).$store.getters.USER_SETTINGS?.table_page_sizes?.['config_props']; + if (stored != null) this.rowsPerPage = stored; + }, async mounted(): Promise { await Promise.all([(this as any).GET_PROP_TYPES(), (this as any).GET_PROPS_LIST()]); }, diff --git a/client/src/vue_components/show/config/stage/SceneryList.vue b/client/src/vue_components/show/config/stage/SceneryList.vue index e3025a1c1..b9153f5fc 100644 --- a/client/src/vue_components/show/config/stage/SceneryList.vue +++ b/client/src/vue_components/show/config/stage/SceneryList.vue @@ -363,11 +363,19 @@ export default defineComponent({ ...mapGetters(['SCENERY_LIST', 'SCENERY_TYPES', 'IS_SHOW_EDITOR', 'SCENERY_TYPE_BY_ID']), }, watch: { - rowsPerPage() { + rowsPerPage(newValue: number) { this.currentSceneryPage = 1; this.currentSceneryTypesPage = 1; + (this as any).$store.dispatch('UPDATE_TABLE_PAGE_SIZE', { + tableKey: 'config_scenery', + value: newValue, + }); }, }, + created() { + const stored = (this as any).$store.getters.USER_SETTINGS?.table_page_sizes?.['config_scenery']; + if (stored != null) this.rowsPerPage = stored; + }, async mounted(): Promise { await Promise.all([(this as any).GET_SCENERY_TYPES(), (this as any).GET_SCENERY_LIST()]); }, diff --git a/client/src/vue_components/user/settings/CueColourPreferences.vue b/client/src/vue_components/user/settings/CueColourPreferences.vue index 398d8e734..5baa08f3c 100644 --- a/client/src/vue_components/user/settings/CueColourPreferences.vue +++ b/client/src/vue_components/user/settings/CueColourPreferences.vue @@ -160,19 +160,19 @@ import { required } from 'vuelidate/lib/validators'; import { contrastColor } from 'contrast-color'; import log from 'loglevel'; import formValidationMixin from '@/mixins/formValidationMixin'; +import paginationMixin from '@/mixins/paginationMixin'; export default defineComponent({ name: 'CueColourPreferences', - mixins: [formValidationMixin], + mixins: [formValidationMixin, paginationMixin], data() { return { + tableKey: 'user_cue_colour_prefs', columns: [ 'description', { key: 'example', label: 'Example Cue Button' }, { key: 'btn', label: '' }, ], - rowsPerPage: 15, - currentPage: 1, newFormState: { cueTypeId: null as number | null, colour: '#FF0000', diff --git a/client/src/vue_components/user/settings/StageDirectionStyles.vue b/client/src/vue_components/user/settings/StageDirectionStyles.vue index 1ef427152..e07eff0b4 100644 --- a/client/src/vue_components/user/settings/StageDirectionStyles.vue +++ b/client/src/vue_components/user/settings/StageDirectionStyles.vue @@ -270,6 +270,7 @@ import { defineComponent } from 'vue'; import { mapGetters, mapActions } from 'vuex'; import { required } from 'vuelidate/lib/validators'; import log from 'loglevel'; +import paginationMixin from '@/mixins/paginationMixin'; interface StyleOption { caption: string; @@ -296,16 +297,16 @@ interface EditStyleFormState { export default defineComponent({ name: 'StageDirectionStyles', + mixins: [paginationMixin], data() { return { + tableKey: 'user_stage_direction_styles', exampleText: 'Your stage direction will look like this when formatted in the script!', columns: [ 'description', { key: 'example', label: 'Example Stage Direction' }, { key: 'btn', label: '' }, ], - rowsPerPage: 15, - currentPage: 1, newStyleFormState: { styleId: null as number | null, styleOptions: [ diff --git a/server/alembic_config/versions/390f0ab54425_add_table_page_sizes_to_user_settings.py b/server/alembic_config/versions/390f0ab54425_add_table_page_sizes_to_user_settings.py new file mode 100644 index 000000000..79f5cc328 --- /dev/null +++ b/server/alembic_config/versions/390f0ab54425_add_table_page_sizes_to_user_settings.py @@ -0,0 +1,35 @@ +"""Add table_page_sizes to user_settings + +Revision ID: 390f0ab54425 +Revises: 3f2343a8a936 +Create Date: 2026-06-09 01:05:20.965630 + +""" + +from typing import Sequence, Union + +import sqlalchemy as sa +from alembic import op + + +# revision identifiers, used by Alembic. +revision: str = "390f0ab54425" +down_revision: Union[str, None] = "3f2343a8a936" +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table("user_settings", schema=None) as batch_op: + batch_op.add_column(sa.Column("table_page_sizes", sa.JSON(), nullable=True)) + + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table("user_settings", schema=None) as batch_op: + batch_op.drop_column("table_page_sizes") + + # ### end Alembic commands ### diff --git a/server/models/user.py b/server/models/user.py index 4371dbb4a..e2ca83377 100644 --- a/server/models/user.py +++ b/server/models/user.py @@ -6,7 +6,15 @@ from functools import partial from typing import TYPE_CHECKING, List, Union -from sqlalchemy import CheckConstraint, ForeignKey, Integer, Text, TypeDecorator, select +from sqlalchemy import ( + JSON, + CheckConstraint, + ForeignKey, + Integer, + Text, + TypeDecorator, + select, +) from sqlalchemy.orm import Mapped, mapped_column, relationship from models.models import db @@ -91,6 +99,7 @@ class UserSettings(db.Model): character_mru_sort: Mapped[bool] = mapped_column(default=False) character_combined_dropdown: Mapped[bool] = mapped_column(default=False) preferred_ui: Mapped[str | None] = mapped_column(default=None) + table_page_sizes: Mapped[dict | None] = mapped_column(JSON, default=None) __table_args__ = ( CheckConstraint( From d45397e74bc936e6d41dd0b342f6b31252fbeeaf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Jun 2026 13:03:34 +0100 Subject: [PATCH 3/7] Bump tornado from 6.5.6 to 6.5.7 in /server (#1177) Bumps [tornado](https://github.com/tornadoweb/tornado) from 6.5.6 to 6.5.7. - [Changelog](https://github.com/tornadoweb/tornado/blob/master/docs/releases.rst) - [Commits](https://github.com/tornadoweb/tornado/compare/v6.5.6...v6.5.7) --- updated-dependencies: - dependency-name: tornado dependency-version: 6.5.7 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- server/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/requirements.txt b/server/requirements.txt index b0a944c13..d54a10bdc 100644 --- a/server/requirements.txt +++ b/server/requirements.txt @@ -1,4 +1,4 @@ -tornado==6.5.6 +tornado==6.5.7 sqlalchemy>=2.0.50,<2.1.0 python-dateutil==2.9.0.post0 marshmallow-sqlalchemy>=1.5.0 From 858814a863448981e33820390bccb2dba7c891a7 Mon Sep 17 00:00:00 2001 From: Tim Bradgate Date: Wed, 10 Jun 2026 15:15:08 +0100 Subject: [PATCH 4/7] Promote Vue 3 to default UI at /, demote Vue 2 to /ui-old/ (#1178) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Promote Vue 3 to default UI at /, demote Vue 2 to /ui-old/ - V3 now served as the catch-all at / with default_ui setting changed to "new" - V2 served at /ui-old/ with its own dedicated routes and static asset handler - Backend redirect logic moved to RootControllerV3: redirects / → /ui-old/ when default_ui == "old" - Both clients' vite base/outDir updated; V3 gains a clean plugin preserving ui-old/ - UI-switch nav links and preference redirects updated to new paths in both apps - E2E UI_BASE updated to reflect V3 now living at the server root Co-Authored-By: Claude Sonnet 4.6 * Move docs generation prebuild from V2 to V3 The docs prebuild (copy-docs.sh + generate-doc-manifest.ts) was in the V2 client, which used Vite's public/ copy mechanism to deposit docs into the outDir. When V2's outDir moved to server/static/ui-old/, docs were landing in ui-old/docs/ instead of server/static/docs/. V3 now owns docs generation since it builds to the server/static/ root. Scripts are copied to client-v3/scripts/ with a mkdir -p guard added for the previously-absent public/ directory in V3. Co-Authored-By: Claude Sonnet 4.6 * Fix CI failures: Prettier formatting and Dockerfile for new UI layout - Fix Prettier formatting in client-v3/src/App.vue (Switch to Classic UI nav item) - Move COPY /docs from build_v2 to build_v3 stage (V3 now owns docs generation) - Update build_v3 mkdir to /server/static (was /server/static/ui-new) - Update final COPY --from=build_v3 to copy from /server/static root (was /server/static/ui-new) Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Claude Sonnet 4.6 --- Dockerfile | 6 +- client-v3/e2e/helpers.ts | 2 +- client-v3/package.json | 1 + client-v3/scripts/copy-docs.sh | 16 +++ client-v3/scripts/generate-doc-manifest.ts | 135 +++++++++++++++++++++ client-v3/src/App.vue | 6 +- client-v3/src/router/index.ts | 2 +- client-v3/vite.config.ts | 27 ++++- client/package.json | 1 - client/src/App.vue | 4 +- client/vite.config.ts | 27 +---- server/controllers/controllers.py | 34 +++--- server/digi_server/app_server.py | 16 +-- server/digi_server/settings.py | 2 +- 14 files changed, 216 insertions(+), 63 deletions(-) create mode 100755 client-v3/scripts/copy-docs.sh create mode 100644 client-v3/scripts/generate-doc-manifest.ts diff --git a/Dockerfile b/Dockerfile index f1203f4cb..2bc14a033 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,17 +7,17 @@ COPY /client/.npmrc /client/.npmrc WORKDIR /client RUN npm ci COPY /client /client -COPY /docs /docs RUN npm run build FROM node:24-bookworm AS build_v3 -RUN mkdir -p /server/static/ui-new +RUN mkdir -p /server/static COPY /client-v3/package.json /client-v3/package.json COPY /client-v3/package-lock.json /client-v3/package-lock.json WORKDIR /client-v3 RUN npm ci COPY /client-v3 /client-v3 +COPY /docs /docs RUN npm run build FROM python:3.13-bookworm @@ -30,7 +30,7 @@ RUN apt install -y nano COPY /server /server COPY --from=build_v2 /server/static /server/static -COPY --from=build_v3 /server/static/ui-new /server/static/ui-new +COPY --from=build_v3 /server/static /server/static WORKDIR /server RUN mkdir conf EXPOSE 8080 diff --git a/client-v3/e2e/helpers.ts b/client-v3/e2e/helpers.ts index 3a694ab90..a9c0331b0 100644 --- a/client-v3/e2e/helpers.ts +++ b/client-v3/e2e/helpers.ts @@ -1,7 +1,7 @@ import type { Page } from '@playwright/test'; export const SERVER_PORT = 8888; -export const UI_BASE = `http://localhost:${SERVER_PORT}/ui-new`; +export const UI_BASE = `http://localhost:${SERVER_PORT}`; export const ADMIN_USERNAME = 'admin'; export const ADMIN_PASSWORD = 'testpassword'; diff --git a/client-v3/package.json b/client-v3/package.json index 3c763bfd7..7386cf92f 100644 --- a/client-v3/package.json +++ b/client-v3/package.json @@ -6,6 +6,7 @@ "private": true, "type": "module", "scripts": { + "prebuild": "scripts/copy-docs.sh && node --strip-types scripts/generate-doc-manifest.ts", "build": "vite build", "build:analyze": "vite build --mode analyze", "lint": "npm run format && npm run lint:eslint", diff --git a/client-v3/scripts/copy-docs.sh b/client-v3/scripts/copy-docs.sh new file mode 100755 index 000000000..962b1b3b1 --- /dev/null +++ b/client-v3/scripts/copy-docs.sh @@ -0,0 +1,16 @@ +#!/bin/bash +set -e + +DOCS_SOURCE="../docs" +DOCS_DEST="./public/docs" + +echo "Copying documentation assets..." + +# Remove existing docs and ensure parent dir exists +rm -rf "$DOCS_DEST" +mkdir -p "$(dirname "$DOCS_DEST")" + +# Copy docs directory +cp -r "$DOCS_SOURCE" "$DOCS_DEST" + +echo "Documentation assets copied successfully" diff --git a/client-v3/scripts/generate-doc-manifest.ts b/client-v3/scripts/generate-doc-manifest.ts new file mode 100644 index 000000000..fb2b41a57 --- /dev/null +++ b/client-v3/scripts/generate-doc-manifest.ts @@ -0,0 +1,135 @@ +#!/usr/bin/env node +import fs from 'fs'; +import path from 'path'; +import { fileURLToPath } from 'url'; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); + +const DOCS_DIR = path.join(__dirname, '../../docs'); +const OUTPUT_DIR = path.join(__dirname, '../public/docs'); +const MANIFEST_PATH = path.join(OUTPUT_DIR, 'manifest.json'); + +interface ManifestEntry { + title: string; + slug: string; + path: string; + category: string; + order: number; +} + +function generateSlug(filepath: string): string { + // pages/getting_started.md → getting-started + // pages/show_config/acts_and_scenes.md → show-config/acts-and-scenes + const withoutExt = filepath.replace(/\.md$/, ''); + const withoutPages = withoutExt.replace(/^pages\//, ''); + return withoutPages.replace(/_/g, '-'); +} + +function extractTitle(content: string, filepath: string): string { + const parts = filepath.split('/'); + + if (parts.length > 2) { + const h3Match = content.match(/^###\s+(.+)$/m); + if (h3Match) return h3Match[1]; + } + + const match = content.match(/^##?\s+(.+)$/m); + if (match) return match[1]; + + const filename = parts[parts.length - 1].replace(/\.md$/, ''); + return filename.replace(/_/g, ' ').replace(/\b\w/g, (c) => c.toUpperCase()); +} + +function extractCategory(relativePath: string): string { + const parts = relativePath.split('/'); + return parts.length > 2 ? parts[1] : 'root'; +} + +function extractMarkdownLinks(content: string): string[] { + // Extract all markdown links: [text](./path.md) or [text](path.md) + return [...content.matchAll(/\[([^\]]+)\]\(([^)]+\.md)\)/g)].map((m) => m[2]); +} + +function normalizeLink(currentFile: string, link: string): string { + const currentDir = path.dirname(currentFile); + return path.normalize(path.join(currentDir, link)).replace(/\\/g, '/'); +} + +function buildOrderFromLinks(docsDir: string): string[] { + const visited = new Set(); + const order: string[] = []; + + function traverse(relativePath: string): void { + if (visited.has(relativePath)) return; + + const fullPath = path.join(docsDir, relativePath); + if (!fs.existsSync(fullPath) || !fs.statSync(fullPath).isFile()) return; + + visited.add(relativePath); + order.push(relativePath); + + const content = fs.readFileSync(fullPath, 'utf8'); + for (const link of extractMarkdownLinks(content)) { + traverse(normalizeLink(relativePath, link)); + } + } + + traverse('index.md'); + return order; +} + +function walkDocs(dir: string, basePath = ''): Omit[] { + const manifest: Omit[] = []; + + if (!fs.existsSync(dir)) { + console.warn(`Warning: Directory ${dir} does not exist`); + return manifest; + } + + for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { + const fullPath = path.join(dir, entry.name); + const relativePath = path.join(basePath, entry.name); + + if (entry.isDirectory() && entry.name !== 'images') { + manifest.push(...walkDocs(fullPath, relativePath)); + } else if (entry.isFile() && entry.name.endsWith('.md')) { + const content = fs.readFileSync(fullPath, 'utf8'); + manifest.push({ + title: extractTitle(content, relativePath), + slug: generateSlug(relativePath), + path: relativePath.replace(/\\/g, '/'), + category: extractCategory(relativePath), + }); + } + } + + return manifest; +} + +if (!fs.existsSync(OUTPUT_DIR)) { + fs.mkdirSync(OUTPUT_DIR, { recursive: true }); +} + +console.log('Generating documentation manifest...'); + +const linkOrder = buildOrderFromLinks(DOCS_DIR); +console.log(`📊 Discovered ${linkOrder.length} documents via link traversal`); + +const orderMap = new Map(linkOrder.map((filePath, i) => [filePath, i])); + +const manifest: ManifestEntry[] = walkDocs(DOCS_DIR).map((entry) => ({ + ...entry, + order: orderMap.get(entry.path) ?? 999, +})); + +const filteredManifest = manifest + .filter((entry) => entry.path !== 'index.md') + .sort((a, b) => { + if (a.order !== b.order) return a.order - b.order; + if (a.category !== b.category) return a.category.localeCompare(b.category); + return a.title.localeCompare(b.title); + }); + +fs.writeFileSync(MANIFEST_PATH, JSON.stringify(filteredManifest, null, 2)); +console.log(`✅ Generated manifest with ${filteredManifest.length} documents (excluded index.md)`); +console.log(`📄 Manifest saved to: ${MANIFEST_PATH}`); diff --git a/client-v3/src/App.vue b/client-v3/src/App.vue index 78d0877df..e2aef2e7c 100644 --- a/client-v3/src/App.vue +++ b/client-v3/src/App.vue @@ -94,7 +94,9 @@ - Switch to Classic UI + + Switch to Classic UI + Help About @@ -273,7 +275,7 @@ async function loadInitialUserData(): Promise { await Promise.all([userStore.getCurrentRbac(), userStore.getUserSettings()]); const switching = new URLSearchParams(window.location.search).has('_switch'); if (!switching && (userStore.userSettings as UserSettings).preferred_ui === 'old') { - window.location.href = '/?_switch=1'; + window.location.href = '/ui-old/?_switch=1'; return false; } if (switching) { diff --git a/client-v3/src/router/index.ts b/client-v3/src/router/index.ts index 7f5930ed6..a26e47279 100644 --- a/client-v3/src/router/index.ts +++ b/client-v3/src/router/index.ts @@ -11,7 +11,7 @@ import NotFoundView from '@/views/NotFoundView.vue'; const isFileProtocol = typeof window !== 'undefined' && window.location.protocol === 'file:'; const router = createRouter({ - history: isFileProtocol ? createWebHashHistory() : createWebHistory('/ui-new/'), + history: isFileProtocol ? createWebHashHistory() : createWebHistory('/'), routes: [ { path: '/electron/server-selector', diff --git a/client-v3/vite.config.ts b/client-v3/vite.config.ts index e1baa54ba..33dc69132 100644 --- a/client-v3/vite.config.ts +++ b/client-v3/vite.config.ts @@ -1,11 +1,29 @@ import path from 'node:path'; -import { defineConfig } from 'vite'; +import fs from 'node:fs'; +import { defineConfig, type Plugin } from 'vite'; import vue from '@vitejs/plugin-vue'; import Components from 'unplugin-vue-components/vite'; import { BootstrapVueNextResolver } from 'bootstrap-vue-next'; import Icons from 'unplugin-icons/vite'; import IconsResolve from 'unplugin-icons/resolver'; +function cleanV3StaticPlugin(): Plugin { + return { + name: 'clean-v3-static', + buildStart() { + if (process.env.BUILD_TARGET === 'electron') return; + const outDir = path.resolve(__dirname, '../server/static'); + if (fs.existsSync(outDir)) { + for (const entry of fs.readdirSync(outDir)) { + if (entry !== 'ui-old') { + fs.rmSync(path.join(outDir, entry), { recursive: true, force: true }); + } + } + } + }, + }; +} + export default defineConfig({ plugins: [ vue(), @@ -17,13 +35,14 @@ export default defineConfig({ compiler: 'vue3', autoInstall: false, }), + cleanV3StaticPlugin(), ], - base: process.env.BUILD_TARGET === 'electron' ? './' : '/ui-new/', + base: process.env.BUILD_TARGET === 'electron' ? './' : '/', build: { outDir: - process.env.BUILD_TARGET === 'electron' ? './dist-electron' : '../server/static/ui-new/', + process.env.BUILD_TARGET === 'electron' ? './dist-electron' : '../server/static/', assetsDir: './assets', - emptyOutDir: true, + emptyOutDir: false, rollupOptions: { output: { manualChunks(id) { diff --git a/client/package.json b/client/package.json index 3cf9a111f..458e1b75a 100644 --- a/client/package.json +++ b/client/package.json @@ -6,7 +6,6 @@ "private": true, "type": "module", "scripts": { - "prebuild": "scripts/copy-docs.sh && node --strip-types scripts/generate-doc-manifest.ts", "build": "vite build", "build:analyze": "vite build --mode analyze", "lint": "npm run format && npm run lint:eslint", diff --git a/client/src/App.vue b/client/src/App.vue index b8b1d3030..1f2afc936 100644 --- a/client/src/App.vue +++ b/client/src/App.vue @@ -91,7 +91,7 @@ - Switch to New UI + Switch to New UI Help About @@ -329,7 +329,7 @@ export default defineComponent({ const userPref = (this as any).USER_SETTINGS?.preferred_ui as string | null | undefined; const systemDefault = (this as any).SETTINGS?.default_ui as string | undefined; if (userPref === 'new' || (userPref == null && systemDefault === 'new')) { - window.location.href = '/ui-new/'; + window.location.href = '/?_switch=1'; return; } } diff --git a/client/vite.config.ts b/client/vite.config.ts index 87157fa47..0cf9bb406 100644 --- a/client/vite.config.ts +++ b/client/vite.config.ts @@ -1,40 +1,21 @@ import path from 'node:path'; -import fs from 'node:fs'; -import { defineConfig, type Plugin } from 'vite'; +import { defineConfig } from 'vite'; import vue from '@vitejs/plugin-vue2'; -function cleanV2StaticPlugin(): Plugin { - return { - name: 'clean-v2-static', - buildStart() { - if (process.env.BUILD_TARGET === 'electron') return; - const outDir = path.resolve(__dirname, '../server/static'); - if (fs.existsSync(outDir)) { - for (const entry of fs.readdirSync(outDir)) { - if (entry !== 'ui-new') { - fs.rmSync(path.join(outDir, entry), { recursive: true, force: true }); - } - } - } - }, - }; -} - export default defineConfig({ plugins: [ vue(), - cleanV2StaticPlugin(), ], define: { 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development'), }, // Use relative paths ONLY for Electron builds (file:// protocol) // Use absolute paths for web server (prevents issues with nested routes) - base: process.env.BUILD_TARGET === 'electron' ? './' : '/', + base: process.env.BUILD_TARGET === 'electron' ? './' : '/ui-old/', build: { - outDir: process.env.BUILD_TARGET === 'electron' ? './dist-electron' : '../server/static/', + outDir: process.env.BUILD_TARGET === 'electron' ? './dist-electron' : '../server/static/ui-old/', assetsDir: './assets', - emptyOutDir: false, + emptyOutDir: true, minify: 'esbuild', cssMinify: 'esbuild', rollupOptions: { diff --git a/server/controllers/controllers.py b/server/controllers/controllers.py index f9d8f9880..d5b67150c 100644 --- a/server/controllers/controllers.py +++ b/server/controllers/controllers.py @@ -26,11 +26,26 @@ def import_all_controllers(): class RootController(BaseController): + def get(self, _path): + if is_frozen(): + full_path = get_resource_path(os.path.join("static", "ui-old", INDEX_HTML)) + else: + file_path = os.path.join( + os.path.abspath(os.path.dirname(__file__)), "..", "static", "ui-old" + ) + full_path = os.path.join(file_path, INDEX_HTML) + if not os.path.isfile(full_path): + raise HTTPError(404) + with open(full_path, "r", encoding="utf-8") as file: + self.write(file.read()) + + +class RootControllerV3(BaseController): async def get(self, path): if not path and not self.get_argument("_switch", None): default_ui = await self.application.digi_settings.get("default_ui") - if default_ui == "new": - self.redirect("/ui-new/") + if default_ui == "old": + self.redirect("/ui-old/") return if is_frozen(): # In PyInstaller mode, use resource path @@ -56,21 +71,6 @@ async def get(self, path): raise HTTPError(500) from e -class RootControllerV3(BaseController): - def get(self, _path): - if is_frozen(): - full_path = get_resource_path(os.path.join("static", "ui-new", INDEX_HTML)) - else: - file_path = os.path.join( - os.path.abspath(os.path.dirname(__file__)), "..", "static", "ui-new" - ) - full_path = os.path.join(file_path, INDEX_HTML) - if not os.path.isfile(full_path): - raise HTTPError(404) - with open(full_path, "r", encoding="utf-8") as file: - self.write(file.read()) - - class StaticController(BaseController): def get(self): self.set_header("Content-Type", "") diff --git a/server/digi_server/app_server.py b/server/digi_server/app_server.py index f118fe2a1..5b9cf6af8 100644 --- a/server/digi_server/app_server.py +++ b/server/digi_server/app_server.py @@ -242,8 +242,8 @@ class AlembicVersion(self._db.Model): if is_frozen(): static_files_path = get_resource_path(os.path.join("static", "assets")) docs_files_path = get_resource_path(os.path.join("static", "docs")) - ui_new_static_files_path = get_resource_path( - os.path.join("static", "ui-new", "assets") + ui_old_static_files_path = get_resource_path( + os.path.join("static", "ui-old", "assets") ) get_logger().info(f"Using packaged static files path: {static_files_path}") get_logger().info(f"Using packaged docs files path: {docs_files_path}") @@ -254,11 +254,11 @@ class AlembicVersion(self._db.Model): docs_files_path = os.path.join( os.path.abspath(os.path.dirname(__file__)), "..", "static", "docs" ) - ui_new_static_files_path = os.path.join( + ui_old_static_files_path = os.path.join( os.path.abspath(os.path.dirname(__file__)), "..", "static", - "ui-new", + "ui-old", "assets", ) get_logger().info(f"Using relative static files path: {static_files_path}") @@ -271,15 +271,15 @@ class AlembicVersion(self._db.Model): ) handlers.append( ( - r"/ui-new/assets/(.*)", + r"/ui-old/assets/(.*)", StaticFileHandler, - {"path": ui_new_static_files_path}, + {"path": ui_old_static_files_path}, ) ) handlers.append((r"/docs/(.*)", StaticFileHandler, {"path": docs_files_path})) handlers.append((r"/api/.*", controllers.ApiFallback)) - handlers.append((r"/ui-new(/?.*)", controllers.RootControllerV3)) - handlers.append((r"/(.*)", controllers.RootController)) + handlers.append((r"/ui-old(/?.*)", controllers.RootController)) + handlers.append((r"/(.*)", controllers.RootControllerV3)) super().__init__( handlers=handlers, debug=debug, diff --git a/server/digi_server/settings.py b/server/digi_server/settings.py index 0fb13092a..6d32643f3 100644 --- a/server/digi_server/settings.py +++ b/server/digi_server/settings.py @@ -209,7 +209,7 @@ def init_settings(self): self.define( "default_ui", str, - "old", + "new", True, display_name="Default UI Version", help_text="Which UI version users are directed to by default. User preferences override this.", From 9c2d062c7d1d478bb4be6211d84cf775bf9be1cc Mon Sep 17 00:00:00 2001 From: Tim Bradgate Date: Wed, 10 Jun 2026 15:37:14 +0100 Subject: [PATCH 5/7] Add hover highlighting to live view cue add buttons (#1186) Replicates the :has() CSS pattern from the config cue/script editors to the live show view. When cue edit mode is active, hovering the add-cue button applies a faint white overlay to the script row. Applied to the inner content row (not the root container) to avoid conflicting with the existing .current-line blue highlight. Updated all four components: standard and compact viewers in both the Vue 2 and Vue 3 clients. Co-authored-by: Claude Sonnet 4.6 --- .../components/show/live/ScriptLineViewer.vue | 11 ++++++++-- .../show/live/ScriptLineViewerCompact.vue | 20 +++++++++++++++---- .../show/live/ScriptLineViewer.vue | 11 ++++++++-- .../show/live/ScriptLineViewerCompact.vue | 14 +++++++++---- 4 files changed, 44 insertions(+), 12 deletions(-) diff --git a/client-v3/src/components/show/live/ScriptLineViewer.vue b/client-v3/src/components/show/live/ScriptLineViewer.vue index 3c8a10ea9..063772a31 100644 --- a/client-v3/src/components/show/live/ScriptLineViewer.vue +++ b/client-v3/src/components/show/live/ScriptLineViewer.vue @@ -64,6 +64,7 @@ @@ -170,7 +171,7 @@ @@ -439,6 +440,12 @@ onUnmounted(() => { padding: 0.2rem; } +.line-row:has(.add-cue-btn:hover) { + background-color: rgba(255, 255, 255, 0.06); + border-radius: 4px; + transition: background-color 0.15s ease; +} + .stage-direction { margin-top: 1rem; margin-bottom: 1rem; diff --git a/client-v3/src/components/show/live/ScriptLineViewerCompact.vue b/client-v3/src/components/show/live/ScriptLineViewerCompact.vue index a5d350854..bb0883823 100644 --- a/client-v3/src/components/show/live/ScriptLineViewerCompact.vue +++ b/client-v3/src/components/show/live/ScriptLineViewerCompact.vue @@ -56,7 +56,7 @@ - + @@ -175,7 +176,7 @@ @@ -393,6 +394,12 @@ export default defineComponent({ padding: 0.2rem; } +.line-row:has(.add-cue-btn:hover) { + background-color: rgba(255, 255, 255, 0.06); + border-radius: 4px; + transition: background-color 0.15s ease; +} + .stage-direction { margin-top: 1rem; margin-bottom: 1rem; diff --git a/client/src/vue_components/show/live/ScriptLineViewerCompact.vue b/client/src/vue_components/show/live/ScriptLineViewerCompact.vue index c447b9b73..81f198df4 100644 --- a/client/src/vue_components/show/live/ScriptLineViewerCompact.vue +++ b/client/src/vue_components/show/live/ScriptLineViewerCompact.vue @@ -70,7 +70,7 @@ - +