diff --git a/package-lock.json b/package-lock.json
index 4a3dd69f9a9073ba5b5749b9a95cc024f56447be..a80405561d5849f84ac85efacb1e7123c83efab8 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -48,7 +48,7 @@
         "@vue/tsconfig": "~0.5.0",
         "axios": "~1.7.0",
         "eslint": "~8.57.0",
-        "eslint-plugin-vue": "~9.26.0",
+        "eslint-plugin-vue": "~9.27.0",
         "highlight.js": "^11.9.0",
         "npm-run-all": "~4.1.5",
         "openapi-typescript-codegen": "^0.29.0",
@@ -962,9 +962,9 @@
       }
     },
     "node_modules/@esbuild/aix-ppc64": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
-      "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==",
+      "version": "0.23.0",
+      "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.0.tgz",
+      "integrity": "sha512-3sG8Zwa5fMcA9bgqB8AfWPQ+HFke6uD3h1s3RIwUNK8EG7a4buxvuFTs3j1IMs2NXAk9F30C/FF4vxRgQCcmoQ==",
       "cpu": [
         "ppc64"
       ],
@@ -973,14 +973,15 @@
       "os": [
         "aix"
       ],
+      "peer": true,
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
       }
     },
     "node_modules/@esbuild/android-arm": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz",
-      "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==",
+      "version": "0.23.0",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.0.tgz",
+      "integrity": "sha512-+KuOHTKKyIKgEEqKbGTK8W7mPp+hKinbMBeEnNzjJGyFcWsfrXjSTNluJHCY1RqhxFurdD8uNXQDei7qDlR6+g==",
       "cpu": [
         "arm"
       ],
@@ -989,14 +990,15 @@
       "os": [
         "android"
       ],
+      "peer": true,
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
       }
     },
     "node_modules/@esbuild/android-arm64": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz",
-      "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==",
+      "version": "0.23.0",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.0.tgz",
+      "integrity": "sha512-EuHFUYkAVfU4qBdyivULuu03FhJO4IJN9PGuABGrFy4vUuzk91P2d+npxHcFdpUnfYKy0PuV+n6bKIpHOB3prQ==",
       "cpu": [
         "arm64"
       ],
@@ -1005,14 +1007,15 @@
       "os": [
         "android"
       ],
+      "peer": true,
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
       }
     },
     "node_modules/@esbuild/android-x64": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz",
-      "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==",
+      "version": "0.23.0",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.0.tgz",
+      "integrity": "sha512-WRrmKidLoKDl56LsbBMhzTTBxrsVwTKdNbKDalbEZr0tcsBgCLbEtoNthOW6PX942YiYq8HzEnb4yWQMLQuipQ==",
       "cpu": [
         "x64"
       ],
@@ -1021,14 +1024,15 @@
       "os": [
         "android"
       ],
+      "peer": true,
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
       }
     },
     "node_modules/@esbuild/darwin-arm64": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz",
-      "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==",
+      "version": "0.23.0",
+      "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.0.tgz",
+      "integrity": "sha512-YLntie/IdS31H54Ogdn+v50NuoWF5BDkEUFpiOChVa9UnKpftgwzZRrI4J132ETIi+D8n6xh9IviFV3eXdxfow==",
       "cpu": [
         "arm64"
       ],
@@ -1037,14 +1041,15 @@
       "os": [
         "darwin"
       ],
+      "peer": true,
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
       }
     },
     "node_modules/@esbuild/darwin-x64": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz",
-      "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==",
+      "version": "0.23.0",
+      "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.0.tgz",
+      "integrity": "sha512-IMQ6eme4AfznElesHUPDZ+teuGwoRmVuuixu7sv92ZkdQcPbsNHzutd+rAfaBKo8YK3IrBEi9SLLKWJdEvJniQ==",
       "cpu": [
         "x64"
       ],
@@ -1053,14 +1058,15 @@
       "os": [
         "darwin"
       ],
+      "peer": true,
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
       }
     },
     "node_modules/@esbuild/freebsd-arm64": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz",
-      "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==",
+      "version": "0.23.0",
+      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.0.tgz",
+      "integrity": "sha512-0muYWCng5vqaxobq6LB3YNtevDFSAZGlgtLoAc81PjUfiFz36n4KMpwhtAd4he8ToSI3TGyuhyx5xmiWNYZFyw==",
       "cpu": [
         "arm64"
       ],
@@ -1069,14 +1075,15 @@
       "os": [
         "freebsd"
       ],
+      "peer": true,
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
       }
     },
     "node_modules/@esbuild/freebsd-x64": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz",
-      "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==",
+      "version": "0.23.0",
+      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.0.tgz",
+      "integrity": "sha512-XKDVu8IsD0/q3foBzsXGt/KjD/yTKBCIwOHE1XwiXmrRwrX6Hbnd5Eqn/WvDekddK21tfszBSrE/WMaZh+1buQ==",
       "cpu": [
         "x64"
       ],
@@ -1085,14 +1092,15 @@
       "os": [
         "freebsd"
       ],
+      "peer": true,
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
       }
     },
     "node_modules/@esbuild/linux-arm": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz",
-      "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==",
+      "version": "0.23.0",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.0.tgz",
+      "integrity": "sha512-SEELSTEtOFu5LPykzA395Mc+54RMg1EUgXP+iw2SJ72+ooMwVsgfuwXo5Fn0wXNgWZsTVHwY2cg4Vi/bOD88qw==",
       "cpu": [
         "arm"
       ],
@@ -1101,14 +1109,15 @@
       "os": [
         "linux"
       ],
+      "peer": true,
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
       }
     },
     "node_modules/@esbuild/linux-arm64": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz",
-      "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==",
+      "version": "0.23.0",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.0.tgz",
+      "integrity": "sha512-j1t5iG8jE7BhonbsEg5d9qOYcVZv/Rv6tghaXM/Ug9xahM0nX/H2gfu6X6z11QRTMT6+aywOMA8TDkhPo8aCGw==",
       "cpu": [
         "arm64"
       ],
@@ -1117,14 +1126,15 @@
       "os": [
         "linux"
       ],
+      "peer": true,
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
       }
     },
     "node_modules/@esbuild/linux-ia32": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz",
-      "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==",
+      "version": "0.23.0",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.0.tgz",
+      "integrity": "sha512-P7O5Tkh2NbgIm2R6x1zGJJsnacDzTFcRWZyTTMgFdVit6E98LTxO+v8LCCLWRvPrjdzXHx9FEOA8oAZPyApWUA==",
       "cpu": [
         "ia32"
       ],
@@ -1133,14 +1143,15 @@
       "os": [
         "linux"
       ],
+      "peer": true,
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
       }
     },
     "node_modules/@esbuild/linux-loong64": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz",
-      "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==",
+      "version": "0.23.0",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.0.tgz",
+      "integrity": "sha512-InQwepswq6urikQiIC/kkx412fqUZudBO4SYKu0N+tGhXRWUqAx+Q+341tFV6QdBifpjYgUndV1hhMq3WeJi7A==",
       "cpu": [
         "loong64"
       ],
@@ -1149,14 +1160,15 @@
       "os": [
         "linux"
       ],
+      "peer": true,
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
       }
     },
     "node_modules/@esbuild/linux-mips64el": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz",
-      "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==",
+      "version": "0.23.0",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.0.tgz",
+      "integrity": "sha512-J9rflLtqdYrxHv2FqXE2i1ELgNjT+JFURt/uDMoPQLcjWQA5wDKgQA4t/dTqGa88ZVECKaD0TctwsUfHbVoi4w==",
       "cpu": [
         "mips64el"
       ],
@@ -1165,14 +1177,15 @@
       "os": [
         "linux"
       ],
+      "peer": true,
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
       }
     },
     "node_modules/@esbuild/linux-ppc64": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz",
-      "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==",
+      "version": "0.23.0",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.0.tgz",
+      "integrity": "sha512-cShCXtEOVc5GxU0fM+dsFD10qZ5UpcQ8AM22bYj0u/yaAykWnqXJDpd77ublcX6vdDsWLuweeuSNZk4yUxZwtw==",
       "cpu": [
         "ppc64"
       ],
@@ -1181,14 +1194,15 @@
       "os": [
         "linux"
       ],
+      "peer": true,
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
       }
     },
     "node_modules/@esbuild/linux-riscv64": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz",
-      "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==",
+      "version": "0.23.0",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.0.tgz",
+      "integrity": "sha512-HEtaN7Y5UB4tZPeQmgz/UhzoEyYftbMXrBCUjINGjh3uil+rB/QzzpMshz3cNUxqXN7Vr93zzVtpIDL99t9aRw==",
       "cpu": [
         "riscv64"
       ],
@@ -1197,14 +1211,15 @@
       "os": [
         "linux"
       ],
+      "peer": true,
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
       }
     },
     "node_modules/@esbuild/linux-s390x": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz",
-      "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==",
+      "version": "0.23.0",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.0.tgz",
+      "integrity": "sha512-WDi3+NVAuyjg/Wxi+o5KPqRbZY0QhI9TjrEEm+8dmpY9Xir8+HE/HNx2JoLckhKbFopW0RdO2D72w8trZOV+Wg==",
       "cpu": [
         "s390x"
       ],
@@ -1213,14 +1228,15 @@
       "os": [
         "linux"
       ],
+      "peer": true,
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
       }
     },
     "node_modules/@esbuild/linux-x64": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz",
-      "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==",
+      "version": "0.23.0",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.0.tgz",
+      "integrity": "sha512-a3pMQhUEJkITgAw6e0bWA+F+vFtCciMjW/LPtoj99MhVt+Mfb6bbL9hu2wmTZgNd994qTAEw+U/r6k3qHWWaOQ==",
       "cpu": [
         "x64"
       ],
@@ -1229,14 +1245,15 @@
       "os": [
         "linux"
       ],
+      "peer": true,
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
       }
     },
     "node_modules/@esbuild/netbsd-x64": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz",
-      "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==",
+      "version": "0.23.0",
+      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.0.tgz",
+      "integrity": "sha512-cRK+YDem7lFTs2Q5nEv/HHc4LnrfBCbH5+JHu6wm2eP+d8OZNoSMYgPZJq78vqQ9g+9+nMuIsAO7skzphRXHyw==",
       "cpu": [
         "x64"
       ],
@@ -1245,14 +1262,32 @@
       "os": [
         "netbsd"
       ],
+      "peer": true,
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/openbsd-arm64": {
+      "version": "0.23.0",
+      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.0.tgz",
+      "integrity": "sha512-suXjq53gERueVWu0OKxzWqk7NxiUWSUlrxoZK7usiF50C6ipColGR5qie2496iKGYNLhDZkPxBI3erbnYkU0rQ==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "openbsd"
+      ],
+      "peer": true,
+      "engines": {
+        "node": ">=18"
       }
     },
     "node_modules/@esbuild/openbsd-x64": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz",
-      "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==",
+      "version": "0.23.0",
+      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.0.tgz",
+      "integrity": "sha512-6p3nHpby0DM/v15IFKMjAaayFhqnXV52aEmv1whZHX56pdkK+MEaLoQWj+H42ssFarP1PcomVhbsR4pkz09qBg==",
       "cpu": [
         "x64"
       ],
@@ -1261,14 +1296,15 @@
       "os": [
         "openbsd"
       ],
+      "peer": true,
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
       }
     },
     "node_modules/@esbuild/sunos-x64": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz",
-      "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==",
+      "version": "0.23.0",
+      "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.0.tgz",
+      "integrity": "sha512-BFelBGfrBwk6LVrmFzCq1u1dZbG4zy/Kp93w2+y83Q5UGYF1d8sCzeLI9NXjKyujjBBniQa8R8PzLFAUrSM9OA==",
       "cpu": [
         "x64"
       ],
@@ -1277,14 +1313,15 @@
       "os": [
         "sunos"
       ],
+      "peer": true,
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
       }
     },
     "node_modules/@esbuild/win32-arm64": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz",
-      "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==",
+      "version": "0.23.0",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.0.tgz",
+      "integrity": "sha512-lY6AC8p4Cnb7xYHuIxQ6iYPe6MfO2CC43XXKo9nBXDb35krYt7KGhQnOkRGar5psxYkircpCqfbNDB4uJbS2jQ==",
       "cpu": [
         "arm64"
       ],
@@ -1293,14 +1330,15 @@
       "os": [
         "win32"
       ],
+      "peer": true,
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
       }
     },
     "node_modules/@esbuild/win32-ia32": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz",
-      "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==",
+      "version": "0.23.0",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.0.tgz",
+      "integrity": "sha512-7L1bHlOTcO4ByvI7OXVI5pNN6HSu6pUQq9yodga8izeuB1KcT2UkHaH6118QJwopExPn0rMHIseCTx1CRo/uNA==",
       "cpu": [
         "ia32"
       ],
@@ -1309,14 +1347,15 @@
       "os": [
         "win32"
       ],
+      "peer": true,
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
       }
     },
     "node_modules/@esbuild/win32-x64": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz",
-      "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==",
+      "version": "0.23.0",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.0.tgz",
+      "integrity": "sha512-Arm+WgUFLUATuoxCJcahGuk6Yj9Pzxd6l11Zb/2aAuv5kWWvvfhLFo2fni4uSK5vzlUdCGZ/BdV5tH8klj8p8g==",
       "cpu": [
         "x64"
       ],
@@ -1325,8 +1364,9 @@
       "os": [
         "win32"
       ],
+      "peer": true,
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
       }
     },
     "node_modules/@eslint-community/eslint-utils": {
@@ -1345,9 +1385,9 @@
       }
     },
     "node_modules/@eslint-community/regexpp": {
-      "version": "4.10.1",
-      "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.1.tgz",
-      "integrity": "sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA==",
+      "version": "4.11.0",
+      "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz",
+      "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==",
       "dev": true,
       "engines": {
         "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
@@ -2488,16 +2528,16 @@
       "dev": true
     },
     "node_modules/@typescript-eslint/eslint-plugin": {
-      "version": "7.14.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.14.1.tgz",
-      "integrity": "sha512-aAJd6bIf2vvQRjUG3ZkNXkmBpN+J7Wd0mfQiiVCJMu9Z5GcZZdcc0j8XwN/BM97Fl7e3SkTXODSk4VehUv7CGw==",
+      "version": "7.15.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.15.0.tgz",
+      "integrity": "sha512-uiNHpyjZtFrLwLDpHnzaDlP3Tt6sGMqTCiqmxaN4n4RP0EfYZDODJyddiFDF44Hjwxr5xAcaYxVKm9QKQFJFLA==",
       "dev": true,
       "dependencies": {
         "@eslint-community/regexpp": "^4.10.0",
-        "@typescript-eslint/scope-manager": "7.14.1",
-        "@typescript-eslint/type-utils": "7.14.1",
-        "@typescript-eslint/utils": "7.14.1",
-        "@typescript-eslint/visitor-keys": "7.14.1",
+        "@typescript-eslint/scope-manager": "7.15.0",
+        "@typescript-eslint/type-utils": "7.15.0",
+        "@typescript-eslint/utils": "7.15.0",
+        "@typescript-eslint/visitor-keys": "7.15.0",
         "graphemer": "^1.4.0",
         "ignore": "^5.3.1",
         "natural-compare": "^1.4.0",
@@ -2521,15 +2561,15 @@
       }
     },
     "node_modules/@typescript-eslint/parser": {
-      "version": "7.14.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.14.1.tgz",
-      "integrity": "sha512-8lKUOebNLcR0D7RvlcloOacTOWzOqemWEWkKSVpMZVF/XVcwjPR+3MD08QzbW9TCGJ+DwIc6zUSGZ9vd8cO1IA==",
+      "version": "7.15.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.15.0.tgz",
+      "integrity": "sha512-k9fYuQNnypLFcqORNClRykkGOMOj+pV6V91R4GO/l1FDGwpqmSwoOQrOHo3cGaH63e+D3ZiCAOsuS/D2c99j/A==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/scope-manager": "7.14.1",
-        "@typescript-eslint/types": "7.14.1",
-        "@typescript-eslint/typescript-estree": "7.14.1",
-        "@typescript-eslint/visitor-keys": "7.14.1",
+        "@typescript-eslint/scope-manager": "7.15.0",
+        "@typescript-eslint/types": "7.15.0",
+        "@typescript-eslint/typescript-estree": "7.15.0",
+        "@typescript-eslint/visitor-keys": "7.15.0",
         "debug": "^4.3.4"
       },
       "engines": {
@@ -2549,13 +2589,13 @@
       }
     },
     "node_modules/@typescript-eslint/scope-manager": {
-      "version": "7.14.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.14.1.tgz",
-      "integrity": "sha512-gPrFSsoYcsffYXTOZ+hT7fyJr95rdVe4kGVX1ps/dJ+DfmlnjFN/GcMxXcVkeHDKqsq6uAcVaQaIi3cFffmAbA==",
+      "version": "7.15.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.15.0.tgz",
+      "integrity": "sha512-Q/1yrF/XbxOTvttNVPihxh1b9fxamjEoz2Os/Pe38OHwxC24CyCqXxGTOdpb4lt6HYtqw9HetA/Rf6gDGaMPlw==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/types": "7.14.1",
-        "@typescript-eslint/visitor-keys": "7.14.1"
+        "@typescript-eslint/types": "7.15.0",
+        "@typescript-eslint/visitor-keys": "7.15.0"
       },
       "engines": {
         "node": "^18.18.0 || >=20.0.0"
@@ -2566,13 +2606,13 @@
       }
     },
     "node_modules/@typescript-eslint/type-utils": {
-      "version": "7.14.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.14.1.tgz",
-      "integrity": "sha512-/MzmgNd3nnbDbOi3LfasXWWe292+iuo+umJ0bCCMCPc1jLO/z2BQmWUUUXvXLbrQey/JgzdF/OV+I5bzEGwJkQ==",
+      "version": "7.15.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.15.0.tgz",
+      "integrity": "sha512-SkgriaeV6PDvpA6253PDVep0qCqgbO1IOBiycjnXsszNTVQe5flN5wR5jiczoEoDEnAqYFSFFc9al9BSGVltkg==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/typescript-estree": "7.14.1",
-        "@typescript-eslint/utils": "7.14.1",
+        "@typescript-eslint/typescript-estree": "7.15.0",
+        "@typescript-eslint/utils": "7.15.0",
         "debug": "^4.3.4",
         "ts-api-utils": "^1.3.0"
       },
@@ -2593,9 +2633,9 @@
       }
     },
     "node_modules/@typescript-eslint/types": {
-      "version": "7.14.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.14.1.tgz",
-      "integrity": "sha512-mL7zNEOQybo5R3AavY+Am7KLv8BorIv7HCYS5rKoNZKQD9tsfGUpO4KdAn3sSUvTiS4PQkr2+K0KJbxj8H9NDg==",
+      "version": "7.15.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.15.0.tgz",
+      "integrity": "sha512-aV1+B1+ySXbQH0pLK0rx66I3IkiZNidYobyfn0WFsdGhSXw+P3YOqeTq5GED458SfB24tg+ux3S+9g118hjlTw==",
       "dev": true,
       "engines": {
         "node": "^18.18.0 || >=20.0.0"
@@ -2606,13 +2646,13 @@
       }
     },
     "node_modules/@typescript-eslint/typescript-estree": {
-      "version": "7.14.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.14.1.tgz",
-      "integrity": "sha512-k5d0VuxViE2ulIO6FbxxSZaxqDVUyMbXcidC8rHvii0I56XZPv8cq+EhMns+d/EVIL41sMXqRbK3D10Oza1bbA==",
+      "version": "7.15.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.15.0.tgz",
+      "integrity": "sha512-gjyB/rHAopL/XxfmYThQbXbzRMGhZzGw6KpcMbfe8Q3nNQKStpxnUKeXb0KiN/fFDR42Z43szs6rY7eHk0zdGQ==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/types": "7.14.1",
-        "@typescript-eslint/visitor-keys": "7.14.1",
+        "@typescript-eslint/types": "7.15.0",
+        "@typescript-eslint/visitor-keys": "7.15.0",
         "debug": "^4.3.4",
         "globby": "^11.1.0",
         "is-glob": "^4.0.3",
@@ -2634,15 +2674,15 @@
       }
     },
     "node_modules/@typescript-eslint/utils": {
-      "version": "7.14.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.14.1.tgz",
-      "integrity": "sha512-CMmVVELns3nak3cpJhZosDkm63n+DwBlDX8g0k4QUa9BMnF+lH2lr3d130M1Zt1xxmB3LLk3NV7KQCq86ZBBhQ==",
+      "version": "7.15.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.15.0.tgz",
+      "integrity": "sha512-hfDMDqaqOqsUVGiEPSMLR/AjTSCsmJwjpKkYQRo1FNbmW4tBwBspYDwO9eh7sKSTwMQgBw9/T4DHudPaqshRWA==",
       "dev": true,
       "dependencies": {
         "@eslint-community/eslint-utils": "^4.4.0",
-        "@typescript-eslint/scope-manager": "7.14.1",
-        "@typescript-eslint/types": "7.14.1",
-        "@typescript-eslint/typescript-estree": "7.14.1"
+        "@typescript-eslint/scope-manager": "7.15.0",
+        "@typescript-eslint/types": "7.15.0",
+        "@typescript-eslint/typescript-estree": "7.15.0"
       },
       "engines": {
         "node": "^18.18.0 || >=20.0.0"
@@ -2656,12 +2696,12 @@
       }
     },
     "node_modules/@typescript-eslint/visitor-keys": {
-      "version": "7.14.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.14.1.tgz",
-      "integrity": "sha512-Crb+F75U1JAEtBeQGxSKwI60hZmmzaqA3z9sYsVm8X7W5cwLEm5bRe0/uXS6+MR/y8CVpKSR/ontIAIEPFcEkA==",
+      "version": "7.15.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.15.0.tgz",
+      "integrity": "sha512-Hqgy/ETgpt2L5xueA/zHHIl4fJI2O4XUE9l4+OIfbJIRSnTJb/QscncdqqZzofQegIJugRIF57OJea1khw2SDw==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/types": "7.14.1",
+        "@typescript-eslint/types": "7.15.0",
         "eslint-visitor-keys": "^3.4.3"
       },
       "engines": {
@@ -2692,38 +2732,38 @@
       }
     },
     "node_modules/@volar/language-core": {
-      "version": "2.3.4",
-      "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.3.4.tgz",
-      "integrity": "sha512-wXBhY11qG6pCDAqDnbBRFIDSIwbqkWI7no+lj5+L7IlA7HRIjRP7YQLGzT0LF4lS6eHkMSsclXqy9DwYJasZTQ==",
+      "version": "2.4.0-alpha.12",
+      "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.0-alpha.12.tgz",
+      "integrity": "sha512-Dj9qTifcGGgzFLfMbU5dCo13kHyNuEyvPJhtWDnoVBBmgwW3GMwFmgWnNxBhjf63m5x0gux1okaxX2CLN7qSww==",
       "dev": true,
       "dependencies": {
-        "@volar/source-map": "2.3.4"
+        "@volar/source-map": "2.4.0-alpha.12"
       }
     },
     "node_modules/@volar/source-map": {
-      "version": "2.3.4",
-      "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.3.4.tgz",
-      "integrity": "sha512-C+t63nwcblqLIVTYXaVi/+gC8NukDaDIQI72J3R7aXGvtgaVB16c+J8Iz7/VfOy7kjYv7lf5GhBny6ACw9fTGQ==",
+      "version": "2.4.0-alpha.12",
+      "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.0-alpha.12.tgz",
+      "integrity": "sha512-LXATFSj4D7T9sEm7FFj6iBgHjKjrdhAgRPcechVKiNCMQdr3r3GVkkeu8aM+1peaMH3LsCqoDxVZEmh2r7CHiw==",
       "dev": true
     },
     "node_modules/@volar/typescript": {
-      "version": "2.3.4",
-      "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.3.4.tgz",
-      "integrity": "sha512-acCvt7dZECyKcvO5geNybmrqOsu9u8n5XP1rfiYsOLYGPxvHRav9BVmEdRyZ3vvY6mNyQ1wLL5Hday4IShe17w==",
+      "version": "2.4.0-alpha.12",
+      "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.0-alpha.12.tgz",
+      "integrity": "sha512-mLg+OQauMTv/+08a7WBWJo1sev/wc8t2is0zhBZIlFU+j5mG89FM4+4089c2p/zoUFZ400Q/VNg2BPfhpZ8wSA==",
       "dev": true,
       "dependencies": {
-        "@volar/language-core": "2.3.4",
+        "@volar/language-core": "2.4.0-alpha.12",
         "path-browserify": "^1.0.1",
         "vscode-uri": "^3.0.8"
       }
     },
     "node_modules/@vue/compiler-core": {
-      "version": "3.4.30",
-      "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.30.tgz",
-      "integrity": "sha512-ZL8y4Xxdh8O6PSwfdZ1IpQ24PjTAieOz3jXb/MDTfDtANcKBMxg1KLm6OX2jofsaQGYfIVzd3BAG22i56/cF1w==",
+      "version": "3.4.31",
+      "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.31.tgz",
+      "integrity": "sha512-skOiodXWTV3DxfDhB4rOf3OGalpITLlgCeOwb+Y9GJpfQ8ErigdBUHomBzvG78JoVE8MJoQsb+qhZiHfKeNeEg==",
       "dependencies": {
         "@babel/parser": "^7.24.7",
-        "@vue/shared": "3.4.30",
+        "@vue/shared": "3.4.31",
         "entities": "^4.5.0",
         "estree-walker": "^2.0.2",
         "source-map-js": "^1.2.0"
@@ -2735,24 +2775,24 @@
       "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
     },
     "node_modules/@vue/compiler-dom": {
-      "version": "3.4.30",
-      "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.30.tgz",
-      "integrity": "sha512-+16Sd8lYr5j/owCbr9dowcNfrHd+pz+w2/b5Lt26Oz/kB90C9yNbxQ3bYOvt7rI2bxk0nqda39hVcwDFw85c2Q==",
+      "version": "3.4.31",
+      "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.31.tgz",
+      "integrity": "sha512-wK424WMXsG1IGMyDGyLqB+TbmEBFM78hIsOJ9QwUVLGrcSk0ak6zYty7Pj8ftm7nEtdU/DGQxAXp0/lM/2cEpQ==",
       "dependencies": {
-        "@vue/compiler-core": "3.4.30",
-        "@vue/shared": "3.4.30"
+        "@vue/compiler-core": "3.4.31",
+        "@vue/shared": "3.4.31"
       }
     },
     "node_modules/@vue/compiler-sfc": {
-      "version": "3.4.30",
-      "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.30.tgz",
-      "integrity": "sha512-8vElKklHn/UY8+FgUFlQrYAPbtiSB2zcgeRKW7HkpSRn/JjMRmZvuOtwDx036D1aqKNSTtXkWRfqx53Qb+HmMg==",
+      "version": "3.4.31",
+      "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.31.tgz",
+      "integrity": "sha512-einJxqEw8IIJxzmnxmJBuK2usI+lJonl53foq+9etB2HAzlPjAS/wa7r0uUpXw5ByX3/0uswVSrjNb17vJm1kQ==",
       "dependencies": {
         "@babel/parser": "^7.24.7",
-        "@vue/compiler-core": "3.4.30",
-        "@vue/compiler-dom": "3.4.30",
-        "@vue/compiler-ssr": "3.4.30",
-        "@vue/shared": "3.4.30",
+        "@vue/compiler-core": "3.4.31",
+        "@vue/compiler-dom": "3.4.31",
+        "@vue/compiler-ssr": "3.4.31",
+        "@vue/shared": "3.4.31",
         "estree-walker": "^2.0.2",
         "magic-string": "^0.30.10",
         "postcss": "^8.4.38",
@@ -2773,12 +2813,12 @@
       }
     },
     "node_modules/@vue/compiler-ssr": {
-      "version": "3.4.30",
-      "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.30.tgz",
-      "integrity": "sha512-ZJ56YZGXJDd6jky4mmM0rNaNP6kIbQu9LTKZDhcpddGe/3QIalB1WHHmZ6iZfFNyj5mSypTa4+qDJa5VIuxMSg==",
+      "version": "3.4.31",
+      "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.31.tgz",
+      "integrity": "sha512-RtefmITAje3fJ8FSg1gwgDhdKhZVntIVbwupdyZDSifZTRMiWxWehAOTCc8/KZDnBOcYQ4/9VWxsTbd3wT0hAA==",
       "dependencies": {
-        "@vue/compiler-dom": "3.4.30",
-        "@vue/shared": "3.4.30"
+        "@vue/compiler-dom": "3.4.31",
+        "@vue/shared": "3.4.31"
       }
     },
     "node_modules/@vue/devtools-api": {
@@ -2825,12 +2865,12 @@
       }
     },
     "node_modules/@vue/language-core": {
-      "version": "2.0.22",
-      "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-2.0.22.tgz",
-      "integrity": "sha512-dNTAAtEOuMiz7N1s5tKpypnVVCtawxVSF5BukD0ELcYSw+DSbrSlYYSw8GuwvurodCeYFSHsmslE+c2sYDNoiA==",
+      "version": "2.0.24",
+      "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-2.0.24.tgz",
+      "integrity": "sha512-997YD6Lq/66LXr3ZOLNxDCmyn13z9NP8LU1UZn9hGCDWhzlbXAIP0hOgL3w3x4RKEaWTaaRtsHP9DzHvmduruQ==",
       "dev": true,
       "dependencies": {
-        "@volar/language-core": "~2.3.1",
+        "@volar/language-core": "~2.4.0-alpha.2",
         "@vue/compiler-dom": "^3.4.0",
         "@vue/shared": "^3.4.0",
         "computeds": "^0.0.1",
@@ -2849,49 +2889,49 @@
       }
     },
     "node_modules/@vue/reactivity": {
-      "version": "3.4.30",
-      "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.30.tgz",
-      "integrity": "sha512-bVJurnCe3LS0JII8PPoAA63Zd2MBzcKrEzwdQl92eHCcxtIbxD2fhNwJpa+KkM3Y/A4T5FUnmdhgKwOf6BfbcA==",
+      "version": "3.4.31",
+      "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.31.tgz",
+      "integrity": "sha512-VGkTani8SOoVkZNds1PfJ/T1SlAIOf8E58PGAhIOUDYPC4GAmFA2u/E14TDAFcf3vVDKunc4QqCe/SHr8xC65Q==",
       "dependencies": {
-        "@vue/shared": "3.4.30"
+        "@vue/shared": "3.4.31"
       }
     },
     "node_modules/@vue/runtime-core": {
-      "version": "3.4.30",
-      "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.30.tgz",
-      "integrity": "sha512-qaFEbnNpGz+tlnkaualomogzN8vBLkgzK55uuWjYXbYn039eOBZrWxyXWq/7qh9Bz2FPifZqGjVDl/FXiq9L2g==",
+      "version": "3.4.31",
+      "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.31.tgz",
+      "integrity": "sha512-LDkztxeUPazxG/p8c5JDDKPfkCDBkkiNLVNf7XZIUnJ+66GVGkP+TIh34+8LtPisZ+HMWl2zqhIw0xN5MwU1cw==",
       "dependencies": {
-        "@vue/reactivity": "3.4.30",
-        "@vue/shared": "3.4.30"
+        "@vue/reactivity": "3.4.31",
+        "@vue/shared": "3.4.31"
       }
     },
     "node_modules/@vue/runtime-dom": {
-      "version": "3.4.30",
-      "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.30.tgz",
-      "integrity": "sha512-tV6B4YiZRj5QsaJgw2THCy5C1H+2UeywO9tqgWEc21tn85qHEERndHN/CxlyXvSBFrpmlexCIdnqPuR9RM9thw==",
+      "version": "3.4.31",
+      "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.31.tgz",
+      "integrity": "sha512-2Auws3mB7+lHhTFCg8E9ZWopA6Q6L455EcU7bzcQ4x6Dn4cCPuqj6S2oBZgN2a8vJRS/LSYYxwFFq2Hlx3Fsaw==",
       "dependencies": {
-        "@vue/reactivity": "3.4.30",
-        "@vue/runtime-core": "3.4.30",
-        "@vue/shared": "3.4.30",
+        "@vue/reactivity": "3.4.31",
+        "@vue/runtime-core": "3.4.31",
+        "@vue/shared": "3.4.31",
         "csstype": "^3.1.3"
       }
     },
     "node_modules/@vue/server-renderer": {
-      "version": "3.4.30",
-      "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.30.tgz",
-      "integrity": "sha512-TBD3eqR1DeDc0cMrXS/vEs/PWzq1uXxnvjoqQuDGFIEHFIwuDTX/KWAQKIBjyMWLFHEeTDGYVsYci85z2UbTDg==",
+      "version": "3.4.31",
+      "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.31.tgz",
+      "integrity": "sha512-D5BLbdvrlR9PE3by9GaUp1gQXlCNadIZytMIb8H2h3FMWJd4oUfkUTEH2wAr3qxoRz25uxbTcbqd3WKlm9EHQA==",
       "dependencies": {
-        "@vue/compiler-ssr": "3.4.30",
-        "@vue/shared": "3.4.30"
+        "@vue/compiler-ssr": "3.4.31",
+        "@vue/shared": "3.4.31"
       },
       "peerDependencies": {
-        "vue": "3.4.30"
+        "vue": "3.4.31"
       }
     },
     "node_modules/@vue/shared": {
-      "version": "3.4.30",
-      "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.30.tgz",
-      "integrity": "sha512-CLg+f8RQCHQnKvuHY9adMsMaQOcqclh6Z5V9TaoMgy0ut0tz848joZ7/CYFFyF/yZ5i2yaw7Fn498C+CNZVHIg=="
+      "version": "3.4.31",
+      "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.31.tgz",
+      "integrity": "sha512-Yp3wtJk//8cO4NItOPpi3QkLExAr/aLBGZMmTtW9WpdwBCJpRM6zj9WgWktXAl8IDIozwNMByT45JP3tO3ACWA=="
     },
     "node_modules/@vue/tsconfig": {
       "version": "0.5.1",
@@ -3651,41 +3691,43 @@
       }
     },
     "node_modules/esbuild": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz",
-      "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==",
+      "version": "0.23.0",
+      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.0.tgz",
+      "integrity": "sha512-1lvV17H2bMYda/WaFb2jLPeHU3zml2k4/yagNMG8Q/YtfMjCwEUZa2eXXMgZTVSL5q1n4H7sQ0X6CdJDqqeCFA==",
       "dev": true,
       "hasInstallScript": true,
+      "peer": true,
       "bin": {
         "esbuild": "bin/esbuild"
       },
       "engines": {
-        "node": ">=12"
+        "node": ">=18"
       },
       "optionalDependencies": {
-        "@esbuild/aix-ppc64": "0.21.5",
-        "@esbuild/android-arm": "0.21.5",
-        "@esbuild/android-arm64": "0.21.5",
-        "@esbuild/android-x64": "0.21.5",
-        "@esbuild/darwin-arm64": "0.21.5",
-        "@esbuild/darwin-x64": "0.21.5",
-        "@esbuild/freebsd-arm64": "0.21.5",
-        "@esbuild/freebsd-x64": "0.21.5",
-        "@esbuild/linux-arm": "0.21.5",
-        "@esbuild/linux-arm64": "0.21.5",
-        "@esbuild/linux-ia32": "0.21.5",
-        "@esbuild/linux-loong64": "0.21.5",
-        "@esbuild/linux-mips64el": "0.21.5",
-        "@esbuild/linux-ppc64": "0.21.5",
-        "@esbuild/linux-riscv64": "0.21.5",
-        "@esbuild/linux-s390x": "0.21.5",
-        "@esbuild/linux-x64": "0.21.5",
-        "@esbuild/netbsd-x64": "0.21.5",
-        "@esbuild/openbsd-x64": "0.21.5",
-        "@esbuild/sunos-x64": "0.21.5",
-        "@esbuild/win32-arm64": "0.21.5",
-        "@esbuild/win32-ia32": "0.21.5",
-        "@esbuild/win32-x64": "0.21.5"
+        "@esbuild/aix-ppc64": "0.23.0",
+        "@esbuild/android-arm": "0.23.0",
+        "@esbuild/android-arm64": "0.23.0",
+        "@esbuild/android-x64": "0.23.0",
+        "@esbuild/darwin-arm64": "0.23.0",
+        "@esbuild/darwin-x64": "0.23.0",
+        "@esbuild/freebsd-arm64": "0.23.0",
+        "@esbuild/freebsd-x64": "0.23.0",
+        "@esbuild/linux-arm": "0.23.0",
+        "@esbuild/linux-arm64": "0.23.0",
+        "@esbuild/linux-ia32": "0.23.0",
+        "@esbuild/linux-loong64": "0.23.0",
+        "@esbuild/linux-mips64el": "0.23.0",
+        "@esbuild/linux-ppc64": "0.23.0",
+        "@esbuild/linux-riscv64": "0.23.0",
+        "@esbuild/linux-s390x": "0.23.0",
+        "@esbuild/linux-x64": "0.23.0",
+        "@esbuild/netbsd-x64": "0.23.0",
+        "@esbuild/openbsd-arm64": "0.23.0",
+        "@esbuild/openbsd-x64": "0.23.0",
+        "@esbuild/sunos-x64": "0.23.0",
+        "@esbuild/win32-arm64": "0.23.0",
+        "@esbuild/win32-ia32": "0.23.0",
+        "@esbuild/win32-x64": "0.23.0"
       }
     },
     "node_modules/escape-string-regexp": {
@@ -3798,9 +3840,9 @@
       }
     },
     "node_modules/eslint-plugin-vue": {
-      "version": "9.26.0",
-      "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.26.0.tgz",
-      "integrity": "sha512-eTvlxXgd4ijE1cdur850G6KalZqk65k1JKoOI2d1kT3hr8sPD07j1q98FRFdNnpxBELGPWxZmInxeHGF/GxtqQ==",
+      "version": "9.27.0",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.27.0.tgz",
+      "integrity": "sha512-5Dw3yxEyuBSXTzT5/Ge1X5kIkRTQ3nvBn/VwPwInNiZBSJOO/timWMUaflONnFBzU6NhB68lxnCda7ULV5N7LA==",
       "dev": true,
       "dependencies": {
         "@eslint-community/eslint-utils": "^4.4.0",
@@ -3809,7 +3851,7 @@
         "nth-check": "^2.1.1",
         "postcss-selector-parser": "^6.0.15",
         "semver": "^7.6.0",
-        "vue-eslint-parser": "^9.4.2",
+        "vue-eslint-parser": "^9.4.3",
         "xml-name-validator": "^4.0.0"
       },
       "engines": {
@@ -5657,9 +5699,9 @@
       }
     },
     "node_modules/postcss": {
-      "version": "8.4.38",
-      "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz",
-      "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==",
+      "version": "8.4.39",
+      "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.39.tgz",
+      "integrity": "sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==",
       "funding": [
         {
           "type": "opencollective",
@@ -5676,7 +5718,7 @@
       ],
       "dependencies": {
         "nanoid": "^3.3.7",
-        "picocolors": "^1.0.0",
+        "picocolors": "^1.0.1",
         "source-map-js": "^1.2.0"
       },
       "engines": {
@@ -6533,9 +6575,9 @@
       }
     },
     "node_modules/typescript": {
-      "version": "5.5.2",
-      "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.2.tgz",
-      "integrity": "sha512-NcRtPEOsPFFWjobJEtfihkLCZCXZt/os3zf8nTxjVH3RvTSxjrCamJpbExGvYOF+tFHc3pA65qpdwPbzjohhew==",
+      "version": "5.5.3",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz",
+      "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==",
       "devOptional": true,
       "bin": {
         "tsc": "bin/tsc",
@@ -6624,9 +6666,9 @@
       }
     },
     "node_modules/vite": {
-      "version": "5.3.1",
-      "resolved": "https://registry.npmjs.org/vite/-/vite-5.3.1.tgz",
-      "integrity": "sha512-XBmSKRLXLxiaPYamLv3/hnP/KXDai1NDexN0FpkTaZXTfycHvkRHoenpgl/fvuK/kPbB6xAgoyiryAhQNxYmAQ==",
+      "version": "5.3.2",
+      "resolved": "https://registry.npmjs.org/vite/-/vite-5.3.2.tgz",
+      "integrity": "sha512-6lA7OBHBlXUxiJxbO5aAY2fsHHzDr1q7DvXYnyZycRs2Dz+dXBWuhpWHvmljTRTpQC2uvGmUFFkSHF2vGo90MA==",
       "dev": true,
       "dependencies": {
         "esbuild": "^0.21.3",
@@ -6678,73 +6720,479 @@
         }
       }
     },
-    "node_modules/vscode-uri": {
-      "version": "3.0.8",
-      "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz",
-      "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==",
-      "dev": true
+    "node_modules/vite/node_modules/@esbuild/aix-ppc64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
+      "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==",
+      "cpu": [
+        "ppc64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "aix"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
     },
-    "node_modules/vue": {
-      "version": "3.4.30",
-      "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.30.tgz",
-      "integrity": "sha512-NcxtKCwkdf1zPsr7Y8+QlDBCGqxvjLXF2EX+yi76rV5rrz90Y6gK1cq0olIhdWGgrlhs9ElHuhi9t3+W5sG5Xw==",
-      "dependencies": {
-        "@vue/compiler-dom": "3.4.30",
-        "@vue/compiler-sfc": "3.4.30",
-        "@vue/runtime-dom": "3.4.30",
-        "@vue/server-renderer": "3.4.30",
-        "@vue/shared": "3.4.30"
-      },
-      "peerDependencies": {
-        "typescript": "*"
-      },
-      "peerDependenciesMeta": {
-        "typescript": {
-          "optional": true
-        }
+    "node_modules/vite/node_modules/@esbuild/android-arm": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz",
+      "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=12"
       }
     },
-    "node_modules/vue-eslint-parser": {
-      "version": "9.4.3",
-      "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.3.tgz",
-      "integrity": "sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg==",
+    "node_modules/vite/node_modules/@esbuild/android-arm64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz",
+      "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==",
+      "cpu": [
+        "arm64"
+      ],
       "dev": true,
-      "dependencies": {
-        "debug": "^4.3.4",
-        "eslint-scope": "^7.1.1",
-        "eslint-visitor-keys": "^3.3.0",
-        "espree": "^9.3.1",
-        "esquery": "^1.4.0",
-        "lodash": "^4.17.21",
-        "semver": "^7.3.6"
-      },
+      "optional": true,
+      "os": [
+        "android"
+      ],
       "engines": {
-        "node": "^14.17.0 || >=16.0.0"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/mysticatea"
-      },
-      "peerDependencies": {
-        "eslint": ">=6.0.0"
+        "node": ">=12"
       }
     },
-    "node_modules/vue-matomo": {
-      "version": "4.2.0",
-      "resolved": "https://registry.npmjs.org/vue-matomo/-/vue-matomo-4.2.0.tgz",
-      "integrity": "sha512-m5hCw7LH3wPDcERaF4sp/ojR9sEx7Rl8TpOyH/4jjQxMF2DuY/q5pO+i9o5Dx+BXLSa9+IQ0qhAbWYRyESQXmA==",
+    "node_modules/vite/node_modules/@esbuild/android-x64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz",
+      "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "android"
+      ],
       "engines": {
-        "node": ">= 6.0.0",
-        "npm": ">= 3.0.0"
+        "node": ">=12"
       }
     },
-    "node_modules/vue-router": {
-      "version": "4.4.0",
-      "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.4.0.tgz",
-      "integrity": "sha512-HB+t2p611aIZraV2aPSRNXf0Z/oLZFrlygJm+sZbdJaW6lcFqEDQwnzUBXn+DApw+/QzDU/I9TeWx9izEjTmsA==",
-      "dependencies": {
-        "@vue/devtools-api": "^6.5.1"
-      },
-      "funding": {
+    "node_modules/vite/node_modules/@esbuild/darwin-arm64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz",
+      "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/vite/node_modules/@esbuild/darwin-x64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz",
+      "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/vite/node_modules/@esbuild/freebsd-arm64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz",
+      "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "freebsd"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/vite/node_modules/@esbuild/freebsd-x64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz",
+      "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "freebsd"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/vite/node_modules/@esbuild/linux-arm": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz",
+      "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/vite/node_modules/@esbuild/linux-arm64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz",
+      "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/vite/node_modules/@esbuild/linux-ia32": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz",
+      "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==",
+      "cpu": [
+        "ia32"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/vite/node_modules/@esbuild/linux-loong64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz",
+      "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==",
+      "cpu": [
+        "loong64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/vite/node_modules/@esbuild/linux-mips64el": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz",
+      "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==",
+      "cpu": [
+        "mips64el"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/vite/node_modules/@esbuild/linux-ppc64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz",
+      "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==",
+      "cpu": [
+        "ppc64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/vite/node_modules/@esbuild/linux-riscv64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz",
+      "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==",
+      "cpu": [
+        "riscv64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/vite/node_modules/@esbuild/linux-s390x": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz",
+      "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==",
+      "cpu": [
+        "s390x"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/vite/node_modules/@esbuild/linux-x64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz",
+      "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/vite/node_modules/@esbuild/netbsd-x64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz",
+      "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "netbsd"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/vite/node_modules/@esbuild/openbsd-x64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz",
+      "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "openbsd"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/vite/node_modules/@esbuild/sunos-x64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz",
+      "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "sunos"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/vite/node_modules/@esbuild/win32-arm64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz",
+      "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/vite/node_modules/@esbuild/win32-ia32": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz",
+      "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==",
+      "cpu": [
+        "ia32"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/vite/node_modules/@esbuild/win32-x64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz",
+      "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/vite/node_modules/esbuild": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz",
+      "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==",
+      "dev": true,
+      "hasInstallScript": true,
+      "bin": {
+        "esbuild": "bin/esbuild"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "optionalDependencies": {
+        "@esbuild/aix-ppc64": "0.21.5",
+        "@esbuild/android-arm": "0.21.5",
+        "@esbuild/android-arm64": "0.21.5",
+        "@esbuild/android-x64": "0.21.5",
+        "@esbuild/darwin-arm64": "0.21.5",
+        "@esbuild/darwin-x64": "0.21.5",
+        "@esbuild/freebsd-arm64": "0.21.5",
+        "@esbuild/freebsd-x64": "0.21.5",
+        "@esbuild/linux-arm": "0.21.5",
+        "@esbuild/linux-arm64": "0.21.5",
+        "@esbuild/linux-ia32": "0.21.5",
+        "@esbuild/linux-loong64": "0.21.5",
+        "@esbuild/linux-mips64el": "0.21.5",
+        "@esbuild/linux-ppc64": "0.21.5",
+        "@esbuild/linux-riscv64": "0.21.5",
+        "@esbuild/linux-s390x": "0.21.5",
+        "@esbuild/linux-x64": "0.21.5",
+        "@esbuild/netbsd-x64": "0.21.5",
+        "@esbuild/openbsd-x64": "0.21.5",
+        "@esbuild/sunos-x64": "0.21.5",
+        "@esbuild/win32-arm64": "0.21.5",
+        "@esbuild/win32-ia32": "0.21.5",
+        "@esbuild/win32-x64": "0.21.5"
+      }
+    },
+    "node_modules/vscode-uri": {
+      "version": "3.0.8",
+      "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz",
+      "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==",
+      "dev": true
+    },
+    "node_modules/vue": {
+      "version": "3.4.31",
+      "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.31.tgz",
+      "integrity": "sha512-njqRrOy7W3YLAlVqSKpBebtZpDVg21FPoaq1I7f/+qqBThK9ChAIjkRWgeP6Eat+8C+iia4P3OYqpATP21BCoQ==",
+      "dependencies": {
+        "@vue/compiler-dom": "3.4.31",
+        "@vue/compiler-sfc": "3.4.31",
+        "@vue/runtime-dom": "3.4.31",
+        "@vue/server-renderer": "3.4.31",
+        "@vue/shared": "3.4.31"
+      },
+      "peerDependencies": {
+        "typescript": "*"
+      },
+      "peerDependenciesMeta": {
+        "typescript": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/vue-eslint-parser": {
+      "version": "9.4.3",
+      "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.3.tgz",
+      "integrity": "sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg==",
+      "dev": true,
+      "dependencies": {
+        "debug": "^4.3.4",
+        "eslint-scope": "^7.1.1",
+        "eslint-visitor-keys": "^3.3.0",
+        "espree": "^9.3.1",
+        "esquery": "^1.4.0",
+        "lodash": "^4.17.21",
+        "semver": "^7.3.6"
+      },
+      "engines": {
+        "node": "^14.17.0 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/mysticatea"
+      },
+      "peerDependencies": {
+        "eslint": ">=6.0.0"
+      }
+    },
+    "node_modules/vue-matomo": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/vue-matomo/-/vue-matomo-4.2.0.tgz",
+      "integrity": "sha512-m5hCw7LH3wPDcERaF4sp/ojR9sEx7Rl8TpOyH/4jjQxMF2DuY/q5pO+i9o5Dx+BXLSa9+IQ0qhAbWYRyESQXmA==",
+      "engines": {
+        "node": ">= 6.0.0",
+        "npm": ">= 3.0.0"
+      }
+    },
+    "node_modules/vue-router": {
+      "version": "4.4.0",
+      "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.4.0.tgz",
+      "integrity": "sha512-HB+t2p611aIZraV2aPSRNXf0Z/oLZFrlygJm+sZbdJaW6lcFqEDQwnzUBXn+DApw+/QzDU/I9TeWx9izEjTmsA==",
+      "dependencies": {
+        "@vue/devtools-api": "^6.5.1"
+      },
+      "funding": {
         "url": "https://github.com/sponsors/posva"
       },
       "peerDependencies": {
@@ -6762,20 +7210,20 @@
       }
     },
     "node_modules/vue-tsc": {
-      "version": "2.0.22",
-      "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-2.0.22.tgz",
-      "integrity": "sha512-lMBIwPBO0sxCcmvu45yt1b035AaQ8/XSXQDk8m75y4j0jSXY/y/XzfEtssQ9JMS47lDaR10O3/926oCs8OeGUw==",
+      "version": "2.0.24",
+      "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-2.0.24.tgz",
+      "integrity": "sha512-1qi4P8L7yS78A7OJ7CDDxUIZPD6nVxoQEgX3DkRZNi1HI1qOfzOJwQlNpmwkogSVD6S/XcanbW9sktzpSxz6rA==",
       "dev": true,
       "dependencies": {
-        "@volar/typescript": "~2.3.1",
-        "@vue/language-core": "2.0.22",
+        "@volar/typescript": "~2.4.0-alpha.2",
+        "@vue/language-core": "2.0.24",
         "semver": "^7.5.4"
       },
       "bin": {
         "vue-tsc": "bin/vue-tsc.js"
       },
       "peerDependencies": {
-        "typescript": "*"
+        "typescript": ">=5.0.0"
       }
     },
     "node_modules/vue3-cookies": {
diff --git a/package.json b/package.json
index ba9afc0e0c29b0ceea2315aeba1bf7716b6d3ae8..9d3de222c264933b3fcf479e74fa9abdb3aec26c 100644
--- a/package.json
+++ b/package.json
@@ -52,7 +52,7 @@
     "@vue/tsconfig": "~0.5.0",
     "axios": "~1.7.0",
     "eslint": "~8.57.0",
-    "eslint-plugin-vue": "~9.26.0",
+    "eslint-plugin-vue": "~9.27.0",
     "highlight.js": "^11.9.0",
     "npm-run-all": "~4.1.5",
     "openapi-typescript-codegen": "^0.29.0",
diff --git a/src/client/services/WorkflowExecutionService.ts b/src/client/services/WorkflowExecutionService.ts
index 69fd3a4e8c282cce27220ce0c4a9a936e3c04b30..22693fdaefe15666c4775ee28964d7cc58b5f108 100644
--- a/src/client/services/WorkflowExecutionService.ts
+++ b/src/client/services/WorkflowExecutionService.ts
@@ -41,11 +41,20 @@ export class WorkflowExecutionService {
      * Get all workflow executions
      * Get all workflow executions.
      *
-     * Permission `workflow_execution:list` required, if 'user_id' is the same as the current user,
+     * This endpoint enforces keyset pagination. To iterate over all workflow executions, follow the link provided in the
+     * `Link` header.
+     * A missing `Link` header indicates that you iterated over all workflow executions with the current filters.
+     *
+     * Permission `workflow_execution:list` required, if `executor_id` is the same as the current user,
      * otherwise `workflow_execution:list_all` required.
      * @param executorId Filter for workflow executions by a user. If none, Permission `workflow_execution:read_any` required.
      * @param executionStatus Filter for status of workflow execution
      * @param workflowVersionId Filter for workflow version
+     * @param startAfter Filter for workflow executions that started after this UNIX timestamp
+     * @param startBefore Filter for workflow executions that started before this UNIX timestamp
+     * @param idAfter Id of the item to start the query from. DO NOT SET MANUALLY.
+     * @param perPage Number of items to list per page
+     * @param sort Sort order of items with creation time
      * @returns WorkflowExecutionOut Successful Response
      * @throws ApiError
      */
@@ -53,6 +62,11 @@ export class WorkflowExecutionService {
         executorId?: string,
         executionStatus?: Array<WorkflowExecutionStatus>,
         workflowVersionId?: string,
+        startAfter?: number,
+        startBefore?: number,
+        idAfter?: string,
+        perPage: number = 20,
+        sort: 'asc' | 'desc' = 'desc',
     ): CancelablePromise<Array<WorkflowExecutionOut>> {
         return __request(OpenAPI, {
             method: 'GET',
@@ -61,6 +75,11 @@ export class WorkflowExecutionService {
                 'executor_id': executorId,
                 'execution_status': executionStatus,
                 'workflow_version_id': workflowVersionId,
+                'start_after': startAfter,
+                'start_before': startBefore,
+                'id_after': idAfter,
+                'per_page': perPage,
+                'sort': sort,
             },
             errors: {
                 400: `Error decoding JWT Token`,
diff --git a/src/components/AppHeader.vue b/src/components/AppHeader.vue
index 331c790cda5193e6e020161ee04d0035325acada..4336dfa33e226bbcbc98b938af1a455d7c1595e4 100644
--- a/src/components/AppHeader.vue
+++ b/src/components/AppHeader.vue
@@ -234,6 +234,13 @@ watch(
                   >Buckets
                 </router-link>
               </li>
+              <li>
+                <router-link
+                  class="dropdown-item"
+                  :to="{ name: 'admin-executions' }"
+                  >Workflow Executions
+                </router-link>
+              </li>
               <li>
                 <router-link
                   class="dropdown-item"
diff --git a/src/components/modals/SearchWorkflowVersionModal.vue b/src/components/modals/SearchWorkflowVersionModal.vue
new file mode 100644
index 0000000000000000000000000000000000000000..402133f7db76f22993d21099e74bcce062f0c528
--- /dev/null
+++ b/src/components/modals/SearchWorkflowVersionModal.vue
@@ -0,0 +1,181 @@
+<script setup lang="ts">
+import BootstrapModal from "@/components/modals/BootstrapModal.vue";
+import { computed, onMounted, reactive } from "vue";
+import type { UserOut, WorkflowOut, WorkflowVersion } from "@/client";
+import { useWorkflowStore } from "@/stores/workflows";
+import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue";
+
+const props = defineProps<{
+  modalId: string;
+  backModalId?: string;
+}>();
+const randomIDSuffix = Math.random().toString(16).substring(2, 8);
+
+const workflowRepository = useWorkflowStore();
+
+const formState = reactive<{
+  searchString: string;
+  potentialUsers: UserOut[];
+  lastSearchTimerId: ReturnType<typeof setTimeout> | null;
+  error: boolean;
+  loading: boolean;
+}>({
+  searchString: "",
+  potentialUsers: [],
+  lastSearchTimerId: null,
+  error: false,
+  loading: false,
+});
+
+const emit = defineEmits<{
+  (
+    e: "workflow-found",
+    workflow: WorkflowOut,
+    workflowVersion: WorkflowVersion,
+  ): void;
+}>();
+
+const workflows = computed<WorkflowOut[]>(() => {
+  if (formState.searchString.length > 0) {
+    return workflowRepository.workflows.filter((workflow) =>
+      workflow.name
+        .toLowerCase()
+        .includes(formState.searchString.toLowerCase()),
+    );
+  }
+  return workflowRepository.workflows;
+});
+
+function modalClosed() {
+  formState.searchString = "";
+  formState.potentialUsers = [];
+}
+
+onMounted(() => {
+  workflowRepository.fetchWorkflows();
+});
+</script>
+
+<template>
+  <bootstrap-modal
+    :modalId="props.modalId"
+    :static-backdrop="true"
+    modal-label="Search User Modal"
+    v-on="{ 'hidden.bs.modal': modalClosed }"
+  >
+    <template #header>Search Workflow Version</template>
+    <template #body>
+      <div class="input-group mt-2 mb-4">
+        <span class="input-group-text"
+          ><font-awesome-icon icon="fa-solid fa-magnifying-glass"
+        /></span>
+        <input
+          class="form-control"
+          placeholder="Search for a workflow"
+          v-model.trim="formState.searchString"
+          maxlength="10"
+        />
+      </div>
+      <div
+        class="accordion"
+        :id="`accordion-${randomIDSuffix}`"
+        v-if="workflows.length > 0"
+      >
+        <div
+          class="accordion-item"
+          v-for="workflow of workflows"
+          :key="workflow.workflow_id"
+        >
+          <h2 class="accordion-header">
+            <button
+              class="accordion-button collapsed"
+              type="button"
+              data-bs-toggle="collapse"
+              :data-bs-target="`#collapse-workflow-${workflow.workflow_id}-${randomIDSuffix}`"
+              :aria-controls="`collapse-workflow-${workflow.workflow_id}-${randomIDSuffix}`"
+            >
+              {{ workflow.name }}
+            </button>
+          </h2>
+          <div
+            :id="`collapse-workflow-${workflow.workflow_id}-${randomIDSuffix}`"
+            class="accordion-collapse collapse"
+            :data-bs-parent="`#accordion-${randomIDSuffix}`"
+          >
+            <div class="accordion-body">
+              <div class="list-group">
+                <button
+                  v-for="version of workflow.versions"
+                  :key="version.workflow_version_id"
+                  type="button"
+                  :data-bs-target="
+                    props.backModalId ? '#' + props.backModalId : null
+                  "
+                  :data-bs-toggle="props.backModalId ? 'modal' : null"
+                  :data-bs-dismiss="props.backModalId ? null : 'modal'"
+                  @click="emit('workflow-found', workflow, version)"
+                  class="list-group-item list-group-item-action"
+                >
+                  {{ version.version }}
+                  <img
+                    v-if="version.icon_url"
+                    class="float-end"
+                    :src="version.icon_url"
+                    width="16"
+                    height="16"
+                  />
+                </button>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+      <div
+        v-else-if="formState.searchString.length > 0"
+        class="text-center fs-4"
+      >
+        <font-awesome-icon
+          icon="fa-solid fa-magnifying-glass"
+          class="mb-2"
+          style="color: var(--bs-secondary); font-size: 3em"
+        />
+        <br />
+        <span
+          >Can't find workflow that contains <br />'{{
+            formState.searchString
+          }}'</span
+        >
+      </div>
+      <div v-else class="text-center fs-4">
+        <font-awesome-icon
+          icon="fa-solid fa-xmark"
+          class="mb-2"
+          style="color: var(--bs-secondary); font-size: 3em"
+        />
+        <br />
+        <span>There are no workflows in the system</span>
+      </div>
+    </template>
+    <template v-slot:footer>
+      <button
+        v-if="backModalId"
+        type="button"
+        class="btn btn-secondary"
+        :data-bs-target="'#' + props.backModalId"
+        data-bs-toggle="modal"
+      >
+        Back
+      </button>
+      <button
+        v-else
+        type="button"
+        class="btn btn-secondary"
+        data-bs-dismiss="modal"
+      >
+        Close
+      </button>
+    </template>
+  </bootstrap-modal>
+</template>
+
+<style scoped></style>
diff --git a/src/components/workflows/modals/ParameterModal.vue b/src/components/workflows/modals/ParameterModal.vue
index 3ce9657903d6fe6b5554e6983cbc3b19d87c4dc2..ef981fc20d011fdeec86d5decd5568d49b5992de 100644
--- a/src/components/workflows/modals/ParameterModal.vue
+++ b/src/components/workflows/modals/ParameterModal.vue
@@ -15,6 +15,7 @@ import type {
   FlatWorkflowParameters,
 } from "@/types/WorkflowParameters";
 import { flattenParameters } from "@/utils/Workflow";
+import MarkdownRenderer from "@/components/MarkdownRenderer.vue";
 
 const nameRepository = useNameStore();
 const executionRepository = useWorkflowExecutionStore();
@@ -228,6 +229,12 @@ onMounted(() => {
             </tr>
           </template>
           <template v-else>
+            <tr v-if="execution?.notes">
+              <th scope="row" class="text-end"><b>Notes</b></th>
+              <th>
+                <markdown-renderer :markdown="execution.notes" />
+              </th>
+            </tr>
             <tr
               v-if="logs_s3_path"
               :class="{
diff --git a/src/router/adminRoutes.ts b/src/router/adminRoutes.ts
index 0567cbdb46f65f1584f72a6117626751edc73ce2..e5e6e9ca7a16017b977368b6c2d0d318e09f607b 100644
--- a/src/router/adminRoutes.ts
+++ b/src/router/adminRoutes.ts
@@ -28,6 +28,15 @@ export const adminRoutes: RouteRecordRaw[] = [
       title: "Manage Buckets",
     },
   },
+  {
+    path: "admin/executions",
+    name: "admin-executions",
+    component: () => import("../views/admin/AdminWorkflowExecutionView.vue"),
+    meta: {
+      requiresAdminRole: true,
+      title: "Manage Executions",
+    },
+  },
   {
     path: "admin/sync-requests",
     name: "admin-sync-requests",
diff --git a/src/stores/workflowExecutions.ts b/src/stores/workflowExecutions.ts
index d7bfd93dcee26b5c183092f811648e86a656a041..2389f45e95b9f6c31a81fe38b027b85e390cebf3 100644
--- a/src/stores/workflowExecutions.ts
+++ b/src/stores/workflowExecutions.ts
@@ -1,9 +1,10 @@
 import { defineStore } from "pinia";
-import type {
-  AnonymizedWorkflowExecution,
-  DevWorkflowExecutionIn,
-  WorkflowExecutionIn,
-  WorkflowExecutionOut,
+import {
+  type AnonymizedWorkflowExecution,
+  type DevWorkflowExecutionIn,
+  OpenAPI,
+  type WorkflowExecutionIn,
+  type WorkflowExecutionOut,
 } from "@/client";
 import {
   WorkflowExecutionService,
@@ -18,6 +19,21 @@ import type {
   WorkflowMetaParameters,
   TemporaryParams,
 } from "@/types/WorkflowParameters";
+import axios from "axios";
+import { getQueryString } from "@/client/core/request";
+
+function extractNextPage(linkHeader?: string): string | undefined {
+  if (linkHeader == undefined) {
+    return undefined;
+  }
+  for (const link of linkHeader.split(",")) {
+    const linkParts = link.split(";");
+    if (linkParts[1]?.trim()?.split("=")?.[1]?.slice(1, -1) === "next") {
+      return linkParts[0].slice(1, -1);
+    }
+  }
+  return undefined;
+}
 
 export const useWorkflowExecutionStore = defineStore({
   id: "workflow-executions",
@@ -41,6 +57,44 @@ export const useWorkflowExecutionStore = defineStore({
     },
   },
   actions: {
+    fetchExecutionsRaw: async function* (
+      executorId?: string,
+      executionStatus?: Array<WorkflowExecutionStatus>,
+      workflowVersionId?: string,
+      startAfter?: number,
+      startBefore?: number,
+      perPage: number = 20,
+      sort: "asc" | "desc" = "desc",
+    ): AsyncGenerator<WorkflowExecutionOut[], void, unknown> {
+      const userRepository = useUserStore();
+      let response = await axios.get<WorkflowExecutionOut[]>(
+        `/workflow_executions${getQueryString({
+          executor_id: executorId,
+          execution_status: executionStatus,
+          workflow_version_id: workflowVersionId,
+          start_after: startAfter,
+          start_before: startBefore,
+          per_page: perPage,
+          sort: sort,
+        })}`,
+        {
+          baseURL: OpenAPI.BASE,
+        },
+      );
+      userRepository.fetchUsernames(
+        response.data.map((execution) => execution.executor_id),
+      );
+      yield response.data;
+      let nextUrl = extractNextPage(response.headers["link"]);
+      while (nextUrl != undefined) {
+        response = await axios.get(nextUrl);
+        userRepository.fetchUsernames(
+          response.data.map((execution) => execution.executor_id),
+        );
+        yield response.data;
+        nextUrl = extractNextPage(response.headers["link"]);
+      }
+    },
     pushTemporaryParameters(
       params: FlatWorkflowParameters,
       metaParams?: WorkflowMetaParameters,
@@ -74,23 +128,35 @@ export const useWorkflowExecutionStore = defineStore({
         })
         .finally(onFinally);
     },
-    fetchExecutions(onFinally?: () => void): Promise<WorkflowExecutionOut[]> {
-      if (Object.keys(this.executionMapping).length > 0) {
+    async fetchExecutions(
+      onFinally?: () => void,
+    ): Promise<WorkflowExecutionOut[]> {
+      if (this.executions.length > 0) {
         onFinally?.();
       }
       const userStore = useUserStore();
-      return WorkflowExecutionService.workflowExecutionListWorkflowExecutions(
-        userStore.currentUID,
-      )
-        .then((executions) => {
-          const newMapping: Record<string, WorkflowExecutionOut> = {};
+      const newMapping: Record<string, WorkflowExecutionOut> = {};
+      const allExecutions: WorkflowExecutionOut[] = [];
+      try {
+        for await (const executions of this.fetchExecutionsRaw(
+          userStore.currentUID,
+          undefined,
+          undefined,
+          undefined,
+          undefined,
+          50,
+        )) {
+          onFinally?.();
           for (const execution of executions) {
             newMapping[execution.execution_id] = execution;
           }
-          this.executionMapping = newMapping;
-          return executions;
-        })
-        .finally(onFinally);
+          allExecutions.push(...executions);
+        }
+        this.executionMapping = newMapping;
+        return allExecutions;
+      } finally {
+        onFinally?.();
+      }
     },
     fetchExecution(
       executionId: string,
diff --git a/src/views/admin/AdminWorkflowExecutionView.vue b/src/views/admin/AdminWorkflowExecutionView.vue
new file mode 100644
index 0000000000000000000000000000000000000000..0b0936cf50ae7e30290a93b7d2b3cc99c0a2dfb2
--- /dev/null
+++ b/src/views/admin/AdminWorkflowExecutionView.vue
@@ -0,0 +1,486 @@
+<script setup lang="ts">
+import { computed, nextTick, onMounted, reactive, ref } from "vue";
+import {
+  type UserOut,
+  type WorkflowExecutionOut,
+  WorkflowExecutionStatus,
+  type WorkflowOut,
+  type WorkflowVersion,
+} from "@/client";
+import SearchUserModal from "@/components/modals/SearchUserModal.vue";
+import SearchWorkflowModal from "@/components/modals/SearchWorkflowVersionModal.vue";
+import { useWorkflowExecutionStore } from "@/stores/workflowExecutions";
+import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue";
+import { useNameStore } from "@/stores/names";
+import dayjs from "dayjs";
+import ParameterModal from "@/components/workflows/modals/ParameterModal.vue";
+
+const executionRepository = useWorkflowExecutionStore();
+const nameRepository = useNameStore();
+
+const statusToColorMapping = {
+  PENDING: "bg-warning",
+  SCHEDULED: "bg-warning",
+  RUNNING: "bg-info",
+  CANCELED: "bg-danger",
+  SUCCESS: "bg-success",
+  ERROR: "bg-danger",
+};
+
+const statusToIconMapping = {
+  PENDING: "fa-solid fa-circle-pause",
+  SCHEDULED: "fa-solid fa-circle-pause",
+  RUNNING: "fa-solid fa-circle-play",
+  CANCELED: "fa-solid fa-circle-xmark",
+  SUCCESS: "fa-solid fa-circle-check",
+  ERROR: "fa-solid fa-circle-xmark",
+};
+
+let loadingObserver: IntersectionObserver;
+const endOfTableElement = ref<HTMLDivElement | undefined>(undefined);
+
+const filters = reactive<{
+  executorId?: string;
+  executionStatus?: WorkflowExecutionStatus[];
+  workflowVersionId?: string;
+  startAfter?: number;
+  startBefore?: number;
+  sort: "asc" | "desc";
+  workflowId?: string;
+}>({
+  executorId: undefined,
+  executionStatus: undefined,
+  workflowVersionId: undefined,
+  startAfter: undefined,
+  startBefore: undefined,
+  sort: "desc",
+  workflowId: undefined,
+});
+
+const formState = reactive<{
+  loading: boolean;
+  executions: WorkflowExecutionOut[];
+  executionParameters?: string;
+}>({
+  loading: false,
+  executions: [],
+  executionParameters: undefined,
+});
+
+const executionIterator = ref<
+  AsyncGenerator<WorkflowExecutionOut[], void, never> | undefined
+>(undefined);
+
+const workflowVersionName = computed<string>(() => {
+  if (
+    filters.workflowId != undefined &&
+    filters.workflowVersionId != undefined
+  ) {
+    return `${nameRepository.getName(filters.workflowId)}@${nameRepository.getName(filters.workflowVersionId)}`;
+  }
+  return "";
+});
+
+function updateUser(user: UserOut) {
+  filters.executorId = user.uid;
+}
+
+function updateWorkflow(
+  workflow: WorkflowOut,
+  workflowVersion: WorkflowVersion,
+) {
+  filters.workflowVersionId = workflowVersion.workflow_version_id;
+  filters.workflowId = workflow.workflow_id;
+}
+
+function searchExecution() {
+  loadingObserver.disconnect();
+  formState.loading = true;
+  formState.executions = [];
+  executionIterator.value = executionRepository.fetchExecutionsRaw(
+    filters.executorId,
+    filters.executionStatus,
+    filters.workflowVersionId,
+    filters.startAfter,
+    filters.startBefore,
+    30,
+    filters.sort,
+  );
+  loadNextExecutions();
+}
+
+function loadNextExecutions() {
+  formState.loading = true;
+  executionIterator.value
+    ?.next()
+    .then((executions) => {
+      if (executions.done ?? false) {
+        return;
+      }
+      formState.executions.push(...executions.value);
+      nextTick(() => {
+        if (endOfTableElement.value != undefined) {
+          loadingObserver.observe(endOfTableElement.value);
+        }
+      });
+    })
+    .finally(() => {
+      formState.loading = false;
+    });
+}
+
+function cancelWorkflowExecution(executionId: string) {
+  executionRepository.cancelExecution(executionId).then(() => {
+    const index = formState.executions.findIndex(
+      (execution) => execution.execution_id === executionId,
+    );
+    if (index > -1) {
+      formState.executions[index].status = WorkflowExecutionStatus.CANCELED;
+      formState.executions[index].end_time = dayjs().unix();
+    }
+  });
+}
+
+function workflowExecutionCancelable(execution: WorkflowExecutionOut): boolean {
+  return execution.end_time == undefined;
+}
+
+function startBeforeTimestampChanged(target?: HTMLInputElement | null) {
+  filters.startBefore = target?.value ? dayjs(target?.value).unix() : undefined;
+}
+
+function startAfterTimestampChanged(target?: HTMLInputElement | null) {
+  filters.startAfter = target?.value ? dayjs(target?.value).unix() : undefined;
+}
+
+function resetForm() {
+  loadingObserver.disconnect();
+  filters.executorId = undefined;
+  filters.executorId = undefined;
+  filters.executionStatus = undefined;
+  filters.workflowVersionId = undefined;
+  filters.workflowId = undefined;
+  filters.startAfter = undefined;
+  filters.startBefore = undefined;
+  filters.sort = "desc";
+  executionIterator.value = undefined;
+  formState.executions = [];
+}
+
+onMounted(() => {
+  loadingObserver = new IntersectionObserver(
+    (entries) => {
+      if (entries.length > 0 && entries[0].isIntersecting) {
+        loadingObserver.unobserve(entries[0].target);
+        loadNextExecutions();
+      }
+    },
+    {
+      threshold: 0,
+    },
+  );
+});
+</script>
+
+<template>
+  <search-user-modal
+    modal-id="admin-execution-search-user-modal"
+    @user-found="updateUser"
+  />
+  <search-workflow-modal
+    modal-id="admin-execution-search-workflow-modal"
+    @workflow-found="updateWorkflow"
+  />
+  <parameter-modal
+    modal-id="workflowExecutionParameterModal"
+    :execution-id="formState.executionParameters"
+  />
+  <div class="border-bottom mb-4">
+    <h2>Search Workflow Execution</h2>
+  </div>
+  <form @submit.prevent="searchExecution" id="admin-execution-search-form">
+    <div class="d-flex justify-content-evenly align-content-center mb-4">
+      <div class="mx-2">
+        <label for="admin-execution-state-select" class="form-label"
+          >Status of Workflow Execution</label
+        >
+        <select
+          v-model="filters.executionStatus"
+          multiple
+          class="form-select"
+          id="admin-execution-state-select"
+        >
+          <option
+            v-for="state in Object.values(WorkflowExecutionStatus)"
+            :key="state"
+          >
+            {{ state }}
+          </option>
+        </select>
+        <div class="form-label mb-0 mt-1">Sort:</div>
+        <div class="form-check form-check-inline">
+          <input
+            class="form-check-input"
+            type="radio"
+            name="flexRadioDefault"
+            id="flexRadioDefault1"
+            value="asc"
+            v-model="filters.sort"
+          />
+          <label class="form-check-label" for="flexRadioDefault1"> Asc </label>
+        </div>
+        <div class="form-check form-check-inline">
+          <input
+            class="form-check-input"
+            type="radio"
+            name="flexRadioDefault"
+            id="flexRadioDefault2"
+            value="desc"
+            v-model="filters.sort"
+          />
+          <label class="form-check-label" for="flexRadioDefault2"> Desc </label>
+        </div>
+      </div>
+      <div class="flex-fill mx-2">
+        <label for="admin-execution-start-after-search" class="form-label"
+          >Start after</label
+        >
+        <div class="input-group mb-2">
+          <div class="input-group-text">
+            <font-awesome-icon icon="fa-solid fa-hourglass-start" />
+          </div>
+          <input
+            class="form-control"
+            id="admin-execution-start-after-search"
+            type="datetime-local"
+            :max="dayjs().format('YYYY-MM-DDTHH:mm')"
+            :value="
+              filters.startAfter
+                ? dayjs.unix(filters.startAfter).format('YYYY-MM-DDTHH:mm')
+                : undefined
+            "
+            @input="
+              (event) =>
+                startAfterTimestampChanged(event.target as HTMLInputElement)
+            "
+          />
+        </div>
+        <label for="admin-execution-start-before-search" class="form-label"
+          >Start before</label
+        >
+        <div class="input-group">
+          <div class="input-group-text">
+            <font-awesome-icon icon="fa-solid fa-hourglass-end" />
+          </div>
+          <input
+            class="form-control"
+            id="admin-execution-start-before-search"
+            type="datetime-local"
+            :max="dayjs().format('YYYY-MM-DDTHH:mm')"
+            :value="
+              filters.startBefore
+                ? dayjs.unix(filters.startBefore).format('YYYY-MM-DDTHH:mm')
+                : undefined
+            "
+            @input="
+              (event) =>
+                startBeforeTimestampChanged(event.target as HTMLInputElement)
+            "
+          />
+        </div>
+      </div>
+      <div class="flex-fill mx-2">
+        <label for="admin-execution-user-search" class="form-label"
+          >Name of the owner</label
+        >
+        <div class="input-group mb-2">
+          <div class="input-group-text">
+            <font-awesome-icon icon="fa-solid fa-user" />
+          </div>
+          <input
+            id="admin-execution-user-search"
+            type="text"
+            class="form-control"
+            readonly
+            :value="nameRepository.getName(filters.executorId)"
+            placeholder="Search for owner"
+            data-bs-toggle="modal"
+            data-bs-target="#admin-execution-search-user-modal"
+          />
+        </div>
+        <label for="admin-execution-workflow-search" class="form-label"
+          >Workflow Version</label
+        >
+        <div class="input-group">
+          <div class="input-group-text">
+            <font-awesome-icon icon="fa-solid fa-tag" />
+          </div>
+          <input
+            id="admin-execution-workflow-search"
+            type="text"
+            class="form-control"
+            readonly
+            :value="workflowVersionName"
+            placeholder="Search for workflow version"
+            data-bs-toggle="modal"
+            data-bs-target="#admin-execution-search-workflow-modal"
+          />
+        </div>
+      </div>
+    </div>
+    <button
+      type="submit"
+      class="btn btn-primary w-fit"
+      :disabled="formState.loading"
+    >
+      Search
+    </button>
+    <button
+      type="button"
+      class="btn-primary btn w-fit ms-4"
+      :disabled="formState.loading"
+      @click="resetForm"
+    >
+      Clear
+    </button>
+  </form>
+  <table class="table table-hover align-middle" ref="executionTable">
+    <caption>
+      Displaying
+      {{
+        formState.executions.length
+      }}
+      Workflow Execution
+    </caption>
+    <thead>
+      <tr>
+        <th scope="col">Workflow</th>
+        <th scope="col">Status</th>
+        <th scope="col">Started</th>
+        <th scope="col">Duration</th>
+        <th scope="col">Ended</th>
+        <th scope="col">User</th>
+        <th scope="col"></th>
+      </tr>
+    </thead>
+    <tbody>
+      <template v-if="formState.executions.length > 0">
+        <tr
+          v-for="execution in formState.executions"
+          :key="execution.execution_id"
+          :id="`admin-execution-${execution.execution_id}`"
+        >
+          <td>
+            <router-link
+              v-if="execution.workflow_id && execution.workflow_version_id"
+              :to="{
+                name: 'workflow-version',
+                params: {
+                  versionId: execution.workflow_version_id,
+                  workflowId: execution.workflow_id,
+                },
+              }"
+            >
+              {{ nameRepository.getName(execution.workflow_id) }}@{{
+                nameRepository.getName(execution.workflow_version_id)
+              }}
+            </router-link>
+          </td>
+          <td>
+            <span
+              class="rounded-pill py-1 px-2 text-light"
+              :class="statusToColorMapping[execution.status]"
+              ><font-awesome-icon
+                class="me-2"
+                :icon="statusToIconMapping[execution.status]"
+              />{{ execution.status }}</span
+            >
+          </td>
+          <td>
+            {{ dayjs.unix(execution.start_time).format("DD.MM.YYYY HH:mm") }}
+          </td>
+          <td>
+            <template v-if="execution.end_time">
+              {{
+                dayjs
+                  .duration(
+                    execution.end_time - execution.start_time,
+                    "seconds",
+                  )
+                  .humanize()
+              }}
+            </template>
+            <template v-else> -</template>
+          </td>
+          <td>
+            <template v-if="execution.end_time">
+              {{ dayjs.unix(execution.end_time).format("DD.MM.YYYY HH:mm") }}
+            </template>
+            <template v-else> -</template>
+          </td>
+          <td>
+            {{ nameRepository.getName(execution.executor_id) }}
+          </td>
+          <td class="text-end">
+            <div
+              class="btn-group btn-group-sm dropdown-center dropdown-menu-start"
+            >
+              <button type="button" class="btn btn-secondary" disabled>
+                Details
+              </button>
+              <button
+                type="button"
+                class="btn btn-secondary dropdown-toggle dropdown-toggle-split"
+                data-bs-toggle="dropdown"
+                aria-expanded="false"
+              >
+                <span class="visually-hidden">Toggle Dropdown</span>
+              </button>
+              <ul class="dropdown-menu dropdown-menu">
+                <li>
+                  <button
+                    class="dropdown-item align-middle"
+                    type="button"
+                    data-bs-toggle="modal"
+                    data-bs-target="#workflowExecutionParameterModal"
+                    @click="
+                      formState.executionParameters = execution.execution_id
+                    "
+                  >
+                    <span class="ms-1">Parameters</span>
+                  </button>
+                </li>
+                <li v-if="workflowExecutionCancelable(execution)">
+                  <button
+                    class="dropdown-item text-danger align-middle"
+                    type="button"
+                    @click="cancelWorkflowExecution(execution.execution_id)"
+                  >
+                    <font-awesome-icon icon="fa-solid fa-ban" />
+                    <span class="ms-1">Cancel</span>
+                  </button>
+                </li>
+              </ul>
+            </div>
+          </td>
+        </tr>
+      </template>
+      <tr v-else-if="!formState.loading">
+        <td colspan="7" class="text-center"><i>No workflow executions</i></td>
+      </tr>
+      <tr v-if="formState.loading">
+        <td colspan="7" class="text-center">
+          <div
+            class="spinner-border text-secondary spinner-border-sm"
+            role="status"
+          >
+            <span class="visually-hidden">Loading...</span>
+          </div>
+        </td>
+      </tr>
+    </tbody>
+  </table>
+  <div ref="endOfTableElement"></div>
+</template>
+
+<style scoped></style>