diff --git a/frontend/package-lock.json b/frontend/package-lock.json index edd99202..5184cceb 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -16,11 +16,7 @@ "@mantine/hooks": "^7.17.2", "@mantine/notifications": "^7.17.2", "@tabler/icons-react": "^3.31.0", -<<<<<<< Updated upstream "@tanstack/react-table": "^8.21.2", -======= - "@tanstack/react-table": "^8.21.3", ->>>>>>> Stashed changes "allotment": "^1.20.3", "axios": "^1.8.2", "clsx": "^2.1.1", @@ -343,278 +339,6 @@ "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==", "license": "MIT" }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.1.tgz", - "integrity": "sha512-kfYGy8IdzTGy+z0vFGvExZtxkFlA4zAxgKEahG9KE1ScBjpQnFsNOX8KTU5ojNru5ed5CVoJYXFtoxaq5nFbjQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.1.tgz", - "integrity": "sha512-dp+MshLYux6j/JjdqVLnMglQlFu+MuVeNrmT5nk6q07wNhCdSnB7QZj+7G8VMUGh1q+vj2Bq8kRsuyA00I/k+Q==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.1.tgz", - "integrity": "sha512-50tM0zCJW5kGqgG7fQ7IHvQOcAn9TKiVRuQ/lN0xR+T2lzEFvAi1ZcS8DiksFcEpf1t/GYOeOfCAgDHFpkiSmA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.1.tgz", - "integrity": "sha512-GCj6WfUtNldqUzYkN/ITtlhwQqGWu9S45vUXs7EIYf+7rCiiqH9bCloatO9VhxsL0Pji+PF4Lz2XXCES+Q8hDw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.1.tgz", - "integrity": "sha512-5hEZKPf+nQjYoSr/elb62U19/l1mZDdqidGfmFutVUjjUZrOazAtwK+Kr+3y0C/oeJfLlxo9fXb1w7L+P7E4FQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.1.tgz", - "integrity": "sha512-hxVnwL2Dqs3fM1IWq8Iezh0cX7ZGdVhbTfnOy5uURtao5OIVCEyj9xIzemDi7sRvKsuSdtCAhMKarxqtlyVyfA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.1.tgz", - "integrity": "sha512-1MrCZs0fZa2g8E+FUo2ipw6jw5qqQiH+tERoS5fAfKnRx6NXH31tXBKI3VpmLijLH6yriMZsxJtaXUyFt/8Y4A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.1.tgz", - "integrity": "sha512-0IZWLiTyz7nm0xuIs0q1Y3QWJC52R8aSXxe40VUxm6BB1RNmkODtW6LHvWRrGiICulcX7ZvyH6h5fqdLu4gkww==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.1.tgz", - "integrity": "sha512-NdKOhS4u7JhDKw9G3cY6sWqFcnLITn6SqivVArbzIaf3cemShqfLGHYMx8Xlm/lBit3/5d7kXvriTUGa5YViuQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.1.tgz", - "integrity": "sha512-jaN3dHi0/DDPelk0nLcXRm1q7DNJpjXy7yWaWvbfkPvI+7XNSc/lDOnCLN7gzsyzgu6qSAmgSvP9oXAhP973uQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.1.tgz", - "integrity": "sha512-OJykPaF4v8JidKNGz8c/q1lBO44sQNUQtq1KktJXdBLn1hPod5rE/Hko5ugKKZd+D2+o1a9MFGUEIUwO2YfgkQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.1.tgz", - "integrity": "sha512-nGfornQj4dzcq5Vp835oM/o21UMlXzn79KobKlcs3Wz9smwiifknLy4xDCLUU0BWp7b/houtdrgUz7nOGnfIYg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.1.tgz", - "integrity": "sha512-1osBbPEFYwIE5IVB/0g2X6i1qInZa1aIoj1TdL4AaAb55xIIgbg8Doq6a5BzYWgr+tEcDzYH67XVnTmUzL+nXg==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.1.tgz", - "integrity": "sha512-/6VBJOwUf3TdTvJZ82qF3tbLuWsscd7/1w+D9LH0W/SqUgM5/JJD0lrJ1fVIfZsqB6RFmLCe0Xz3fmZc3WtyVg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.1.tgz", - "integrity": "sha512-nSut/Mx5gnilhcq2yIMLMe3Wl4FK5wx/o0QuuCLMtmJn+WeWYoEGDN1ipcN72g1WHsnIbxGXd4i/MF0gTcuAjQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.1.tgz", - "integrity": "sha512-cEECeLlJNfT8kZHqLarDBQso9a27o2Zd2AQ8USAEoGtejOrCYHNtKP8XQhMDJMtthdF4GBmjR2au3x1udADQQQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, "node_modules/@esbuild/linux-x64": { "version": "0.25.1", "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.1.tgz", @@ -632,142 +356,6 @@ "node": ">=18" } }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.1.tgz", - "integrity": "sha512-O96poM2XGhLtpTh+s4+nP7YCCAfb4tJNRVZHfIE7dgmax+yMP2WgMd2OecBuaATHKTHsLWHQeuaxMRnCsH8+5g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.1.tgz", - "integrity": "sha512-X53z6uXip6KFXBQ+Krbx25XHV/NCbzryM6ehOAeAil7X7oa4XIq+394PWGnwaSQ2WRA0KI6PUO6hTO5zeF5ijA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.1.tgz", - "integrity": "sha512-Na9T3szbXezdzM/Kfs3GcRQNjHzM6GzFBeU1/6IV/npKP5ORtp9zbQjvkDJ47s6BCgaAZnnnu/cY1x342+MvZg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.1.tgz", - "integrity": "sha512-T3H78X2h1tszfRSf+txbt5aOp/e7TAz3ptVKu9Oyir3IAOFPGV6O9c2naym5TOriy1l0nNf6a4X5UXRZSGX/dw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.1.tgz", - "integrity": "sha512-2H3RUvcmULO7dIE5EWJH8eubZAI4xw54H1ilJnRNZdeo8dTADEZ21w6J22XBkXqGJbe0+wnNJtw3UXRoLJnFEg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.1.tgz", - "integrity": "sha512-GE7XvrdOzrb+yVKB9KsRMq+7a2U/K5Cf/8grVFRAGJmfADr/e/ODQ134RK2/eeHqYV5eQRFxb1hY7Nr15fv1NQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.1.tgz", - "integrity": "sha512-uOxSJCIcavSiT6UnBhBzE8wy3n0hOkJsBOzy7HDAuTDE++1DJMRRVCPGisULScHL+a/ZwdXPpXD3IyFKjA7K8A==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.1.tgz", - "integrity": "sha512-Y1EQdcfwMSeQN/ujR5VayLOJ1BHaK+ssyk0AEzPjC+t1lITgsnccPqFjb6V+LsTp/9Iov4ysfjxLaGJ9RPtkVg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, "node_modules/@eslint-community/eslint-utils": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.5.0.tgz", @@ -1212,202 +800,6 @@ "url": "https://opencollective.com/popperjs" } }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.35.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.35.0.tgz", - "integrity": "sha512-uYQ2WfPaqz5QtVgMxfN6NpLD+no0MYHDBywl7itPYd3K5TjjSghNKmX8ic9S8NU8w81NVhJv/XojcHptRly7qQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.35.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.35.0.tgz", - "integrity": "sha512-FtKddj9XZudurLhdJnBl9fl6BwCJ3ky8riCXjEw3/UIbjmIY58ppWwPEvU3fNu+W7FUsAsB1CdH+7EQE6CXAPA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.35.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.35.0.tgz", - "integrity": "sha512-Uk+GjOJR6CY844/q6r5DR/6lkPFOw0hjfOIzVx22THJXMxktXG6CbejseJFznU8vHcEBLpiXKY3/6xc+cBm65Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.35.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.35.0.tgz", - "integrity": "sha512-3IrHjfAS6Vkp+5bISNQnPogRAW5GAV1n+bNCrDwXmfMHbPl5EhTmWtfmwlJxFRUCBZ+tZ/OxDyU08aF6NI/N5Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.35.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.35.0.tgz", - "integrity": "sha512-sxjoD/6F9cDLSELuLNnY0fOrM9WA0KrM0vWm57XhrIMf5FGiN8D0l7fn+bpUeBSU7dCgPV2oX4zHAsAXyHFGcQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.35.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.35.0.tgz", - "integrity": "sha512-2mpHCeRuD1u/2kruUiHSsnjWtHjqVbzhBkNVQ1aVD63CcexKVcQGwJ2g5VphOd84GvxfSvnnlEyBtQCE5hxVVw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.35.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.35.0.tgz", - "integrity": "sha512-mrA0v3QMy6ZSvEuLs0dMxcO2LnaCONs1Z73GUDBHWbY8tFFocM6yl7YyMu7rz4zS81NDSqhrUuolyZXGi8TEqg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.35.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.35.0.tgz", - "integrity": "sha512-DnYhhzcvTAKNexIql8pFajr0PiDGrIsBYPRvCKlA5ixSS3uwo/CWNZxB09jhIapEIg945KOzcYEAGGSmTSpk7A==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.35.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.35.0.tgz", - "integrity": "sha512-uagpnH2M2g2b5iLsCTZ35CL1FgyuzzJQ8L9VtlJ+FckBXroTwNOaD0z0/UF+k5K3aNQjbm8LIVpxykUOQt1m/A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.35.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.35.0.tgz", - "integrity": "sha512-XQxVOCd6VJeHQA/7YcqyV0/88N6ysSVzRjJ9I9UA/xXpEsjvAgDTgH3wQYz5bmr7SPtVK2TsP2fQ2N9L4ukoUg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.35.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.35.0.tgz", - "integrity": "sha512-5pMT5PzfgwcXEwOaSrqVsz/LvjDZt+vQ8RT/70yhPU06PTuq8WaHhfT1LW+cdD7mW6i/J5/XIkX/1tCAkh1W6g==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.35.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.35.0.tgz", - "integrity": "sha512-c+zkcvbhbXF98f4CtEIP1EBA/lCic5xB0lToneZYvMeKu5Kamq3O8gqrxiYYLzlZH6E3Aq+TSW86E4ay8iD8EA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.35.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.35.0.tgz", - "integrity": "sha512-s91fuAHdOwH/Tad2tzTtPX7UZyytHIRR6V4+2IGlV0Cej5rkG0R61SX4l4y9sh0JBibMiploZx3oHKPnQBKe4g==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.35.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.35.0.tgz", - "integrity": "sha512-hQRkPQPLYJZYGP+Hj4fR9dDBMIM7zrzJDWFEMPdTnTy95Ljnv0/4w/ixFw3pTBMEuuEuoqtBINYND4M7ujcuQw==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, "node_modules/@rollup/rollup-linux-x64-gnu": { "version": "4.35.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.35.0.tgz", @@ -1436,48 +828,6 @@ "linux" ] }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.35.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.35.0.tgz", - "integrity": "sha512-OUOlGqPkVJCdJETKOCEf1mw848ZyJ5w50/rZ/3IBQVdLfR5jk/6Sr5m3iO2tdPgwo0x7VcncYuOvMhBWZq8ayg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.35.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.35.0.tgz", - "integrity": "sha512-2/lsgejMrtwQe44glq7AFFHLfJBPafpsTa6JvP2NGef/ifOa4KBoglVf7AKN7EV9o32evBPRqfg96fEHzWo5kw==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.35.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.35.0.tgz", - "integrity": "sha512-PIQeY5XDkrOysbQblSW7v3l1MDZzkTEzAfTPkj5VAu3FW8fS4ynyLg2sINp0fp3SjZ8xkRYpLqoKcYqAkhU1dw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, "node_modules/@swc/core": { "version": "1.11.8", "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.11.8.tgz", @@ -1517,91 +867,6 @@ } } }, - "node_modules/@swc/core-darwin-arm64": { - "version": "1.11.8", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.11.8.tgz", - "integrity": "sha512-rrSsunyJWpHN+5V1zumndwSSifmIeFQBK9i2RMQQp15PgbgUNxHK5qoET1n20pcUrmZeT6jmJaEWlQchkV//Og==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-darwin-x64": { - "version": "1.11.8", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.11.8.tgz", - "integrity": "sha512-44goLqQuuo0HgWnG8qC+ZFw/qnjCVVeqffhzFr9WAXXotogVaxM8ze6egE58VWrfEc8me8yCcxOYL9RbtjhS/Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm-gnueabihf": { - "version": "1.11.8", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.11.8.tgz", - "integrity": "sha512-Mzo8umKlhTWwF1v8SLuTM1z2A+P43UVhf4R8RZDhzIRBuB2NkeyE+c0gexIOJBuGSIATryuAF4O4luDu727D1w==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.11.8", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.11.8.tgz", - "integrity": "sha512-EyhO6U+QdoGYC1MeHOR0pyaaSaKYyNuT4FQNZ1eZIbnuueXpuICC7iNmLIOfr3LE5bVWcZ7NKGVPlM2StJEcgA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.11.8", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.11.8.tgz", - "integrity": "sha512-QU6wOkZnS6/QuBN1MHD6G2BgFxB0AclvTVGbqYkRA7MsVkcC29PffESqzTXnypzB252/XkhQjoB2JIt9rPYf6A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, "node_modules/@swc/core-linux-x64-gnu": { "version": "1.11.8", "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.11.8.tgz", @@ -1636,57 +901,6 @@ "node": ">=10" } }, - "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.11.8", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.11.8.tgz", - "integrity": "sha512-EbjOzQ+B85rumHyeesBYxZ+hq3ZQn+YAAT1ZNE9xW1/8SuLoBmHy/K9YniRGVDq/2NRmp5kI5+5h5TX0asIS9A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.11.8", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.11.8.tgz", - "integrity": "sha512-Z+FF5kgLHfQWIZ1KPdeInToXLzbY0sMAashjd/igKeP1Lz0qKXVAK+rpn6ASJi85Fn8wTftCGCyQUkRVn0bTDg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.11.8", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.11.8.tgz", - "integrity": "sha512-j6B6N0hChCeAISS6xp/hh6zR5CSCr037BAjCxNLsT8TGe5D+gYZ57heswUWXRH8eMKiRDGiLCYpPB2pkTqxCSw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } - }, "node_modules/@swc/counter": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", @@ -1747,21 +961,12 @@ } }, "node_modules/@tanstack/react-table": { -<<<<<<< Updated upstream - "version": "8.21.2", - "resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.21.2.tgz", - "integrity": "sha512-11tNlEDTdIhMJba2RBH+ecJ9l1zgS2kjmexDPAraulc8jeNA4xocSNeyzextT0XJyASil4XsCYlJmf5jEWAtYg==", - "license": "MIT", - "dependencies": { - "@tanstack/table-core": "8.21.2" -======= "version": "8.21.3", "resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.21.3.tgz", "integrity": "sha512-5nNMTSETP4ykGegmVkhjcS8tTLW6Vl4axfEGQN3v0zdHYbK4UfoqfPChclTrJ4EoK9QynqAu9oUf8VEmrpZ5Ww==", "license": "MIT", "dependencies": { "@tanstack/table-core": "8.21.3" ->>>>>>> Stashed changes }, "engines": { "node": ">=12" @@ -1793,15 +998,9 @@ } }, "node_modules/@tanstack/table-core": { -<<<<<<< Updated upstream - "version": "8.21.2", - "resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.21.2.tgz", - "integrity": "sha512-uvXk/U4cBiFMxt+p9/G7yUWI/UbHYbyghLCjlpWZ3mLeIZiUBSKcUnw9UnKkdRz7Z/N4UBuFLWQdJCjUe7HjvA==", -======= "version": "8.21.3", "resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.21.3.tgz", "integrity": "sha512-ldZXEhOBb8Is7xLs01fR3YEc3DERiz5silj8tnGkFZytt1abEvl/GhUmCE0PMLaMPTa3Jk4HbKmRlHmu+gCftg==", ->>>>>>> Stashed changes "license": "MIT", "engines": { "node": ">=12" @@ -2972,21 +2171,6 @@ "react": ">=16.8.0" } }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", diff --git a/frontend/package.json b/frontend/package.json index 76a72114..c0d6ced3 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -18,11 +18,7 @@ "@mantine/hooks": "^7.17.2", "@mantine/notifications": "^7.17.2", "@tabler/icons-react": "^3.31.0", -<<<<<<< Updated upstream "@tanstack/react-table": "^8.21.2", -======= - "@tanstack/react-table": "^8.21.3", ->>>>>>> Stashed changes "allotment": "^1.20.3", "axios": "^1.8.2", "clsx": "^2.1.1", diff --git a/frontend/src/components/tables/ChannelsTable.jsx b/frontend/src/components/tables/ChannelsTable.jsx index 69df12a1..b79aae85 100644 --- a/frontend/src/components/tables/ChannelsTable.jsx +++ b/frontend/src/components/tables/ChannelsTable.jsx @@ -32,6 +32,9 @@ import { EllipsisVertical, CircleEllipsis, CopyMinus, + ArrowUpNarrowWide, + ArrowUpDown, + ArrowDownWideNarrow, } from 'lucide-react'; import ghostImage from '../../images/ghost.svg'; import { @@ -66,144 +69,13 @@ import { flexRender, } from '@tanstack/react-table'; import './table.css'; - -const ChannelStreams = React.memo(({ channel, isExpanded }) => { - const channelStreams = useChannelsStore( - (state) => state.channels[channel.id]?.streams - ); - const { playlists } = usePlaylistsStore(); - - const removeStream = async (stream) => { - const newStreamList = channelStreams.filter((s) => s.id !== stream.id); - await API.updateChannel({ - ...channel, - stream_ids: newStreamList.map((s) => s.id), - }); - }; - - const channelStreamsTable = useReactTable({ - ...TableHelper.defaultProperties, - data: channelStreams, - columns: useMemo( - () => [ - { - size: 400, - header: 'Name', - accessorKey: 'name', - Cell: ({ cell }) => ( -
- {cell.getValue()} -
- ), - }, - { - size: 100, - header: 'M3U', - accessorFn: (row) => - playlists.find((playlist) => playlist.id === row.m3u_account)?.name, - Cell: ({ cell }) => ( -
- {cell.getValue()} -
- ), - }, - ], - [playlists] - ), - displayColumnDefOptions: { - 'mrt-row-actions': { - size: 10, - }, - }, - enableKeyboardShortcuts: false, - enableColumnFilters: false, - enableBottomToolbar: false, - enableTopToolbar: false, - enableTableHead: false, - columnFilterDisplayMode: 'popover', - enablePagination: false, - enableRowVirtualization: true, - enableColumnHeaders: false, - rowVirtualizerOptions: { overscan: 5 }, //optionally customize the row virtualizer - initialState: { - density: 'compact', - }, - enableRowActions: true, - enableRowOrdering: true, - mantineTableHeadRowProps: { - style: { display: 'none' }, - }, - mantineTableBodyCellProps: { - style: { - // py: 0, - padding: 4, - borderColor: '#444', - color: '#E0E0E0', - fontSize: '0.85rem', - }, - }, - mantineRowDragHandleProps: ({ table }) => ({ - onDragEnd: async () => { - const { draggingRow, hoveredRow } = table.getState(); - - if (hoveredRow && draggingRow) { - channelStreams.splice( - hoveredRow.index, - 0, - channelStreams.splice(draggingRow.index, 1)[0] - ); - - const { streams: _, ...channelUpdate } = channel; - - API.updateChannel({ - ...channelUpdate, - stream_ids: channelStreams.map((stream) => stream.id), - }); - } - }, - }), - renderRowActions: ({ row }) => ( - - removeStream(row.original)} - > - - - - ), - }); - - if (!isExpanded) { - return <>; - } - - return ( - - - - ); -}); +import useChannelsTableStore from '../../store/channelsTable'; const m3uUrlBase = `${window.location.protocol}//${window.location.host}/output/m3u`; const epgUrlBase = `${window.location.protocol}//${window.location.host}/output/epg`; const hdhrUrlBase = `${window.location.protocol}//${window.location.host}/hdhr`; -const CreateProfilePopover = React.memo(({}) => { +const CreateProfilePopover = React.memo(() => { const [opened, setOpened] = useState(false); const [name, setName] = useState(''); const theme = useMantineTheme(); @@ -382,18 +254,17 @@ const ChannelRowActions = React.memo( } ); -const ChannelsTable = React.memo(({}) => { - const { - channels, - isLoading: channelsLoading, - fetchChannels, - setChannelsPageSelection, - profiles, - selectedProfileId, - setSelectedProfileId, - channelsPageSelection, - channelGroups, - } = useChannelsStore(); +const ChannelsTable = ({}) => { + const profiles = useChannelsStore((s) => s.profiles); + const selectedProfileId = useChannelsStore((s) => s.selectedProfileId); + const setSelectedProfileId = useChannelsStore((s) => s.setSelectedProfileId); + const channelGroups = useChannelsStore((s) => s.channelGroups); + + const queryChannels = useChannelsTableStore((s) => s.queryChannels); + const requeryChannels = useChannelsTableStore((s) => s.requeryChannels); + const data = useChannelsTableStore((s) => s.channels); + const rowCount = useChannelsTableStore((s) => s.count); + const pageCount = useChannelsTableStore((s) => s.pageCount); const selectedProfileChannels = useChannelsStore( (s) => s.profiles[selectedProfileId]?.channels @@ -416,10 +287,6 @@ const ChannelsTable = React.memo(({}) => { const [selectedProfile, setSelectedProfile] = useState( profiles[selectedProfileId] ); - const [data, setData] = useState([]); // Holds fetched data - const [selectedRowIds, setSelectedRowIds] = useState([]); - const [rowCount, setRowCount] = useState(0); - const [pageCount, setPageCount] = useState(0); const [paginationString, setPaginationString] = useState(''); const [pagination, setPagination] = useState({ pageIndex: 0, @@ -435,14 +302,34 @@ const ChannelsTable = React.memo(({}) => { const [selectedChannelIds, setSelectedChannelIds] = useState([]); const [sorting, setSorting] = useState([ { id: 'channel_number', desc: false }, - { id: 'name', desc: false }, ]); const [hdhrUrl, setHDHRUrl] = useState(hdhrUrlBase); const [epgUrl, setEPGUrl] = useState(epgUrlBase); const [m3uUrl, setM3UUrl] = useState(m3uUrlBase); - const [textToCopy, setTextToCopy] = useState(''); + useEffect(() => { + const startItem = pagination.pageIndex * pagination.pageSize + 1; // +1 to start from 1, not 0 + const endItem = Math.min( + (pagination.pageIndex + 1) * pagination.pageSize, + rowCount + ); + + if (initialDataCount === null) { + setInitialDataCount(rowCount); + } + + // Generate the string + setPaginationString(`${startItem} to ${endItem} of ${rowCount}`); + }, [data]); + + useEffect(() => { + queryChannels({ pagination, sorting, filters }); + }, []); + + useEffect(() => { + queryChannels({ pagination, sorting, filters }); + }, [pagination, sorting, debouncedFilters]); // const theme = useTheme(); const theme = useMantineTheme(); @@ -508,67 +395,6 @@ const ChannelsTable = React.memo(({}) => { showVideo(vidUrl); } - const fetchData = useCallback(async () => { - setIsLoading(true); - - const params = new URLSearchParams(); - params.append('page', pagination.pageIndex + 1); - params.append('page_size', pagination.pageSize); - - // Apply sorting - if (sorting.length > 0) { - const sortField = sorting[0].id; - const sortDirection = sorting[0].desc ? '-' : ''; - params.append('ordering', `${sortDirection}${sortField}`); - } - - // Apply debounced filters - Object.entries(debouncedFilters).forEach(([key, value]) => { - if (value) params.append(key, value); - }); - - try { - const result = await API.queryChannels(params); - setData(result.results); - setRowCount(result.count); - setPageCount(Math.ceil(result.count / pagination.pageSize)); - - // Calculate the starting and ending item indexes - const startItem = pagination.pageIndex * pagination.pageSize + 1; // +1 to start from 1, not 0 - const endItem = Math.min( - (pagination.pageIndex + 1) * pagination.pageSize, - result.count - ); - - if (initialDataCount === null) { - setInitialDataCount(result.count); - } - - // Generate the string - setPaginationString(`${startItem} to ${endItem} of ${result.count}`); - - const newSelection = {}; - result.results.forEach((item, index) => { - if (selectedChannelIds.includes(item.id)) { - newSelection[index] = true; - } - }); - - // ✅ Only update rowSelection if it's different - if (JSON.stringify(newSelection) !== JSON.stringify(rowSelection)) { - setRowSelection(newSelection); - } - } catch (error) { - console.error('Error fetching data:', error); - } - - setIsLoading(false); - }, [pagination, sorting, debouncedFilters]); - - useEffect(() => { - fetchData(); - }, [fetchData]); - const onRowSelectionChange = (updater) => { setRowSelection((prevRowSelection) => { const newRowSelection = @@ -656,13 +482,13 @@ const ChannelsTable = React.memo(({}) => { }; return ; - }, [selectedChannelIds, selectedProfileChannelIds, fetchData]); + }, [selectedChannelIds, selectedProfileChannelIds, data]); // (Optional) bulk delete, but your endpoint is @TODO const deleteChannels = async () => { setIsLoading(true); await API.deleteChannels(selectedChannelIds); - fetchData(); + requeryChannels(); setIsLoading(false); }; @@ -687,7 +513,7 @@ const ChannelsTable = React.memo(({}) => { // Refresh the channel list // await fetchChannels(); - fetchData(); + requeryChannels(); } catch (err) { console.error(err); notifications.show({ @@ -762,6 +588,32 @@ const ChannelsTable = React.memo(({}) => { await API.deleteChannelProfile(id); }; + const onSortingChange = (column) => { + console.log(sorting); + const sortField = sorting[0]?.id; + const sortDirection = sorting[0]?.desc; + + if (sortField == column) { + if (sortDirection == false) { + setSorting([ + { + id: column, + desc: true, + }, + ]); + } else { + setSorting([]); + } + } else { + setSorting([ + { + id: column, + desc: false, + }, + ]); + } + }; + const renderProfileOption = ({ option, checked }) => { return ( @@ -859,7 +711,7 @@ const ChannelsTable = React.memo(({}) => { const value = getValue(); const src = value?.cache_url || logo; return ( -
+
logo { enableSorting: false, }, ], - [selectedProfileId] + [selectedProfileId, data] ); const { getHeaderGroups, getRowModel } = useReactTable({ @@ -899,6 +751,8 @@ const ChannelsTable = React.memo(({}) => { }, pageCount, state: { + data, + rowCount, sorting, filters, pagination, @@ -908,9 +762,6 @@ const ChannelsTable = React.memo(({}) => { manualSorting: true, manualFiltering: true, enableRowSelection: true, - // onPaginationChange: setPagination, - // onSortingChange: setSorting, - // onColumnFiltersChange: setFilters, onRowSelectionChange: onRowSelectionChange, getCoreRowModel: getCoreRowModel(), getFilteredRowModel: getFilteredRowModel(), @@ -922,6 +773,15 @@ const ChannelsTable = React.memo(({}) => { const rows = getRowModel().rows; const renderHeaderCell = (header) => { + let sortingIcon = ArrowUpDown; + if (sorting[0]?.id == header.id) { + if (sorting[0].desc === false) { + sortingIcon = ArrowUpNarrowWide; + } else { + sortingIcon = ArrowDownWideNarrow; + } + } + switch (header.id) { case 'select': return ChannelRowSelectHeader({ @@ -938,19 +798,39 @@ const ChannelsTable = React.memo(({}) => {
); + case 'channel_number': + return ( + + # + {/*
+ {React.createElement(sortingIcon, { + onClick: () => onSortingChange('name'), + size: 14, + })} +
*/} +
+ ); + case 'name': return ( - e.stopPropagation()} - onChange={handleFilterChange} - size="xs" - variant="unstyled" - className="table-input-header" - style={{ width: '100%' }} - /> + + e.stopPropagation()} + onChange={handleFilterChange} + size="xs" + variant="unstyled" + className="table-input-header" + /> +
+ {React.createElement(sortingIcon, { + onClick: () => onSortingChange('name'), + size: 14, + })} +
+
); case 'channel_group': @@ -1006,7 +886,7 @@ const ChannelsTable = React.memo(({}) => {
); }, - [rows] + [rows, rowCount] ); return ( @@ -1320,8 +1200,7 @@ const ChannelsTable = React.memo(({}) => { style={{ display: 'flex', flexDirection: 'column', - height: '100%', - paddingBottom: '56px', + height: 'calc(100vh - 120px)', }} > { > { }} > { /> ); -}); +}; export default ChannelsTable; diff --git a/frontend/src/components/tables/StreamsTable.jsx b/frontend/src/components/tables/StreamsTable.jsx index bcc81a37..777d2a32 100644 --- a/frontend/src/components/tables/StreamsTable.jsx +++ b/frontend/src/components/tables/StreamsTable.jsx @@ -39,6 +39,7 @@ import { IconSquarePlus } from '@tabler/icons-react'; import { useNavigate } from 'react-router-dom'; import useSettingsStore from '../../store/settings'; import useVideoStore from '../../store/useVideoStore'; +import useChannelsTableStore from '../../store/channelsTable'; const StreamsTable = ({}) => { const theme = useMantineTheme(); @@ -77,11 +78,15 @@ const StreamsTable = ({}) => { * Stores */ const { playlists } = usePlaylistsStore(); - const { channelGroups, channelsPageSelection, fetchLogos } = - useChannelsStore(); + const channelGroups = useChannelsStore((s) => s.channelGroups); + const channelsPageSelection = useChannelsStore( + (s) => s.channelsPageSelection + ); + const fetchLogos = useChannelsStore((s) => s.fetchLogos); const channelSelectionStreams = useChannelsStore( (state) => state.channels[state.channelsPageSelection[0]?.id]?.streams ); + const requeryChannels = useChannelsTableStore((s) => s.requeryChannels); const { environment: { env_mode }, } = useSettingsStore(); @@ -293,6 +298,7 @@ const StreamsTable = ({}) => { stream_id, })) ); + requeryChannels(); fetchLogos(); setIsLoading(false); }; diff --git a/frontend/src/store/channels.jsx b/frontend/src/store/channels.jsx index 282ece4c..5e5049be 100644 --- a/frontend/src/store/channels.jsx +++ b/frontend/src/store/channels.jsx @@ -18,6 +18,11 @@ const useChannelsStore = create((set, get) => ({ recordings: [], isLoading: false, error: null, + forceUpdate: 0, + + triggerUpdate: () => { + set({ forecUpdate: new Date() }); + }, fetchChannels: async () => { set({ isLoading: true, error: null }); diff --git a/frontend/src/store/channelsTable b/frontend/src/store/channelsTable new file mode 100644 index 00000000..a5146363 --- /dev/null +++ b/frontend/src/store/channelsTable @@ -0,0 +1,59 @@ +import { create } from 'zustand'; +import api from '../api'; +import { notifications } from '@mantine/notifications'; +import API from '../api'; + +const defaultProfiles = { 0: { id: '0', name: 'All', channels: new Set() } }; + +const useChannelsTableStore = create((set, get) => ({ + channels: [], + count: 0, + pageCount: 0, + lastParams: new URLSearchParams(), + + requeryChannels: async () => { + const lastParams = get().lastParams; + console.log(lastParams); + const result = await API.queryChannels(lastParams); + const pageSize = parseInt(lastParams.get?.('page_size') || '25'); + + set({ + channels: result.results, + count: result.count, + pageCount: Math.ceil(result.count / pageSize), + }); + }, + + queryChannels: async ({ pagination, sorting, filters }) => { + const params = new URLSearchParams(); + params.append('page', pagination.pageIndex + 1); + params.append('page_size', pagination.pageSize); + + // Apply sorting + if (sorting.length > 0) { + const sortField = sorting[0].id; + const sortDirection = sorting[0].desc ? '-' : ''; + params.append('ordering', `${sortDirection}${sortField}`); + } + + // Apply debounced filters + Object.entries(filters).forEach(([key, value]) => { + if (value) params.append(key, value); + }); + + try { + const result = await API.queryChannels(params); + + set((state) => ({ + channels: result.results, + count: result.count, + pageCount: Math.ceil(result.count / pagination.pageSize), + lastParams: params, + })); + } catch (error) { + console.error('Error fetching data:', error); + } + }, +})); + +export default useChannelsTableStore;