diff --git a/package-lock.json b/package-lock.json
index df1766219a1737e149cfe4d45658530ef415faf1..b3ce605a7ff4fc0bcb2e0f50a0287e59244129ac 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,28 +8,28 @@
       "name": "nacsos-web",
       "version": "0.2.0",
       "dependencies": {
-        "@fortawesome/fontawesome-svg-core": "^6.2.0",
-        "@fortawesome/free-brands-svg-icons": "^6.2.0",
-        "@fortawesome/free-regular-svg-icons": "^6.2.0",
-        "@fortawesome/free-solid-svg-icons": "^6.2.0",
-        "@fortawesome/vue-fontawesome": "^3.0.1",
+        "@fortawesome/fontawesome-svg-core": "^6.2.1",
+        "@fortawesome/free-brands-svg-icons": "^6.2.1",
+        "@fortawesome/free-regular-svg-icons": "^6.2.1",
+        "@fortawesome/free-solid-svg-icons": "^6.2.1",
+        "@fortawesome/vue-fontawesome": "^3.0.2",
         "@vuelidate/core": "^2.0.0",
         "@vuelidate/validators": "^2.0.0",
-        "@vueuse/core": "^9.3.1",
-        "axios": "^1.1.3",
-        "bootstrap": "^5.2.2",
-        "core-js": "^3.26.0",
+        "@vueuse/core": "^9.6.0",
+        "axios": "^1.2.0",
+        "bootstrap": "^5.2.3",
+        "core-js": "^3.26.1",
         "form-data": "^4.0.0",
-        "marked": "^4.1.1",
-        "pinia": "^2.0.23",
-        "vue": "^3.2.41",
+        "marked": "^4.2.3",
+        "pinia": "^2.0.27",
+        "vue": "^3.2.45",
         "vue-router": "^4.1.6"
       },
       "devDependencies": {
         "@rushstack/eslint-patch": "^1.2.0",
         "@types/marked": "^4.0.7",
-        "@typescript-eslint/eslint-plugin": "^5.40.1",
-        "@typescript-eslint/parser": "^5.40.1",
+        "@typescript-eslint/eslint-plugin": "^5.45.0",
+        "@typescript-eslint/parser": "^5.45.0",
         "@vue/cli-plugin-babel": "^5.0.8",
         "@vue/cli-plugin-eslint": "^5.0.8",
         "@vue/cli-plugin-router": "^5.0.8",
@@ -39,16 +39,16 @@
         "@vue/eslint-config-airbnb-with-typescript": "^7.0.0",
         "camelcase": "^6.3.0",
         "commander": "^9.4.1",
-        "eslint": "^8.26.0",
+        "eslint": "^8.28.0",
         "eslint-plugin-import": "^2.26.0",
-        "eslint-plugin-vue": "^9.6.0",
-        "eslint-plugin-vuejs-accessibility": "^1.2.0",
-        "fs-extra": "^10.1.0",
+        "eslint-plugin-vue": "^9.8.0",
+        "eslint-plugin-vuejs-accessibility": "^2.0.0",
+        "fs-extra": "^11.0.0",
         "handlebars": "^4.7.7",
         "json-schema-ref-parser": "^9.0.9",
-        "sass": "^1.55.0",
-        "sass-loader": "^13.1.0",
-        "typescript": "^4.8.4"
+        "sass": "^1.56.1",
+        "sass-loader": "^13.2.0",
+        "typescript": "^4.9.3"
       }
     },
     "node_modules/@achrinza/node-ipc": {
@@ -1780,66 +1780,66 @@
       }
     },
     "node_modules/@fortawesome/fontawesome-common-types": {
-      "version": "6.2.0",
-      "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.2.0.tgz",
-      "integrity": "sha512-rBevIsj2nclStJ7AxTdfsa3ovHb1H+qApwrxcTVo+NNdeJiB9V75hsKfrkG5AwNcRUNxrPPiScGYCNmLMoh8pg==",
+      "version": "6.2.1",
+      "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.2.1.tgz",
+      "integrity": "sha512-Sz07mnQrTekFWLz5BMjOzHl/+NooTdW8F8kDQxjWwbpOJcnoSg4vUDng8d/WR1wOxM0O+CY9Zw0nR054riNYtQ==",
       "hasInstallScript": true,
       "engines": {
         "node": ">=6"
       }
     },
     "node_modules/@fortawesome/fontawesome-svg-core": {
-      "version": "6.2.0",
-      "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.2.0.tgz",
-      "integrity": "sha512-Cf2mAAeMWFMzpLC7Y9H1I4o3wEU+XovVJhTiNG8ZNgSQj53yl7OCJaS80K4YjrABWZzbAHVaoHE1dVJ27AAYXw==",
+      "version": "6.2.1",
+      "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.2.1.tgz",
+      "integrity": "sha512-HELwwbCz6C1XEcjzyT1Jugmz2NNklMrSPjZOWMlc+ZsHIVk+XOvOXLGGQtFBwSyqfJDNgRq4xBCwWOaZ/d9DEA==",
       "hasInstallScript": true,
       "dependencies": {
-        "@fortawesome/fontawesome-common-types": "6.2.0"
+        "@fortawesome/fontawesome-common-types": "6.2.1"
       },
       "engines": {
         "node": ">=6"
       }
     },
     "node_modules/@fortawesome/free-brands-svg-icons": {
-      "version": "6.2.0",
-      "resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-6.2.0.tgz",
-      "integrity": "sha512-fm1y4NyZ2qKYNmYhdMz9VAWRw1Et7PMHNunSw3W0SVAwKwv6o0qiJworLH3Y9SnmhHzAymXJwCX1op22FFvGiA==",
+      "version": "6.2.1",
+      "resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-6.2.1.tgz",
+      "integrity": "sha512-L8l4MfdHPmZlJ72PvzdfwOwbwcCAL0vx48tJRnI6u1PJXh+j2f3yDoKyQgO3qjEsgD5Fr2tQV/cPP8F/k6aUig==",
       "hasInstallScript": true,
       "dependencies": {
-        "@fortawesome/fontawesome-common-types": "6.2.0"
+        "@fortawesome/fontawesome-common-types": "6.2.1"
       },
       "engines": {
         "node": ">=6"
       }
     },
     "node_modules/@fortawesome/free-regular-svg-icons": {
-      "version": "6.2.0",
-      "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.2.0.tgz",
-      "integrity": "sha512-M1dG+PAmkYMTL9BSUHFXY5oaHwBYfHCPhbJ8qj8JELsc9XCrUJ6eEHWip4q0tE+h9C0DVyFkwIM9t7QYyCpprQ==",
+      "version": "6.2.1",
+      "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.2.1.tgz",
+      "integrity": "sha512-wiqcNDNom75x+pe88FclpKz7aOSqS2lOivZeicMV5KRwOAeypxEYWAK/0v+7r+LrEY30+qzh8r2XDaEHvoLsMA==",
       "hasInstallScript": true,
       "dependencies": {
-        "@fortawesome/fontawesome-common-types": "6.2.0"
+        "@fortawesome/fontawesome-common-types": "6.2.1"
       },
       "engines": {
         "node": ">=6"
       }
     },
     "node_modules/@fortawesome/free-solid-svg-icons": {
-      "version": "6.2.0",
-      "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.2.0.tgz",
-      "integrity": "sha512-UjCILHIQ4I8cN46EiQn0CZL/h8AwCGgR//1c4R96Q5viSRwuKVo0NdQEc4bm+69ZwC0dUvjbDqAHF1RR5FA3XA==",
+      "version": "6.2.1",
+      "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.2.1.tgz",
+      "integrity": "sha512-oKuqrP5jbfEPJWTij4sM+/RvgX+RMFwx3QZCZcK9PrBDgxC35zuc7AOFsyMjMd/PIFPeB2JxyqDr5zs/DZFPPw==",
       "hasInstallScript": true,
       "dependencies": {
-        "@fortawesome/fontawesome-common-types": "6.2.0"
+        "@fortawesome/fontawesome-common-types": "6.2.1"
       },
       "engines": {
         "node": ">=6"
       }
     },
     "node_modules/@fortawesome/vue-fontawesome": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/@fortawesome/vue-fontawesome/-/vue-fontawesome-3.0.1.tgz",
-      "integrity": "sha512-CdXZJoCS+aEPec26ZP7hWWU3SaJlQPZSCGdgpQ2qGl2HUmtUUNrI3zC4XWdn1JUmh3t5OuDeRG1qB4eGRNSD4A==",
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/@fortawesome/vue-fontawesome/-/vue-fontawesome-3.0.2.tgz",
+      "integrity": "sha512-xHVtVY8ASUeEvgcA/7vULUesENhD+pi/EirRHdMBqooHlXBqK+yrV6d8tUye1m5UKQKVgYAHMhUBfOnoiwvc8Q==",
       "peerDependencies": {
         "@fortawesome/fontawesome-svg-core": "~1 || ~6",
         "vue": ">= 3.0.0 < 4"
@@ -2398,9 +2398,9 @@
       "dev": true
     },
     "node_modules/@types/semver": {
-      "version": "7.3.12",
-      "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.12.tgz",
-      "integrity": "sha512-WwA1MW0++RfXmCr12xeYOOC5baSC9mSb0ZqCquFzKhcoF4TvHu5MKOuXsncgZcpVFhB1pXd5hZmM0ryAoCp12A==",
+      "version": "7.3.13",
+      "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz",
+      "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==",
       "dev": true
     },
     "node_modules/@types/serve-index": {
@@ -2452,16 +2452,17 @@
       }
     },
     "node_modules/@typescript-eslint/eslint-plugin": {
-      "version": "5.40.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.40.1.tgz",
-      "integrity": "sha512-FsWboKkWdytGiXT5O1/R9j37YgcjO8MKHSUmWnIEjVaz0krHkplPnYi7mwdb+5+cs0toFNQb0HIrN7zONdIEWg==",
+      "version": "5.45.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.45.0.tgz",
+      "integrity": "sha512-CXXHNlf0oL+Yg021cxgOdMHNTXD17rHkq7iW6RFHoybdFgQBjU3yIXhhcPpGwr1CjZlo6ET8C6tzX5juQoXeGA==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/scope-manager": "5.40.1",
-        "@typescript-eslint/type-utils": "5.40.1",
-        "@typescript-eslint/utils": "5.40.1",
+        "@typescript-eslint/scope-manager": "5.45.0",
+        "@typescript-eslint/type-utils": "5.45.0",
+        "@typescript-eslint/utils": "5.45.0",
         "debug": "^4.3.4",
         "ignore": "^5.2.0",
+        "natural-compare-lite": "^1.4.0",
         "regexpp": "^3.2.0",
         "semver": "^7.3.7",
         "tsutils": "^3.21.0"
@@ -2499,14 +2500,14 @@
       }
     },
     "node_modules/@typescript-eslint/parser": {
-      "version": "5.40.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.40.1.tgz",
-      "integrity": "sha512-IK6x55va5w4YvXd4b3VrXQPldV9vQTxi5ov+g4pMANsXPTXOcfjx08CRR1Dfrcc51syPtXHF5bgLlMHYFrvQtg==",
+      "version": "5.45.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.45.0.tgz",
+      "integrity": "sha512-brvs/WSM4fKUmF5Ot/gEve6qYiCMjm6w4HkHPfS6ZNmxTS0m0iNN4yOChImaCkqc1hRwFGqUyanMXuGal6oyyQ==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/scope-manager": "5.40.1",
-        "@typescript-eslint/types": "5.40.1",
-        "@typescript-eslint/typescript-estree": "5.40.1",
+        "@typescript-eslint/scope-manager": "5.45.0",
+        "@typescript-eslint/types": "5.45.0",
+        "@typescript-eslint/typescript-estree": "5.45.0",
         "debug": "^4.3.4"
       },
       "engines": {
@@ -2526,13 +2527,13 @@
       }
     },
     "node_modules/@typescript-eslint/scope-manager": {
-      "version": "5.40.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.40.1.tgz",
-      "integrity": "sha512-jkn4xsJiUQucI16OLCXrLRXDZ3afKhOIqXs4R3O+M00hdQLKR58WuyXPZZjhKLFCEP2g+TXdBRtLQ33UfAdRUg==",
+      "version": "5.45.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.45.0.tgz",
+      "integrity": "sha512-noDMjr87Arp/PuVrtvN3dXiJstQR1+XlQ4R1EvzG+NMgXi8CuMCXpb8JqNtFHKceVSQ985BZhfRdowJzbv4yKw==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/types": "5.40.1",
-        "@typescript-eslint/visitor-keys": "5.40.1"
+        "@typescript-eslint/types": "5.45.0",
+        "@typescript-eslint/visitor-keys": "5.45.0"
       },
       "engines": {
         "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -2543,13 +2544,13 @@
       }
     },
     "node_modules/@typescript-eslint/type-utils": {
-      "version": "5.40.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.40.1.tgz",
-      "integrity": "sha512-DLAs+AHQOe6n5LRraXiv27IYPhleF0ldEmx6yBqBgBLaNRKTkffhV1RPsjoJBhVup2zHxfaRtan8/YRBgYhU9Q==",
+      "version": "5.45.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.45.0.tgz",
+      "integrity": "sha512-DY7BXVFSIGRGFZ574hTEyLPRiQIvI/9oGcN8t1A7f6zIs6ftbrU0nhyV26ZW//6f85avkwrLag424n+fkuoJ1Q==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/typescript-estree": "5.40.1",
-        "@typescript-eslint/utils": "5.40.1",
+        "@typescript-eslint/typescript-estree": "5.45.0",
+        "@typescript-eslint/utils": "5.45.0",
         "debug": "^4.3.4",
         "tsutils": "^3.21.0"
       },
@@ -2570,9 +2571,9 @@
       }
     },
     "node_modules/@typescript-eslint/types": {
-      "version": "5.40.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.40.1.tgz",
-      "integrity": "sha512-Icg9kiuVJSwdzSQvtdGspOlWNjVDnF3qVIKXdJ103o36yRprdl3Ge5cABQx+csx960nuMF21v8qvO31v9t3OHw==",
+      "version": "5.45.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.45.0.tgz",
+      "integrity": "sha512-QQij+u/vgskA66azc9dCmx+rev79PzX8uDHpsqSjEFtfF2gBUTRCpvYMh2gw2ghkJabNkPlSUCimsyBEQZd1DA==",
       "dev": true,
       "engines": {
         "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -2583,13 +2584,13 @@
       }
     },
     "node_modules/@typescript-eslint/typescript-estree": {
-      "version": "5.40.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.40.1.tgz",
-      "integrity": "sha512-5QTP/nW5+60jBcEPfXy/EZL01qrl9GZtbgDZtDPlfW5zj/zjNrdI2B5zMUHmOsfvOr2cWqwVdWjobCiHcedmQA==",
+      "version": "5.45.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.45.0.tgz",
+      "integrity": "sha512-maRhLGSzqUpFcZgXxg1qc/+H0bT36lHK4APhp0AEUVrpSwXiRAomm/JGjSG+kNUio5kAa3uekCYu/47cnGn5EQ==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/types": "5.40.1",
-        "@typescript-eslint/visitor-keys": "5.40.1",
+        "@typescript-eslint/types": "5.45.0",
+        "@typescript-eslint/visitor-keys": "5.45.0",
         "debug": "^4.3.4",
         "globby": "^11.1.0",
         "is-glob": "^4.0.3",
@@ -2625,16 +2626,16 @@
       }
     },
     "node_modules/@typescript-eslint/utils": {
-      "version": "5.40.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.40.1.tgz",
-      "integrity": "sha512-a2TAVScoX9fjryNrW6BZRnreDUszxqm9eQ9Esv8n5nXApMW0zeANUYlwh/DED04SC/ifuBvXgZpIK5xeJHQ3aw==",
+      "version": "5.45.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.45.0.tgz",
+      "integrity": "sha512-OUg2JvsVI1oIee/SwiejTot2OxwU8a7UfTFMOdlhD2y+Hl6memUSL4s98bpUTo8EpVEr0lmwlU7JSu/p2QpSvA==",
       "dev": true,
       "dependencies": {
         "@types/json-schema": "^7.0.9",
         "@types/semver": "^7.3.12",
-        "@typescript-eslint/scope-manager": "5.40.1",
-        "@typescript-eslint/types": "5.40.1",
-        "@typescript-eslint/typescript-estree": "5.40.1",
+        "@typescript-eslint/scope-manager": "5.45.0",
+        "@typescript-eslint/types": "5.45.0",
+        "@typescript-eslint/typescript-estree": "5.45.0",
         "eslint-scope": "^5.1.1",
         "eslint-utils": "^3.0.0",
         "semver": "^7.3.7"
@@ -2666,12 +2667,12 @@
       }
     },
     "node_modules/@typescript-eslint/visitor-keys": {
-      "version": "5.40.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.40.1.tgz",
-      "integrity": "sha512-A2DGmeZ+FMja0geX5rww+DpvILpwo1OsiQs0M+joPWJYsiEFBLsH0y1oFymPNul6Z5okSmHpP4ivkc2N0Cgfkw==",
+      "version": "5.45.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.45.0.tgz",
+      "integrity": "sha512-jc6Eccbn2RtQPr1s7th6jJWQHBHI6GBVQkCHoJFQ5UreaKm59Vxw+ynQUPPY2u2Amquc+7tmEoC2G52ApsGNNg==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/types": "5.40.1",
+        "@typescript-eslint/types": "5.45.0",
         "eslint-visitor-keys": "^3.3.0"
       },
       "engines": {
@@ -3228,36 +3229,36 @@
       }
     },
     "node_modules/@vue/compiler-core": {
-      "version": "3.2.41",
-      "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.41.tgz",
-      "integrity": "sha512-oA4mH6SA78DT+96/nsi4p9DX97PHcNROxs51lYk7gb9Z4BPKQ3Mh+BLn6CQZBw857Iuhu28BfMSRHAlPvD4vlw==",
+      "version": "3.2.45",
+      "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.45.tgz",
+      "integrity": "sha512-rcMj7H+PYe5wBV3iYeUgbCglC+pbpN8hBLTJvRiK2eKQiWqu+fG9F+8sW99JdL4LQi7Re178UOxn09puSXvn4A==",
       "dependencies": {
         "@babel/parser": "^7.16.4",
-        "@vue/shared": "3.2.41",
+        "@vue/shared": "3.2.45",
         "estree-walker": "^2.0.2",
         "source-map": "^0.6.1"
       }
     },
     "node_modules/@vue/compiler-dom": {
-      "version": "3.2.41",
-      "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.41.tgz",
-      "integrity": "sha512-xe5TbbIsonjENxJsYRbDJvthzqxLNk+tb3d/c47zgREDa/PCp6/Y4gC/skM4H6PIuX5DAxm7fFJdbjjUH2QTMw==",
+      "version": "3.2.45",
+      "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.45.tgz",
+      "integrity": "sha512-tyYeUEuKqqZO137WrZkpwfPCdiiIeXYCcJ8L4gWz9vqaxzIQRccTSwSWZ/Axx5YR2z+LvpUbmPNXxuBU45lyRw==",
       "dependencies": {
-        "@vue/compiler-core": "3.2.41",
-        "@vue/shared": "3.2.41"
+        "@vue/compiler-core": "3.2.45",
+        "@vue/shared": "3.2.45"
       }
     },
     "node_modules/@vue/compiler-sfc": {
-      "version": "3.2.41",
-      "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.41.tgz",
-      "integrity": "sha512-+1P2m5kxOeaxVmJNXnBskAn3BenbTmbxBxWOtBq3mQTCokIreuMULFantBUclP0+KnzNCMOvcnKinqQZmiOF8w==",
+      "version": "3.2.45",
+      "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.45.tgz",
+      "integrity": "sha512-1jXDuWah1ggsnSAOGsec8cFjT/K6TMZ0sPL3o3d84Ft2AYZi2jWJgRMjw4iaK0rBfA89L5gw427H4n1RZQBu6Q==",
       "dependencies": {
         "@babel/parser": "^7.16.4",
-        "@vue/compiler-core": "3.2.41",
-        "@vue/compiler-dom": "3.2.41",
-        "@vue/compiler-ssr": "3.2.41",
-        "@vue/reactivity-transform": "3.2.41",
-        "@vue/shared": "3.2.41",
+        "@vue/compiler-core": "3.2.45",
+        "@vue/compiler-dom": "3.2.45",
+        "@vue/compiler-ssr": "3.2.45",
+        "@vue/reactivity-transform": "3.2.45",
+        "@vue/shared": "3.2.45",
         "estree-walker": "^2.0.2",
         "magic-string": "^0.25.7",
         "postcss": "^8.1.10",
@@ -3265,12 +3266,12 @@
       }
     },
     "node_modules/@vue/compiler-ssr": {
-      "version": "3.2.41",
-      "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.41.tgz",
-      "integrity": "sha512-Y5wPiNIiaMz/sps8+DmhaKfDm1xgj6GrH99z4gq2LQenfVQcYXmHIOBcs5qPwl7jaW3SUQWjkAPKMfQemEQZwQ==",
+      "version": "3.2.45",
+      "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.45.tgz",
+      "integrity": "sha512-6BRaggEGqhWht3lt24CrIbQSRD5O07MTmd+LjAn5fJj568+R9eUD2F7wMQJjX859seSlrYog7sUtrZSd7feqrQ==",
       "dependencies": {
-        "@vue/compiler-dom": "3.2.41",
-        "@vue/shared": "3.2.41"
+        "@vue/compiler-dom": "3.2.45",
+        "@vue/shared": "3.2.45"
       }
     },
     "node_modules/@vue/component-compiler-utils": {
@@ -3380,61 +3381,81 @@
         "typescript": "*"
       }
     },
+    "node_modules/@vue/eslint-config-airbnb/node_modules/emoji-regex": {
+      "version": "10.2.1",
+      "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.2.1.tgz",
+      "integrity": "sha512-97g6QgOk8zlDRdgq1WxwgTMgEWGVAQvB5Fdpgc1MkNy56la5SKP9GsMXKDOdqwn90/41a8yPwIGk1Y6WVbeMQA==",
+      "dev": true
+    },
+    "node_modules/@vue/eslint-config-airbnb/node_modules/eslint-plugin-vuejs-accessibility": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-vuejs-accessibility/-/eslint-plugin-vuejs-accessibility-1.2.0.tgz",
+      "integrity": "sha512-wF7kT22lS2VOmIpDeI65bnFFKFgESEEpI+CWKr43mdfDRywA4sCk7cKhtZsvfbPOtKO0GDlnpFxZbOIGsFn7IQ==",
+      "dev": true,
+      "dependencies": {
+        "aria-query": "^5.0.0",
+        "emoji-regex": "^10.0.0",
+        "vue-eslint-parser": "^9.0.1"
+      },
+      "peerDependencies": {
+        "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"
+      }
+    },
     "node_modules/@vue/reactivity": {
-      "version": "3.2.41",
-      "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.41.tgz",
-      "integrity": "sha512-9JvCnlj8uc5xRiQGZ28MKGjuCoPhhTwcoAdv3o31+cfGgonwdPNuvqAXLhlzu4zwqavFEG5tvaoINQEfxz+l6g==",
+      "version": "3.2.45",
+      "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.45.tgz",
+      "integrity": "sha512-PRvhCcQcyEVohW0P8iQ7HDcIOXRjZfAsOds3N99X/Dzewy8TVhTCT4uXpAHfoKjVTJRA0O0K+6QNkDIZAxNi3A==",
       "dependencies": {
-        "@vue/shared": "3.2.41"
+        "@vue/shared": "3.2.45"
       }
     },
     "node_modules/@vue/reactivity-transform": {
-      "version": "3.2.41",
-      "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.41.tgz",
-      "integrity": "sha512-mK5+BNMsL4hHi+IR3Ft/ho6Za+L3FA5j8WvreJ7XzHrqkPq8jtF/SMo7tuc9gHjLDwKZX1nP1JQOKo9IEAn54A==",
+      "version": "3.2.45",
+      "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.45.tgz",
+      "integrity": "sha512-BHVmzYAvM7vcU5WmuYqXpwaBHjsS8T63jlKGWVtHxAHIoMIlmaMyurUSEs1Zcg46M4AYT5MtB1U274/2aNzjJQ==",
       "dependencies": {
         "@babel/parser": "^7.16.4",
-        "@vue/compiler-core": "3.2.41",
-        "@vue/shared": "3.2.41",
+        "@vue/compiler-core": "3.2.45",
+        "@vue/shared": "3.2.45",
         "estree-walker": "^2.0.2",
         "magic-string": "^0.25.7"
       }
     },
     "node_modules/@vue/runtime-core": {
-      "version": "3.2.41",
-      "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.41.tgz",
-      "integrity": "sha512-0LBBRwqnI0p4FgIkO9q2aJBBTKDSjzhnxrxHYengkAF6dMOjeAIZFDADAlcf2h3GDALWnblbeprYYpItiulSVQ==",
+      "version": "3.2.45",
+      "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.45.tgz",
+      "integrity": "sha512-gzJiTA3f74cgARptqzYswmoQx0fIA+gGYBfokYVhF8YSXjWTUA2SngRzZRku2HbGbjzB6LBYSbKGIaK8IW+s0A==",
       "dependencies": {
-        "@vue/reactivity": "3.2.41",
-        "@vue/shared": "3.2.41"
+        "@vue/reactivity": "3.2.45",
+        "@vue/shared": "3.2.45"
       }
     },
     "node_modules/@vue/runtime-dom": {
-      "version": "3.2.41",
-      "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.41.tgz",
-      "integrity": "sha512-U7zYuR1NVIP8BL6jmOqmapRAHovEFp7CSw4pR2FacqewXNGqZaRfHoNLQsqQvVQ8yuZNZtxSZy0FFyC70YXPpA==",
+      "version": "3.2.45",
+      "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.45.tgz",
+      "integrity": "sha512-cy88YpfP5Ue2bDBbj75Cb4bIEZUMM/mAkDMfqDTpUYVgTf/kuQ2VQ8LebuZ8k6EudgH8pYhsGWHlY0lcxlvTwA==",
       "dependencies": {
-        "@vue/runtime-core": "3.2.41",
-        "@vue/shared": "3.2.41",
+        "@vue/runtime-core": "3.2.45",
+        "@vue/shared": "3.2.45",
         "csstype": "^2.6.8"
       }
     },
     "node_modules/@vue/server-renderer": {
-      "version": "3.2.41",
-      "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.41.tgz",
-      "integrity": "sha512-7YHLkfJdTlsZTV0ae5sPwl9Gn/EGr2hrlbcS/8naXm2CDpnKUwC68i1wGlrYAfIgYWL7vUZwk2GkYLQH5CvFig==",
+      "version": "3.2.45",
+      "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.45.tgz",
+      "integrity": "sha512-ebiMq7q24WBU1D6uhPK//2OTR1iRIyxjF5iVq/1a5I1SDMDyDu4Ts6fJaMnjrvD3MqnaiFkKQj+LKAgz5WIK3g==",
       "dependencies": {
-        "@vue/compiler-ssr": "3.2.41",
-        "@vue/shared": "3.2.41"
+        "@vue/compiler-ssr": "3.2.45",
+        "@vue/shared": "3.2.45"
       },
       "peerDependencies": {
-        "vue": "3.2.41"
+        "vue": "3.2.45"
       }
     },
     "node_modules/@vue/shared": {
-      "version": "3.2.41",
-      "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.41.tgz",
-      "integrity": "sha512-W9mfWLHmJhkfAmV+7gDjcHeAWALQtgGT3JErxULl0oz6R6+3ug91I7IErs93eCFhPCZPHBs4QJS7YWEV7A3sxw=="
+      "version": "3.2.45",
+      "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.45.tgz",
+      "integrity": "sha512-Ewzq5Yhimg7pSztDV+RH1UDKBzmtqieXQlpTVm2AwraoRL/Rks96mvd8Vgi7Lj+h+TH8dv7mXD3FRZR3TUvbSg=="
     },
     "node_modules/@vue/vue-loader-v15": {
       "name": "vue-loader",
@@ -3559,13 +3580,13 @@
       }
     },
     "node_modules/@vueuse/core": {
-      "version": "9.3.1",
-      "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-9.3.1.tgz",
-      "integrity": "sha512-xriyD+v3D2ObH/UtnkEl+1sbcLBVHNaZaLi/rqoNEe/B92hggDEFQIGXoQUjdRzYOjASHSezf9uCDtmd7LeWyA==",
+      "version": "9.6.0",
+      "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-9.6.0.tgz",
+      "integrity": "sha512-qGUcjKQXHgN+jqXEgpeZGoxdCbIDCdVPz3QiF1uyecVGbMuM63o96I1GjYx5zskKgRI0FKSNsVWM7rwrRMTf6A==",
       "dependencies": {
         "@types/web-bluetooth": "^0.0.16",
-        "@vueuse/metadata": "9.3.1",
-        "@vueuse/shared": "9.3.1",
+        "@vueuse/metadata": "9.6.0",
+        "@vueuse/shared": "9.6.0",
         "vue-demi": "*"
       },
       "funding": {
@@ -3598,17 +3619,17 @@
       }
     },
     "node_modules/@vueuse/metadata": {
-      "version": "9.3.1",
-      "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-9.3.1.tgz",
-      "integrity": "sha512-G1BPhtx3OHaL/y4OZBofh6Xt02G1VA9PuOO8nac9sTKMkMqfyez5VfkF3D9GUjSRNO7cVWyH4rceeGXfr2wdMg==",
+      "version": "9.6.0",
+      "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-9.6.0.tgz",
+      "integrity": "sha512-sIC8R+kWkIdpi5X2z2Gk8TRYzmczDwHRhEFfCu2P+XW2JdPoXrziqsGpDDsN7ykBx4ilwieS7JUIweVGhvZ93w==",
       "funding": {
         "url": "https://github.com/sponsors/antfu"
       }
     },
     "node_modules/@vueuse/shared": {
-      "version": "9.3.1",
-      "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-9.3.1.tgz",
-      "integrity": "sha512-YFu3qcnVeu0S2L4XdQJtBpDcjz6xwqHZtTv/XRhu66/yge1XVhxskUcc7VZbX52xF9A34V6KCfwncP9YDqYFiw==",
+      "version": "9.6.0",
+      "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-9.6.0.tgz",
+      "integrity": "sha512-/eDchxYYhkHnFyrb00t90UfjCx94kRHxc7J1GtBCqCG4HyPMX+krV9XJgVtWIsAMaxKVU4fC8NSUviG1JkwhUQ==",
       "dependencies": {
         "vue-demi": "*"
       },
@@ -4127,9 +4148,9 @@
       }
     },
     "node_modules/axios": {
-      "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/axios/-/axios-1.1.3.tgz",
-      "integrity": "sha512-00tXVRwKx/FZr/IDVFt4C+f9FYairX517WoGCL6dpOntqLkZofjhu43F/Xl44UOpqa+9sLFDrG/XAnFsUYgkDA==",
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/axios/-/axios-1.2.0.tgz",
+      "integrity": "sha512-zT7wZyNYu3N5Bu0wuZ6QccIf93Qk1eV8LOewxgjOZFd2DenOs98cJ7+Y6703d0wkaXGY6/nZd4EweJaHz9uzQw==",
       "dependencies": {
         "follow-redirects": "^1.15.0",
         "form-data": "^4.0.0",
@@ -4340,9 +4361,9 @@
       "dev": true
     },
     "node_modules/bootstrap": {
-      "version": "5.2.2",
-      "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.2.2.tgz",
-      "integrity": "sha512-dEtzMTV71n6Fhmbg4fYJzQsw1N29hJKO1js5ackCgIpDcGid2ETMGC6zwSYw09v05Y+oRdQ9loC54zB1La3hHQ==",
+      "version": "5.2.3",
+      "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.2.3.tgz",
+      "integrity": "sha512-cEKPM+fwb3cT8NzQZYEu4HilJ3anCrWqh3CHAok1p9jXqMPsPTBhU25fBckEJHJ/p+tTxTFTsFQGM+gaHpi3QQ==",
       "funding": [
         {
           "type": "github",
@@ -4961,9 +4982,9 @@
       }
     },
     "node_modules/core-js": {
-      "version": "3.26.0",
-      "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.26.0.tgz",
-      "integrity": "sha512-+DkDrhoR4Y0PxDz6rurahuB+I45OsEUv8E1maPTB6OuHRohMMcznBq9TMpdpDMm/hUPob/mJJS3PqgbHpMTQgw==",
+      "version": "3.26.1",
+      "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.26.1.tgz",
+      "integrity": "sha512-21491RRQVzUn0GGM9Z1Jrpr6PNPxPi+Za8OM9q4tksTSnlbXXGKK1nXNg/QvwFYettXvSX6zWKCtHHfjN4puyA==",
       "hasInstallScript": true,
       "funding": {
         "type": "opencollective",
@@ -5844,9 +5865,9 @@
       }
     },
     "node_modules/eslint": {
-      "version": "8.26.0",
-      "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.26.0.tgz",
-      "integrity": "sha512-kzJkpaw1Bfwheq4VXUezFriD1GxszX6dUekM7Z3aC2o4hju+tsR/XyTC3RcoSD7jmy9VkPU3+N6YjVU2e96Oyg==",
+      "version": "8.28.0",
+      "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.28.0.tgz",
+      "integrity": "sha512-S27Di+EVyMxcHiwDrFzk8dJYAaD+/5SoWKxL1ri/71CRHsnJnRDPNt2Kzj24+MT9FDupf4aqqyqPrvI8MvQ4VQ==",
       "dev": true,
       "dependencies": {
         "@eslint/eslintrc": "^1.3.3",
@@ -6310,9 +6331,9 @@
       }
     },
     "node_modules/eslint-plugin-vue": {
-      "version": "9.6.0",
-      "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.6.0.tgz",
-      "integrity": "sha512-zzySkJgVbFCylnG2+9MDF7N+2Rjze2y0bF8GyUNpFOnT8mCMfqqtLDJkHBuYu9N/psW1A6DVbQhPkP92E+qakA==",
+      "version": "9.8.0",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.8.0.tgz",
+      "integrity": "sha512-E/AXwcTzunyzM83C2QqDHxepMzvI2y6x+mmeYHbVDQlKFqmKYvRrhaVixEeeG27uI44p9oKDFiyCRw4XxgtfHA==",
       "dev": true,
       "dependencies": {
         "eslint-utils": "^3.0.0",
@@ -6346,12 +6367,12 @@
       }
     },
     "node_modules/eslint-plugin-vuejs-accessibility": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/eslint-plugin-vuejs-accessibility/-/eslint-plugin-vuejs-accessibility-1.2.0.tgz",
-      "integrity": "sha512-wF7kT22lS2VOmIpDeI65bnFFKFgESEEpI+CWKr43mdfDRywA4sCk7cKhtZsvfbPOtKO0GDlnpFxZbOIGsFn7IQ==",
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-vuejs-accessibility/-/eslint-plugin-vuejs-accessibility-2.0.0.tgz",
+      "integrity": "sha512-mjbXnncDT9+5K+/QXXhOVWhEU6OOJck/JNlC6tewo3R+Kzsbaecyq3ylN1NqmyKo78vsgun34JLd+vGdxSPFWQ==",
       "dev": true,
       "dependencies": {
-        "aria-query": "^5.0.0",
+        "aria-query": ">=5.0.0",
         "emoji-regex": "^10.0.0",
         "vue-eslint-parser": "^9.0.1"
       },
@@ -7277,9 +7298,9 @@
       }
     },
     "node_modules/fs-extra": {
-      "version": "10.1.0",
-      "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
-      "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
+      "version": "11.0.0",
+      "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.0.0.tgz",
+      "integrity": "sha512-4YxRvMi4P5C3WQTvdRfrv5UVqbISpqjORFQAW5QPiKAauaxNCwrEdIi6pG3tDFhKKpMen+enEhHIzB/tvIO+/w==",
       "dev": true,
       "dependencies": {
         "graceful-fs": "^4.2.0",
@@ -7287,7 +7308,7 @@
         "universalify": "^2.0.0"
       },
       "engines": {
-        "node": ">=12"
+        "node": ">=14.14"
       }
     },
     "node_modules/fs-monkey": {
@@ -8817,9 +8838,9 @@
       }
     },
     "node_modules/marked": {
-      "version": "4.1.1",
-      "resolved": "https://registry.npmjs.org/marked/-/marked-4.1.1.tgz",
-      "integrity": "sha512-0cNMnTcUJPxbA6uWmCmjWz4NJRe/0Xfk2NhXCUHjew9qJzFN20krFnsUe7QynwqOwa5m1fZ4UDg0ycKFVC0ccw==",
+      "version": "4.2.3",
+      "resolved": "https://registry.npmjs.org/marked/-/marked-4.2.3.tgz",
+      "integrity": "sha512-slWRdJkbTZ+PjkyJnE30Uid64eHwbwa1Q25INCAYfZlK4o6ylagBy/Le9eWntqJFoFT93ikUKMv47GZ4gTwHkw==",
       "bin": {
         "marked": "bin/marked.js"
       },
@@ -9116,6 +9137,12 @@
       "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
       "dev": true
     },
+    "node_modules/natural-compare-lite": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz",
+      "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==",
+      "dev": true
+    },
     "node_modules/negotiator": {
       "version": "0.6.3",
       "resolved": "https://registry.npmmirror.com/negotiator/-/negotiator-0.6.3.tgz",
@@ -9718,11 +9745,11 @@
       }
     },
     "node_modules/pinia": {
-      "version": "2.0.23",
-      "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.0.23.tgz",
-      "integrity": "sha512-N15hFf4o5STrxpNrib1IEb1GOArvPYf1zPvQVRGOO1G1d74Ak0J0lVyalX/SmrzdT4Q0nlEFjbURsmBmIGUR5Q==",
+      "version": "2.0.27",
+      "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.0.27.tgz",
+      "integrity": "sha512-nOnXP0OFeL8R4WjAHsterU+11vptda643gH02xKNtSCDPiRzVfRYodOLihLDoa0gL1KKuQKV+KOzEgdt3YvqEw==",
       "dependencies": {
-        "@vue/devtools-api": "^6.4.4",
+        "@vue/devtools-api": "^6.4.5",
         "vue-demi": "*"
       },
       "funding": {
@@ -10829,9 +10856,9 @@
       "dev": true
     },
     "node_modules/sass": {
-      "version": "1.55.0",
-      "resolved": "https://registry.npmjs.org/sass/-/sass-1.55.0.tgz",
-      "integrity": "sha512-Pk+PMy7OGLs9WaxZGJMn7S96dvlyVBwwtToX895WmCpAOr5YiJYEUJfiJidMuKb613z2xNWcXCHEuOvjZbqC6A==",
+      "version": "1.56.1",
+      "resolved": "https://registry.npmjs.org/sass/-/sass-1.56.1.tgz",
+      "integrity": "sha512-VpEyKpyBPCxE7qGDtOcdJ6fFbcpOM+Emu7uZLxVrkX8KVU/Dp5UF7WLvzqRuUhB6mqqQt1xffLoG+AndxTZrCQ==",
       "dev": true,
       "dependencies": {
         "chokidar": ">=3.0.0 <4.0.0",
@@ -10846,9 +10873,9 @@
       }
     },
     "node_modules/sass-loader": {
-      "version": "13.1.0",
-      "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-13.1.0.tgz",
-      "integrity": "sha512-tZS1RJQ2n2+QNyf3CCAo1H562WjL/5AM6Gi8YcPVVoNxQX8d19mx8E+8fRrMWsyc93ZL6Q8vZDSM0FHVTJaVnQ==",
+      "version": "13.2.0",
+      "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-13.2.0.tgz",
+      "integrity": "sha512-JWEp48djQA4nbZxmgC02/Wh0eroSUutulROUusYJO9P9zltRbNN80JCBHqRGzjd4cmZCa/r88xgfkjGD0TXsHg==",
       "dev": true,
       "dependencies": {
         "klona": "^2.0.4",
@@ -10863,7 +10890,7 @@
       },
       "peerDependencies": {
         "fibers": ">= 3.1.0",
-        "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0",
+        "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0",
         "sass": "^1.3.0",
         "sass-embedded": "*",
         "webpack": "^5.0.0"
@@ -11888,9 +11915,9 @@
       }
     },
     "node_modules/typescript": {
-      "version": "4.8.4",
-      "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz",
-      "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==",
+      "version": "4.9.3",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.3.tgz",
+      "integrity": "sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==",
       "devOptional": true,
       "bin": {
         "tsc": "bin/tsc",
@@ -12068,15 +12095,15 @@
       }
     },
     "node_modules/vue": {
-      "version": "3.2.41",
-      "resolved": "https://registry.npmjs.org/vue/-/vue-3.2.41.tgz",
-      "integrity": "sha512-uuuvnrDXEeZ9VUPljgHkqB5IaVO8SxhPpqF2eWOukVrBnRBx2THPSGQBnVRt0GrIG1gvCmFXMGbd7FqcT1ixNQ==",
+      "version": "3.2.45",
+      "resolved": "https://registry.npmjs.org/vue/-/vue-3.2.45.tgz",
+      "integrity": "sha512-9Nx/Mg2b2xWlXykmCwiTUCWHbWIj53bnkizBxKai1g61f2Xit700A1ljowpTIM11e3uipOeiPcSqnmBg6gyiaA==",
       "dependencies": {
-        "@vue/compiler-dom": "3.2.41",
-        "@vue/compiler-sfc": "3.2.41",
-        "@vue/runtime-dom": "3.2.41",
-        "@vue/server-renderer": "3.2.41",
-        "@vue/shared": "3.2.41"
+        "@vue/compiler-dom": "3.2.45",
+        "@vue/compiler-sfc": "3.2.45",
+        "@vue/runtime-dom": "3.2.45",
+        "@vue/server-renderer": "3.2.45",
+        "@vue/shared": "3.2.45"
       }
     },
     "node_modules/vue-eslint-parser": {
@@ -14215,46 +14242,46 @@
       }
     },
     "@fortawesome/fontawesome-common-types": {
-      "version": "6.2.0",
-      "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.2.0.tgz",
-      "integrity": "sha512-rBevIsj2nclStJ7AxTdfsa3ovHb1H+qApwrxcTVo+NNdeJiB9V75hsKfrkG5AwNcRUNxrPPiScGYCNmLMoh8pg=="
+      "version": "6.2.1",
+      "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.2.1.tgz",
+      "integrity": "sha512-Sz07mnQrTekFWLz5BMjOzHl/+NooTdW8F8kDQxjWwbpOJcnoSg4vUDng8d/WR1wOxM0O+CY9Zw0nR054riNYtQ=="
     },
     "@fortawesome/fontawesome-svg-core": {
-      "version": "6.2.0",
-      "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.2.0.tgz",
-      "integrity": "sha512-Cf2mAAeMWFMzpLC7Y9H1I4o3wEU+XovVJhTiNG8ZNgSQj53yl7OCJaS80K4YjrABWZzbAHVaoHE1dVJ27AAYXw==",
+      "version": "6.2.1",
+      "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.2.1.tgz",
+      "integrity": "sha512-HELwwbCz6C1XEcjzyT1Jugmz2NNklMrSPjZOWMlc+ZsHIVk+XOvOXLGGQtFBwSyqfJDNgRq4xBCwWOaZ/d9DEA==",
       "requires": {
-        "@fortawesome/fontawesome-common-types": "6.2.0"
+        "@fortawesome/fontawesome-common-types": "6.2.1"
       }
     },
     "@fortawesome/free-brands-svg-icons": {
-      "version": "6.2.0",
-      "resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-6.2.0.tgz",
-      "integrity": "sha512-fm1y4NyZ2qKYNmYhdMz9VAWRw1Et7PMHNunSw3W0SVAwKwv6o0qiJworLH3Y9SnmhHzAymXJwCX1op22FFvGiA==",
+      "version": "6.2.1",
+      "resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-6.2.1.tgz",
+      "integrity": "sha512-L8l4MfdHPmZlJ72PvzdfwOwbwcCAL0vx48tJRnI6u1PJXh+j2f3yDoKyQgO3qjEsgD5Fr2tQV/cPP8F/k6aUig==",
       "requires": {
-        "@fortawesome/fontawesome-common-types": "6.2.0"
+        "@fortawesome/fontawesome-common-types": "6.2.1"
       }
     },
     "@fortawesome/free-regular-svg-icons": {
-      "version": "6.2.0",
-      "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.2.0.tgz",
-      "integrity": "sha512-M1dG+PAmkYMTL9BSUHFXY5oaHwBYfHCPhbJ8qj8JELsc9XCrUJ6eEHWip4q0tE+h9C0DVyFkwIM9t7QYyCpprQ==",
+      "version": "6.2.1",
+      "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.2.1.tgz",
+      "integrity": "sha512-wiqcNDNom75x+pe88FclpKz7aOSqS2lOivZeicMV5KRwOAeypxEYWAK/0v+7r+LrEY30+qzh8r2XDaEHvoLsMA==",
       "requires": {
-        "@fortawesome/fontawesome-common-types": "6.2.0"
+        "@fortawesome/fontawesome-common-types": "6.2.1"
       }
     },
     "@fortawesome/free-solid-svg-icons": {
-      "version": "6.2.0",
-      "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.2.0.tgz",
-      "integrity": "sha512-UjCILHIQ4I8cN46EiQn0CZL/h8AwCGgR//1c4R96Q5viSRwuKVo0NdQEc4bm+69ZwC0dUvjbDqAHF1RR5FA3XA==",
+      "version": "6.2.1",
+      "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.2.1.tgz",
+      "integrity": "sha512-oKuqrP5jbfEPJWTij4sM+/RvgX+RMFwx3QZCZcK9PrBDgxC35zuc7AOFsyMjMd/PIFPeB2JxyqDr5zs/DZFPPw==",
       "requires": {
-        "@fortawesome/fontawesome-common-types": "6.2.0"
+        "@fortawesome/fontawesome-common-types": "6.2.1"
       }
     },
     "@fortawesome/vue-fontawesome": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/@fortawesome/vue-fontawesome/-/vue-fontawesome-3.0.1.tgz",
-      "integrity": "sha512-CdXZJoCS+aEPec26ZP7hWWU3SaJlQPZSCGdgpQ2qGl2HUmtUUNrI3zC4XWdn1JUmh3t5OuDeRG1qB4eGRNSD4A==",
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/@fortawesome/vue-fontawesome/-/vue-fontawesome-3.0.2.tgz",
+      "integrity": "sha512-xHVtVY8ASUeEvgcA/7vULUesENhD+pi/EirRHdMBqooHlXBqK+yrV6d8tUye1m5UKQKVgYAHMhUBfOnoiwvc8Q==",
       "requires": {}
     },
     "@hapi/hoek": {
@@ -14731,9 +14758,9 @@
       "dev": true
     },
     "@types/semver": {
-      "version": "7.3.12",
-      "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.12.tgz",
-      "integrity": "sha512-WwA1MW0++RfXmCr12xeYOOC5baSC9mSb0ZqCquFzKhcoF4TvHu5MKOuXsncgZcpVFhB1pXd5hZmM0ryAoCp12A==",
+      "version": "7.3.13",
+      "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz",
+      "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==",
       "dev": true
     },
     "@types/serve-index": {
@@ -14785,16 +14812,17 @@
       }
     },
     "@typescript-eslint/eslint-plugin": {
-      "version": "5.40.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.40.1.tgz",
-      "integrity": "sha512-FsWboKkWdytGiXT5O1/R9j37YgcjO8MKHSUmWnIEjVaz0krHkplPnYi7mwdb+5+cs0toFNQb0HIrN7zONdIEWg==",
+      "version": "5.45.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.45.0.tgz",
+      "integrity": "sha512-CXXHNlf0oL+Yg021cxgOdMHNTXD17rHkq7iW6RFHoybdFgQBjU3yIXhhcPpGwr1CjZlo6ET8C6tzX5juQoXeGA==",
       "dev": true,
       "requires": {
-        "@typescript-eslint/scope-manager": "5.40.1",
-        "@typescript-eslint/type-utils": "5.40.1",
-        "@typescript-eslint/utils": "5.40.1",
+        "@typescript-eslint/scope-manager": "5.45.0",
+        "@typescript-eslint/type-utils": "5.45.0",
+        "@typescript-eslint/utils": "5.45.0",
         "debug": "^4.3.4",
         "ignore": "^5.2.0",
+        "natural-compare-lite": "^1.4.0",
         "regexpp": "^3.2.0",
         "semver": "^7.3.7",
         "tsutils": "^3.21.0"
@@ -14812,53 +14840,53 @@
       }
     },
     "@typescript-eslint/parser": {
-      "version": "5.40.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.40.1.tgz",
-      "integrity": "sha512-IK6x55va5w4YvXd4b3VrXQPldV9vQTxi5ov+g4pMANsXPTXOcfjx08CRR1Dfrcc51syPtXHF5bgLlMHYFrvQtg==",
+      "version": "5.45.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.45.0.tgz",
+      "integrity": "sha512-brvs/WSM4fKUmF5Ot/gEve6qYiCMjm6w4HkHPfS6ZNmxTS0m0iNN4yOChImaCkqc1hRwFGqUyanMXuGal6oyyQ==",
       "dev": true,
       "requires": {
-        "@typescript-eslint/scope-manager": "5.40.1",
-        "@typescript-eslint/types": "5.40.1",
-        "@typescript-eslint/typescript-estree": "5.40.1",
+        "@typescript-eslint/scope-manager": "5.45.0",
+        "@typescript-eslint/types": "5.45.0",
+        "@typescript-eslint/typescript-estree": "5.45.0",
         "debug": "^4.3.4"
       }
     },
     "@typescript-eslint/scope-manager": {
-      "version": "5.40.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.40.1.tgz",
-      "integrity": "sha512-jkn4xsJiUQucI16OLCXrLRXDZ3afKhOIqXs4R3O+M00hdQLKR58WuyXPZZjhKLFCEP2g+TXdBRtLQ33UfAdRUg==",
+      "version": "5.45.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.45.0.tgz",
+      "integrity": "sha512-noDMjr87Arp/PuVrtvN3dXiJstQR1+XlQ4R1EvzG+NMgXi8CuMCXpb8JqNtFHKceVSQ985BZhfRdowJzbv4yKw==",
       "dev": true,
       "requires": {
-        "@typescript-eslint/types": "5.40.1",
-        "@typescript-eslint/visitor-keys": "5.40.1"
+        "@typescript-eslint/types": "5.45.0",
+        "@typescript-eslint/visitor-keys": "5.45.0"
       }
     },
     "@typescript-eslint/type-utils": {
-      "version": "5.40.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.40.1.tgz",
-      "integrity": "sha512-DLAs+AHQOe6n5LRraXiv27IYPhleF0ldEmx6yBqBgBLaNRKTkffhV1RPsjoJBhVup2zHxfaRtan8/YRBgYhU9Q==",
+      "version": "5.45.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.45.0.tgz",
+      "integrity": "sha512-DY7BXVFSIGRGFZ574hTEyLPRiQIvI/9oGcN8t1A7f6zIs6ftbrU0nhyV26ZW//6f85avkwrLag424n+fkuoJ1Q==",
       "dev": true,
       "requires": {
-        "@typescript-eslint/typescript-estree": "5.40.1",
-        "@typescript-eslint/utils": "5.40.1",
+        "@typescript-eslint/typescript-estree": "5.45.0",
+        "@typescript-eslint/utils": "5.45.0",
         "debug": "^4.3.4",
         "tsutils": "^3.21.0"
       }
     },
     "@typescript-eslint/types": {
-      "version": "5.40.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.40.1.tgz",
-      "integrity": "sha512-Icg9kiuVJSwdzSQvtdGspOlWNjVDnF3qVIKXdJ103o36yRprdl3Ge5cABQx+csx960nuMF21v8qvO31v9t3OHw==",
+      "version": "5.45.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.45.0.tgz",
+      "integrity": "sha512-QQij+u/vgskA66azc9dCmx+rev79PzX8uDHpsqSjEFtfF2gBUTRCpvYMh2gw2ghkJabNkPlSUCimsyBEQZd1DA==",
       "dev": true
     },
     "@typescript-eslint/typescript-estree": {
-      "version": "5.40.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.40.1.tgz",
-      "integrity": "sha512-5QTP/nW5+60jBcEPfXy/EZL01qrl9GZtbgDZtDPlfW5zj/zjNrdI2B5zMUHmOsfvOr2cWqwVdWjobCiHcedmQA==",
+      "version": "5.45.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.45.0.tgz",
+      "integrity": "sha512-maRhLGSzqUpFcZgXxg1qc/+H0bT36lHK4APhp0AEUVrpSwXiRAomm/JGjSG+kNUio5kAa3uekCYu/47cnGn5EQ==",
       "dev": true,
       "requires": {
-        "@typescript-eslint/types": "5.40.1",
-        "@typescript-eslint/visitor-keys": "5.40.1",
+        "@typescript-eslint/types": "5.45.0",
+        "@typescript-eslint/visitor-keys": "5.45.0",
         "debug": "^4.3.4",
         "globby": "^11.1.0",
         "is-glob": "^4.0.3",
@@ -14878,16 +14906,16 @@
       }
     },
     "@typescript-eslint/utils": {
-      "version": "5.40.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.40.1.tgz",
-      "integrity": "sha512-a2TAVScoX9fjryNrW6BZRnreDUszxqm9eQ9Esv8n5nXApMW0zeANUYlwh/DED04SC/ifuBvXgZpIK5xeJHQ3aw==",
+      "version": "5.45.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.45.0.tgz",
+      "integrity": "sha512-OUg2JvsVI1oIee/SwiejTot2OxwU8a7UfTFMOdlhD2y+Hl6memUSL4s98bpUTo8EpVEr0lmwlU7JSu/p2QpSvA==",
       "dev": true,
       "requires": {
         "@types/json-schema": "^7.0.9",
         "@types/semver": "^7.3.12",
-        "@typescript-eslint/scope-manager": "5.40.1",
-        "@typescript-eslint/types": "5.40.1",
-        "@typescript-eslint/typescript-estree": "5.40.1",
+        "@typescript-eslint/scope-manager": "5.45.0",
+        "@typescript-eslint/types": "5.45.0",
+        "@typescript-eslint/typescript-estree": "5.45.0",
         "eslint-scope": "^5.1.1",
         "eslint-utils": "^3.0.0",
         "semver": "^7.3.7"
@@ -14905,12 +14933,12 @@
       }
     },
     "@typescript-eslint/visitor-keys": {
-      "version": "5.40.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.40.1.tgz",
-      "integrity": "sha512-A2DGmeZ+FMja0geX5rww+DpvILpwo1OsiQs0M+joPWJYsiEFBLsH0y1oFymPNul6Z5okSmHpP4ivkc2N0Cgfkw==",
+      "version": "5.45.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.45.0.tgz",
+      "integrity": "sha512-jc6Eccbn2RtQPr1s7th6jJWQHBHI6GBVQkCHoJFQ5UreaKm59Vxw+ynQUPPY2u2Amquc+7tmEoC2G52ApsGNNg==",
       "dev": true,
       "requires": {
-        "@typescript-eslint/types": "5.40.1",
+        "@typescript-eslint/types": "5.45.0",
         "eslint-visitor-keys": "^3.3.0"
       }
     },
@@ -15324,36 +15352,36 @@
       }
     },
     "@vue/compiler-core": {
-      "version": "3.2.41",
-      "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.41.tgz",
-      "integrity": "sha512-oA4mH6SA78DT+96/nsi4p9DX97PHcNROxs51lYk7gb9Z4BPKQ3Mh+BLn6CQZBw857Iuhu28BfMSRHAlPvD4vlw==",
+      "version": "3.2.45",
+      "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.45.tgz",
+      "integrity": "sha512-rcMj7H+PYe5wBV3iYeUgbCglC+pbpN8hBLTJvRiK2eKQiWqu+fG9F+8sW99JdL4LQi7Re178UOxn09puSXvn4A==",
       "requires": {
         "@babel/parser": "^7.16.4",
-        "@vue/shared": "3.2.41",
+        "@vue/shared": "3.2.45",
         "estree-walker": "^2.0.2",
         "source-map": "^0.6.1"
       }
     },
     "@vue/compiler-dom": {
-      "version": "3.2.41",
-      "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.41.tgz",
-      "integrity": "sha512-xe5TbbIsonjENxJsYRbDJvthzqxLNk+tb3d/c47zgREDa/PCp6/Y4gC/skM4H6PIuX5DAxm7fFJdbjjUH2QTMw==",
+      "version": "3.2.45",
+      "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.45.tgz",
+      "integrity": "sha512-tyYeUEuKqqZO137WrZkpwfPCdiiIeXYCcJ8L4gWz9vqaxzIQRccTSwSWZ/Axx5YR2z+LvpUbmPNXxuBU45lyRw==",
       "requires": {
-        "@vue/compiler-core": "3.2.41",
-        "@vue/shared": "3.2.41"
+        "@vue/compiler-core": "3.2.45",
+        "@vue/shared": "3.2.45"
       }
     },
     "@vue/compiler-sfc": {
-      "version": "3.2.41",
-      "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.41.tgz",
-      "integrity": "sha512-+1P2m5kxOeaxVmJNXnBskAn3BenbTmbxBxWOtBq3mQTCokIreuMULFantBUclP0+KnzNCMOvcnKinqQZmiOF8w==",
+      "version": "3.2.45",
+      "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.45.tgz",
+      "integrity": "sha512-1jXDuWah1ggsnSAOGsec8cFjT/K6TMZ0sPL3o3d84Ft2AYZi2jWJgRMjw4iaK0rBfA89L5gw427H4n1RZQBu6Q==",
       "requires": {
         "@babel/parser": "^7.16.4",
-        "@vue/compiler-core": "3.2.41",
-        "@vue/compiler-dom": "3.2.41",
-        "@vue/compiler-ssr": "3.2.41",
-        "@vue/reactivity-transform": "3.2.41",
-        "@vue/shared": "3.2.41",
+        "@vue/compiler-core": "3.2.45",
+        "@vue/compiler-dom": "3.2.45",
+        "@vue/compiler-ssr": "3.2.45",
+        "@vue/reactivity-transform": "3.2.45",
+        "@vue/shared": "3.2.45",
         "estree-walker": "^2.0.2",
         "magic-string": "^0.25.7",
         "postcss": "^8.1.10",
@@ -15361,12 +15389,12 @@
       }
     },
     "@vue/compiler-ssr": {
-      "version": "3.2.41",
-      "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.41.tgz",
-      "integrity": "sha512-Y5wPiNIiaMz/sps8+DmhaKfDm1xgj6GrH99z4gq2LQenfVQcYXmHIOBcs5qPwl7jaW3SUQWjkAPKMfQemEQZwQ==",
+      "version": "3.2.45",
+      "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.45.tgz",
+      "integrity": "sha512-6BRaggEGqhWht3lt24CrIbQSRD5O07MTmd+LjAn5fJj568+R9eUD2F7wMQJjX859seSlrYog7sUtrZSd7feqrQ==",
       "requires": {
-        "@vue/compiler-dom": "3.2.41",
-        "@vue/shared": "3.2.41"
+        "@vue/compiler-dom": "3.2.45",
+        "@vue/shared": "3.2.45"
       }
     },
     "@vue/component-compiler-utils": {
@@ -15445,6 +15473,25 @@
         "eslint-plugin-react": "^7.30.1",
         "eslint-plugin-vuejs-accessibility": "^1.2.0",
         "vue-eslint-parser": "^9.0.3"
+      },
+      "dependencies": {
+        "emoji-regex": {
+          "version": "10.2.1",
+          "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.2.1.tgz",
+          "integrity": "sha512-97g6QgOk8zlDRdgq1WxwgTMgEWGVAQvB5Fdpgc1MkNy56la5SKP9GsMXKDOdqwn90/41a8yPwIGk1Y6WVbeMQA==",
+          "dev": true
+        },
+        "eslint-plugin-vuejs-accessibility": {
+          "version": "1.2.0",
+          "resolved": "https://registry.npmjs.org/eslint-plugin-vuejs-accessibility/-/eslint-plugin-vuejs-accessibility-1.2.0.tgz",
+          "integrity": "sha512-wF7kT22lS2VOmIpDeI65bnFFKFgESEEpI+CWKr43mdfDRywA4sCk7cKhtZsvfbPOtKO0GDlnpFxZbOIGsFn7IQ==",
+          "dev": true,
+          "requires": {
+            "aria-query": "^5.0.0",
+            "emoji-regex": "^10.0.0",
+            "vue-eslint-parser": "^9.0.1"
+          }
+        }
       }
     },
     "@vue/eslint-config-airbnb-with-typescript": {
@@ -15465,57 +15512,57 @@
       }
     },
     "@vue/reactivity": {
-      "version": "3.2.41",
-      "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.41.tgz",
-      "integrity": "sha512-9JvCnlj8uc5xRiQGZ28MKGjuCoPhhTwcoAdv3o31+cfGgonwdPNuvqAXLhlzu4zwqavFEG5tvaoINQEfxz+l6g==",
+      "version": "3.2.45",
+      "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.45.tgz",
+      "integrity": "sha512-PRvhCcQcyEVohW0P8iQ7HDcIOXRjZfAsOds3N99X/Dzewy8TVhTCT4uXpAHfoKjVTJRA0O0K+6QNkDIZAxNi3A==",
       "requires": {
-        "@vue/shared": "3.2.41"
+        "@vue/shared": "3.2.45"
       }
     },
     "@vue/reactivity-transform": {
-      "version": "3.2.41",
-      "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.41.tgz",
-      "integrity": "sha512-mK5+BNMsL4hHi+IR3Ft/ho6Za+L3FA5j8WvreJ7XzHrqkPq8jtF/SMo7tuc9gHjLDwKZX1nP1JQOKo9IEAn54A==",
+      "version": "3.2.45",
+      "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.45.tgz",
+      "integrity": "sha512-BHVmzYAvM7vcU5WmuYqXpwaBHjsS8T63jlKGWVtHxAHIoMIlmaMyurUSEs1Zcg46M4AYT5MtB1U274/2aNzjJQ==",
       "requires": {
         "@babel/parser": "^7.16.4",
-        "@vue/compiler-core": "3.2.41",
-        "@vue/shared": "3.2.41",
+        "@vue/compiler-core": "3.2.45",
+        "@vue/shared": "3.2.45",
         "estree-walker": "^2.0.2",
         "magic-string": "^0.25.7"
       }
     },
     "@vue/runtime-core": {
-      "version": "3.2.41",
-      "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.41.tgz",
-      "integrity": "sha512-0LBBRwqnI0p4FgIkO9q2aJBBTKDSjzhnxrxHYengkAF6dMOjeAIZFDADAlcf2h3GDALWnblbeprYYpItiulSVQ==",
+      "version": "3.2.45",
+      "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.45.tgz",
+      "integrity": "sha512-gzJiTA3f74cgARptqzYswmoQx0fIA+gGYBfokYVhF8YSXjWTUA2SngRzZRku2HbGbjzB6LBYSbKGIaK8IW+s0A==",
       "requires": {
-        "@vue/reactivity": "3.2.41",
-        "@vue/shared": "3.2.41"
+        "@vue/reactivity": "3.2.45",
+        "@vue/shared": "3.2.45"
       }
     },
     "@vue/runtime-dom": {
-      "version": "3.2.41",
-      "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.41.tgz",
-      "integrity": "sha512-U7zYuR1NVIP8BL6jmOqmapRAHovEFp7CSw4pR2FacqewXNGqZaRfHoNLQsqQvVQ8yuZNZtxSZy0FFyC70YXPpA==",
+      "version": "3.2.45",
+      "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.45.tgz",
+      "integrity": "sha512-cy88YpfP5Ue2bDBbj75Cb4bIEZUMM/mAkDMfqDTpUYVgTf/kuQ2VQ8LebuZ8k6EudgH8pYhsGWHlY0lcxlvTwA==",
       "requires": {
-        "@vue/runtime-core": "3.2.41",
-        "@vue/shared": "3.2.41",
+        "@vue/runtime-core": "3.2.45",
+        "@vue/shared": "3.2.45",
         "csstype": "^2.6.8"
       }
     },
     "@vue/server-renderer": {
-      "version": "3.2.41",
-      "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.41.tgz",
-      "integrity": "sha512-7YHLkfJdTlsZTV0ae5sPwl9Gn/EGr2hrlbcS/8naXm2CDpnKUwC68i1wGlrYAfIgYWL7vUZwk2GkYLQH5CvFig==",
+      "version": "3.2.45",
+      "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.45.tgz",
+      "integrity": "sha512-ebiMq7q24WBU1D6uhPK//2OTR1iRIyxjF5iVq/1a5I1SDMDyDu4Ts6fJaMnjrvD3MqnaiFkKQj+LKAgz5WIK3g==",
       "requires": {
-        "@vue/compiler-ssr": "3.2.41",
-        "@vue/shared": "3.2.41"
+        "@vue/compiler-ssr": "3.2.45",
+        "@vue/shared": "3.2.45"
       }
     },
     "@vue/shared": {
-      "version": "3.2.41",
-      "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.41.tgz",
-      "integrity": "sha512-W9mfWLHmJhkfAmV+7gDjcHeAWALQtgGT3JErxULl0oz6R6+3ug91I7IErs93eCFhPCZPHBs4QJS7YWEV7A3sxw=="
+      "version": "3.2.45",
+      "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.45.tgz",
+      "integrity": "sha512-Ewzq5Yhimg7pSztDV+RH1UDKBzmtqieXQlpTVm2AwraoRL/Rks96mvd8Vgi7Lj+h+TH8dv7mXD3FRZR3TUvbSg=="
     },
     "@vue/vue-loader-v15": {
       "version": "npm:vue-loader@15.9.8",
@@ -15577,13 +15624,13 @@
       }
     },
     "@vueuse/core": {
-      "version": "9.3.1",
-      "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-9.3.1.tgz",
-      "integrity": "sha512-xriyD+v3D2ObH/UtnkEl+1sbcLBVHNaZaLi/rqoNEe/B92hggDEFQIGXoQUjdRzYOjASHSezf9uCDtmd7LeWyA==",
+      "version": "9.6.0",
+      "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-9.6.0.tgz",
+      "integrity": "sha512-qGUcjKQXHgN+jqXEgpeZGoxdCbIDCdVPz3QiF1uyecVGbMuM63o96I1GjYx5zskKgRI0FKSNsVWM7rwrRMTf6A==",
       "requires": {
         "@types/web-bluetooth": "^0.0.16",
-        "@vueuse/metadata": "9.3.1",
-        "@vueuse/shared": "9.3.1",
+        "@vueuse/metadata": "9.6.0",
+        "@vueuse/shared": "9.6.0",
         "vue-demi": "*"
       },
       "dependencies": {
@@ -15596,14 +15643,14 @@
       }
     },
     "@vueuse/metadata": {
-      "version": "9.3.1",
-      "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-9.3.1.tgz",
-      "integrity": "sha512-G1BPhtx3OHaL/y4OZBofh6Xt02G1VA9PuOO8nac9sTKMkMqfyez5VfkF3D9GUjSRNO7cVWyH4rceeGXfr2wdMg=="
+      "version": "9.6.0",
+      "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-9.6.0.tgz",
+      "integrity": "sha512-sIC8R+kWkIdpi5X2z2Gk8TRYzmczDwHRhEFfCu2P+XW2JdPoXrziqsGpDDsN7ykBx4ilwieS7JUIweVGhvZ93w=="
     },
     "@vueuse/shared": {
-      "version": "9.3.1",
-      "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-9.3.1.tgz",
-      "integrity": "sha512-YFu3qcnVeu0S2L4XdQJtBpDcjz6xwqHZtTv/XRhu66/yge1XVhxskUcc7VZbX52xF9A34V6KCfwncP9YDqYFiw==",
+      "version": "9.6.0",
+      "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-9.6.0.tgz",
+      "integrity": "sha512-/eDchxYYhkHnFyrb00t90UfjCx94kRHxc7J1GtBCqCG4HyPMX+krV9XJgVtWIsAMaxKVU4fC8NSUviG1JkwhUQ==",
       "requires": {
         "vue-demi": "*"
       },
@@ -16021,9 +16068,9 @@
       "dev": true
     },
     "axios": {
-      "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/axios/-/axios-1.1.3.tgz",
-      "integrity": "sha512-00tXVRwKx/FZr/IDVFt4C+f9FYairX517WoGCL6dpOntqLkZofjhu43F/Xl44UOpqa+9sLFDrG/XAnFsUYgkDA==",
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/axios/-/axios-1.2.0.tgz",
+      "integrity": "sha512-zT7wZyNYu3N5Bu0wuZ6QccIf93Qk1eV8LOewxgjOZFd2DenOs98cJ7+Y6703d0wkaXGY6/nZd4EweJaHz9uzQw==",
       "requires": {
         "follow-redirects": "^1.15.0",
         "form-data": "^4.0.0",
@@ -16207,9 +16254,9 @@
       "dev": true
     },
     "bootstrap": {
-      "version": "5.2.2",
-      "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.2.2.tgz",
-      "integrity": "sha512-dEtzMTV71n6Fhmbg4fYJzQsw1N29hJKO1js5ackCgIpDcGid2ETMGC6zwSYw09v05Y+oRdQ9loC54zB1La3hHQ==",
+      "version": "5.2.3",
+      "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.2.3.tgz",
+      "integrity": "sha512-cEKPM+fwb3cT8NzQZYEu4HilJ3anCrWqh3CHAok1p9jXqMPsPTBhU25fBckEJHJ/p+tTxTFTsFQGM+gaHpi3QQ==",
       "requires": {}
     },
     "brace-expansion": {
@@ -16692,9 +16739,9 @@
       }
     },
     "core-js": {
-      "version": "3.26.0",
-      "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.26.0.tgz",
-      "integrity": "sha512-+DkDrhoR4Y0PxDz6rurahuB+I45OsEUv8E1maPTB6OuHRohMMcznBq9TMpdpDMm/hUPob/mJJS3PqgbHpMTQgw=="
+      "version": "3.26.1",
+      "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.26.1.tgz",
+      "integrity": "sha512-21491RRQVzUn0GGM9Z1Jrpr6PNPxPi+Za8OM9q4tksTSnlbXXGKK1nXNg/QvwFYettXvSX6zWKCtHHfjN4puyA=="
     },
     "core-js-compat": {
       "version": "3.23.4",
@@ -17385,9 +17432,9 @@
       "dev": true
     },
     "eslint": {
-      "version": "8.26.0",
-      "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.26.0.tgz",
-      "integrity": "sha512-kzJkpaw1Bfwheq4VXUezFriD1GxszX6dUekM7Z3aC2o4hju+tsR/XyTC3RcoSD7jmy9VkPU3+N6YjVU2e96Oyg==",
+      "version": "8.28.0",
+      "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.28.0.tgz",
+      "integrity": "sha512-S27Di+EVyMxcHiwDrFzk8dJYAaD+/5SoWKxL1ri/71CRHsnJnRDPNt2Kzj24+MT9FDupf4aqqyqPrvI8MvQ4VQ==",
       "dev": true,
       "requires": {
         "@eslint/eslintrc": "^1.3.3",
@@ -17909,9 +17956,9 @@
       }
     },
     "eslint-plugin-vue": {
-      "version": "9.6.0",
-      "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.6.0.tgz",
-      "integrity": "sha512-zzySkJgVbFCylnG2+9MDF7N+2Rjze2y0bF8GyUNpFOnT8mCMfqqtLDJkHBuYu9N/psW1A6DVbQhPkP92E+qakA==",
+      "version": "9.8.0",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.8.0.tgz",
+      "integrity": "sha512-E/AXwcTzunyzM83C2QqDHxepMzvI2y6x+mmeYHbVDQlKFqmKYvRrhaVixEeeG27uI44p9oKDFiyCRw4XxgtfHA==",
       "dev": true,
       "requires": {
         "eslint-utils": "^3.0.0",
@@ -17935,12 +17982,12 @@
       }
     },
     "eslint-plugin-vuejs-accessibility": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/eslint-plugin-vuejs-accessibility/-/eslint-plugin-vuejs-accessibility-1.2.0.tgz",
-      "integrity": "sha512-wF7kT22lS2VOmIpDeI65bnFFKFgESEEpI+CWKr43mdfDRywA4sCk7cKhtZsvfbPOtKO0GDlnpFxZbOIGsFn7IQ==",
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-vuejs-accessibility/-/eslint-plugin-vuejs-accessibility-2.0.0.tgz",
+      "integrity": "sha512-mjbXnncDT9+5K+/QXXhOVWhEU6OOJck/JNlC6tewo3R+Kzsbaecyq3ylN1NqmyKo78vsgun34JLd+vGdxSPFWQ==",
       "dev": true,
       "requires": {
-        "aria-query": "^5.0.0",
+        "aria-query": ">=5.0.0",
         "emoji-regex": "^10.0.0",
         "vue-eslint-parser": "^9.0.1"
       },
@@ -18474,9 +18521,9 @@
       "dev": true
     },
     "fs-extra": {
-      "version": "10.1.0",
-      "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
-      "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
+      "version": "11.0.0",
+      "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.0.0.tgz",
+      "integrity": "sha512-4YxRvMi4P5C3WQTvdRfrv5UVqbISpqjORFQAW5QPiKAauaxNCwrEdIi6pG3tDFhKKpMen+enEhHIzB/tvIO+/w==",
       "dev": true,
       "requires": {
         "graceful-fs": "^4.2.0",
@@ -19699,9 +19746,9 @@
       }
     },
     "marked": {
-      "version": "4.1.1",
-      "resolved": "https://registry.npmjs.org/marked/-/marked-4.1.1.tgz",
-      "integrity": "sha512-0cNMnTcUJPxbA6uWmCmjWz4NJRe/0Xfk2NhXCUHjew9qJzFN20krFnsUe7QynwqOwa5m1fZ4UDg0ycKFVC0ccw=="
+      "version": "4.2.3",
+      "resolved": "https://registry.npmjs.org/marked/-/marked-4.2.3.tgz",
+      "integrity": "sha512-slWRdJkbTZ+PjkyJnE30Uid64eHwbwa1Q25INCAYfZlK4o6ylagBy/Le9eWntqJFoFT93ikUKMv47GZ4gTwHkw=="
     },
     "mdn-data": {
       "version": "2.0.14",
@@ -19931,6 +19978,12 @@
       "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
       "dev": true
     },
+    "natural-compare-lite": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz",
+      "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==",
+      "dev": true
+    },
     "negotiator": {
       "version": "0.6.3",
       "resolved": "https://registry.npmmirror.com/negotiator/-/negotiator-0.6.3.tgz",
@@ -20405,11 +20458,11 @@
       "dev": true
     },
     "pinia": {
-      "version": "2.0.23",
-      "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.0.23.tgz",
-      "integrity": "sha512-N15hFf4o5STrxpNrib1IEb1GOArvPYf1zPvQVRGOO1G1d74Ak0J0lVyalX/SmrzdT4Q0nlEFjbURsmBmIGUR5Q==",
+      "version": "2.0.27",
+      "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.0.27.tgz",
+      "integrity": "sha512-nOnXP0OFeL8R4WjAHsterU+11vptda643gH02xKNtSCDPiRzVfRYodOLihLDoa0gL1KKuQKV+KOzEgdt3YvqEw==",
       "requires": {
-        "@vue/devtools-api": "^6.4.4",
+        "@vue/devtools-api": "^6.4.5",
         "vue-demi": "*"
       },
       "dependencies": {
@@ -21190,9 +21243,9 @@
       "dev": true
     },
     "sass": {
-      "version": "1.55.0",
-      "resolved": "https://registry.npmjs.org/sass/-/sass-1.55.0.tgz",
-      "integrity": "sha512-Pk+PMy7OGLs9WaxZGJMn7S96dvlyVBwwtToX895WmCpAOr5YiJYEUJfiJidMuKb613z2xNWcXCHEuOvjZbqC6A==",
+      "version": "1.56.1",
+      "resolved": "https://registry.npmjs.org/sass/-/sass-1.56.1.tgz",
+      "integrity": "sha512-VpEyKpyBPCxE7qGDtOcdJ6fFbcpOM+Emu7uZLxVrkX8KVU/Dp5UF7WLvzqRuUhB6mqqQt1xffLoG+AndxTZrCQ==",
       "dev": true,
       "requires": {
         "chokidar": ">=3.0.0 <4.0.0",
@@ -21201,9 +21254,9 @@
       }
     },
     "sass-loader": {
-      "version": "13.1.0",
-      "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-13.1.0.tgz",
-      "integrity": "sha512-tZS1RJQ2n2+QNyf3CCAo1H562WjL/5AM6Gi8YcPVVoNxQX8d19mx8E+8fRrMWsyc93ZL6Q8vZDSM0FHVTJaVnQ==",
+      "version": "13.2.0",
+      "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-13.2.0.tgz",
+      "integrity": "sha512-JWEp48djQA4nbZxmgC02/Wh0eroSUutulROUusYJO9P9zltRbNN80JCBHqRGzjd4cmZCa/r88xgfkjGD0TXsHg==",
       "dev": true,
       "requires": {
         "klona": "^2.0.4",
@@ -22030,9 +22083,9 @@
       }
     },
     "typescript": {
-      "version": "4.8.4",
-      "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz",
-      "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==",
+      "version": "4.9.3",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.3.tgz",
+      "integrity": "sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==",
       "devOptional": true
     },
     "uglify-js": {
@@ -22154,15 +22207,15 @@
       "dev": true
     },
     "vue": {
-      "version": "3.2.41",
-      "resolved": "https://registry.npmjs.org/vue/-/vue-3.2.41.tgz",
-      "integrity": "sha512-uuuvnrDXEeZ9VUPljgHkqB5IaVO8SxhPpqF2eWOukVrBnRBx2THPSGQBnVRt0GrIG1gvCmFXMGbd7FqcT1ixNQ==",
-      "requires": {
-        "@vue/compiler-dom": "3.2.41",
-        "@vue/compiler-sfc": "3.2.41",
-        "@vue/runtime-dom": "3.2.41",
-        "@vue/server-renderer": "3.2.41",
-        "@vue/shared": "3.2.41"
+      "version": "3.2.45",
+      "resolved": "https://registry.npmjs.org/vue/-/vue-3.2.45.tgz",
+      "integrity": "sha512-9Nx/Mg2b2xWlXykmCwiTUCWHbWIj53bnkizBxKai1g61f2Xit700A1ljowpTIM11e3uipOeiPcSqnmBg6gyiaA==",
+      "requires": {
+        "@vue/compiler-dom": "3.2.45",
+        "@vue/compiler-sfc": "3.2.45",
+        "@vue/runtime-dom": "3.2.45",
+        "@vue/server-renderer": "3.2.45",
+        "@vue/shared": "3.2.45"
       }
     },
     "vue-eslint-parser": {
diff --git a/package.json b/package.json
index 626e4811ce0e0f2ae16765821d095f45e89f7edf..0c1cce6bc86559c4b58a07fbd63e5b6d2b499638 100644
--- a/package.json
+++ b/package.json
@@ -7,7 +7,7 @@
     "nacsos_pipe": "http://127.0.0.1:8000"
   },
   "scripts": {
-    "serve": "vue-cli-service serve",
+    "serve": "vue-cli-service serve --host localhost --mode development",
     "build": "vue-cli-service build",
     "lint": "vue-cli-service lint",
     "api-core": "node ./tools/openapi-gen/bin/index.js --input $npm_package_config_nacsos_core/openapi.json --output src/plugins/api/api-core --name CoreClient --client axios --indent 2 --useOptions --exportModels true --exportServices true --exportSchemas true --exportCore false --corePathTop @/plugins/api/core --corePathDeep @/plugins/api/core",
@@ -15,28 +15,28 @@
     "build-dev": "vue-cli-service build --mode=development"
   },
   "dependencies": {
-    "@fortawesome/fontawesome-svg-core": "^6.2.0",
-    "@fortawesome/free-brands-svg-icons": "^6.2.0",
-    "@fortawesome/free-regular-svg-icons": "^6.2.0",
-    "@fortawesome/free-solid-svg-icons": "^6.2.0",
-    "@fortawesome/vue-fontawesome": "^3.0.1",
+    "@fortawesome/fontawesome-svg-core": "^6.2.1",
+    "@fortawesome/free-brands-svg-icons": "^6.2.1",
+    "@fortawesome/free-regular-svg-icons": "^6.2.1",
+    "@fortawesome/free-solid-svg-icons": "^6.2.1",
+    "@fortawesome/vue-fontawesome": "^3.0.2",
     "@vuelidate/core": "^2.0.0",
     "@vuelidate/validators": "^2.0.0",
-    "@vueuse/core": "^9.3.1",
-    "axios": "^1.1.3",
-    "bootstrap": "^5.2.2",
-    "core-js": "^3.26.0",
+    "@vueuse/core": "^9.6.0",
+    "axios": "^1.2.0",
+    "bootstrap": "^5.2.3",
+    "core-js": "^3.26.1",
     "form-data": "^4.0.0",
-    "marked": "^4.1.1",
-    "pinia": "^2.0.23",
-    "vue": "^3.2.41",
+    "marked": "^4.2.3",
+    "pinia": "^2.0.27",
+    "vue": "^3.2.45",
     "vue-router": "^4.1.6"
   },
   "devDependencies": {
     "@rushstack/eslint-patch": "^1.2.0",
     "@types/marked": "^4.0.7",
-    "@typescript-eslint/eslint-plugin": "^5.40.1",
-    "@typescript-eslint/parser": "^5.40.1",
+    "@typescript-eslint/eslint-plugin": "^5.45.0",
+    "@typescript-eslint/parser": "^5.45.0",
     "@vue/cli-plugin-babel": "^5.0.8",
     "@vue/cli-plugin-eslint": "^5.0.8",
     "@vue/cli-plugin-router": "^5.0.8",
@@ -44,16 +44,16 @@
     "@vue/cli-plugin-vuex": "^5.0.8",
     "@vue/cli-service": "^5.0.8",
     "@vue/eslint-config-airbnb-with-typescript": "^7.0.0",
-    "eslint": "^8.26.0",
+    "eslint": "^8.28.0",
     "eslint-plugin-import": "^2.26.0",
-    "eslint-plugin-vue": "^9.6.0",
-    "eslint-plugin-vuejs-accessibility": "^1.2.0",
-    "sass": "^1.55.0",
-    "sass-loader": "^13.1.0",
-    "typescript": "^4.8.4",
+    "eslint-plugin-vue": "^9.8.0",
+    "eslint-plugin-vuejs-accessibility": "^2.0.0",
+    "sass": "^1.56.1",
+    "sass-loader": "^13.2.0",
+    "typescript": "^4.9.3",
     "camelcase": "^6.3.0",
     "commander": "^9.4.1",
-    "fs-extra": "^10.1.0",
+    "fs-extra": "^11.0.0",
     "handlebars": "^4.7.7",
     "json-schema-ref-parser": "^9.0.9"
   }
diff --git a/src/assets/style.css b/src/assets/style.css
index 42e37e1eef1e286954d5e82e5040bcfd2bb2efbb..3c79ec9d6b890c113ad58622f0de358d18986e54 100644
--- a/src/assets/style.css
+++ b/src/assets/style.css
@@ -19,6 +19,11 @@
 .nacsos-tooltip {
     position: relative;
     display: inline-block;
+
+    --tooltip-margin-x: 1rem;
+    --tooltip-margin-y: -1rem;
+    --tooltip-padding-x: 1rem;
+    --tooltip-padding-y: 0.5rem;
 }
 
 /* Tooltip text */
@@ -27,29 +32,45 @@
     visibility: hidden;
     background-color: rgba(0, 0, 0, 0.9);
     color: #fff;
-    padding: 0.5rem 1rem;
-    margin: -1rem 1rem;
+    padding: var(--tooltip-padding-y) var(--tooltip-padding-x);
+    margin: var(--tooltip-margin-y) var(--tooltip-margin-x);
     border-radius: 6px;
 
     /* Position the tooltip text - see examples below! */
     position: absolute;
     z-index: 1;
+    inline-size: max-content;
+}
+
+.nacsos-tooltip > .right {
+    transform: translate(0%, 0%);
+    --tooltip-margin-x: 0.2rem;
+}
+
+.nacsos-tooltip > .top {
+    transform: translate(-50%, -100%);
+}
+
+.nacsos-tooltip > .bottom {
+    transform: translate(-50%, 33%);
+}
+
+.nacsos-tooltip > .left {
+    transform: translate(calc(-100% - 2 * var(--tooltip-padding-x)), -33%);
 }
 
 .nacsos-tooltip > .small {
     margin: 0;
-    transform: translate(-50%,-100%);
     max-width: 10rem;
     text-align: center;
-    inline-size: max-content;
 }
 
 .nacsos-tooltip > .medium {
-    width: 25rem;
+    max-width: 25rem;
 }
 
 .nacsos-tooltip > .wide {
-    width: 50rem;
+    max-width: 50rem;
 }
 
 /* Show the tooltip text when you mouse over the tooltip container */
@@ -96,3 +117,29 @@
 .collapsible > .toggle:checked + .lbl-toggle + .collapsible-content {
     max-height: 350px;
 }
+
+/*
+Analogous to LaTeX
+\tiny         .fs-tiny (0.5rem)
+\scriptsize   .fs-script (0.6125rem)
+\footnotesize .fs-fn (0.75rem)
+\small        .small (0.875rem)  # already in bootstrap
+\normalsize   .fs-6 (1.00rem)
+\large        .fs-5 (1.25rem)
+\Large        .fs-4 (1.50rem)
+\LARGE        .fs-3 (1.75rem)
+\huge         .fs-2 (2.00rem)
+\Huge         .fs-1 (2.50rem)
+*/
+
+.fs-tiny {
+    font-size: 0.5rem !important;
+}
+
+.fs-script {
+    font-size: 0.6125rem !important;
+}
+
+.fs-fn {
+    font-size: 0.75rem !important;
+}
\ No newline at end of file
diff --git a/src/components/InlineToolTip.vue b/src/components/InlineToolTip.vue
index 83319403f866c35dbdc11ed61ba2c2aefa6d579a..36ea948cf3ad2d3dc01693f9e453210c305cdedd 100644
--- a/src/components/InlineToolTip.vue
+++ b/src/components/InlineToolTip.vue
@@ -5,7 +5,7 @@
   <template v-else>
     <span class="nacsos-tooltip">
       <slot />
-      <span class="nacsos-tooltiptext small">
+      <span class="nacsos-tooltiptext" :class="[size, placement]">
         {{ info }}
       </span>
     </span>
@@ -14,8 +14,25 @@
 
 <script lang="ts">
 
+// type Placement = 'top' | 'left' | 'bottom' | 'right';
+// type Size = 'small' | 'medium' | 'wide';
 export default {
   name: 'InlineToolTip',
-  props: ['info'],
+  props: {
+    info: {
+      type: String,
+      required: true,
+    },
+    placement: {
+      type: String,
+      required: false,
+      default: 'top',
+    },
+    size: {
+      type: String,
+      required: false,
+      default: 'small',
+    },
+  },
 };
 </script>
diff --git a/src/components/SideBar.vue b/src/components/SideBar.vue
index 729b9e339f2cecb14631a99e48f08a51336e2c32..2de2e0d66c6cac104025d69aeab9d7379858c0ee 100644
--- a/src/components/SideBar.vue
+++ b/src/components/SideBar.vue
@@ -49,13 +49,13 @@
         v-if="projectPermissions.annotations_read && isActive('project-pipelines')"
         to="/project/pipelines/setup"
         class="list-group-item list-group-item-action list-group-item-info border-end-0 sub-link"
-        active-class="active"> Task Configuration
+        exact-active-class="active"> Task Configuration
       </router-link>
       <router-link
         v-if="projectPermissions.annotations_read && isActive('project-pipelines')"
         to="/project/pipelines/presets"
         class="list-group-item list-group-item-action list-group-item-info border-end-0 sub-link"
-        active-class="active"> Presets
+        exact-active-class="active"> Presets
       </router-link>
       <router-link
         v-if="projectPermissions.annotations_edit"
@@ -65,9 +65,26 @@
         <font-awesome-icon icon="gear" />
         Annotations
       </router-link>
+      <router-link
+        v-if="projectPermissions.annotations_edit && isActive('config-annotation-schemes')"
+        to="/project/config/annotations/list"
+        class="list-group-item list-group-item-action list-group-item-info border-end-0 sub-link"
+        :class="{
+          active: anyOf(['config-annotation-scheme-edit',
+                         'config-annotation-scheme-scope',
+                         'config-annotation-scheme-list']),
+        }"> Schemes & Scopes
+      </router-link>
+      <router-link
+        v-if="projectPermissions.annotations_edit && isActive('config-annotation-schemes')"
+        to="/project/config/annotations/resolved"
+        class="list-group-item list-group-item-action list-group-item-info border-end-0 sub-link"
+        :class="{ active: anyOf(['config-annotation-resolve', 'config-resolved-annotations-list']) }">
+        Label Centre
+      </router-link>
       <router-link
         v-if="projectPermissions.owner"
-        to="/project/config/project"
+        to="/project/settings"
         class="list-group-item list-group-item-action border-end-0"
         active-class="active">
         <font-awesome-icon icon="gear" />
@@ -120,12 +137,15 @@ export default {
     isActive(parentName: string): boolean {
       return this.$router.currentRoute.value.matched.some((route: RouteLocationMatched) => route.name === parentName);
     },
+    anyOf(routeNames: string[]): boolean {
+      return routeNames.indexOf(this.$router.currentRoute.value.name) >= 0;
+    },
     toggleVisibility(): void {
       this.visible = (this.visible === undefined) ? false : !this.visible;
     },
-    setVisibility(newState: boolean): void {
-      this.visible = newState;
-    },
+    // setVisibility(newState: boolean): void {
+    //   this.visible = newState;
+    // },
   },
   mounted() {
     window.onresize = () => {
diff --git a/src/components/annotations/resolve/BoolLabel.vue b/src/components/annotations/resolve/BoolLabel.vue
new file mode 100644
index 0000000000000000000000000000000000000000..732b164c4fcf8272d6b668c15198ae8a1c36daac
--- /dev/null
+++ b/src/components/annotations/resolve/BoolLabel.vue
@@ -0,0 +1,106 @@
+<template>
+  <div>
+    <span v-for="annotation in userAnnotations" :key="annotation.annotation_id">
+      <InlineToolTip :info="getPrettyUsername(annotation.user_id)">
+        <font-awesome-icon
+          :icon="['fas', annotation2icon(annotation.value_bool)]"
+          :class="[annotation2classes(annotation.value_bool)]"
+          class="border text-light p-1"
+          style="height: 1rem; width: 1rem;" />
+      </InlineToolTip>
+    </span>
+
+    <div class="dropdown ps-2 d-inline-block">
+      <font-awesome-icon
+        :icon="['fas', annotation2icon(botAnnotation.value_bool)]"
+        :class="annotation2classes(botAnnotation.value_bool)"
+        class="border border-dark border-2 rounded-3 text-light p-1 dropdown-toggle"
+        role="button"
+        style="height: 1rem; width: 1rem;"
+        @click="editMode = !editMode" />
+      <ul class="dropdown-menu end-0" :class="{ show: editMode }">
+        <li><span class="dropdown-item" role="button" tabindex="-1" @click="setBotAnnotation(true)">True</span></li>
+        <li><span class="dropdown-item" role="button" tabindex="-1" @click="setBotAnnotation(false)">False</span></li>
+        <li><span
+          class="dropdown-item"
+          role="button"
+          tabindex="-1"
+          @click="setBotAnnotation(undefined)">[NONE]</span></li>
+      </ul>
+    </div>
+  </div>
+</template>
+
+<script lang="ts">
+import { AnnotationModel, BotAnnotationModel, FlattenedAnnotationSchemeLabel, UserModel } from '@/plugins/api/api-core';
+import InlineToolTip from '@/components/InlineToolTip.vue';
+import { PropType } from 'vue';
+import { EventBus } from '@/plugins/events';
+import { ToastEvent } from '@/plugins/events/events/toast';
+
+interface BoolLabelData {
+  changed: boolean,
+  editMode: boolean,
+}
+
+export default {
+  name: 'BoolLabel',
+  components: { InlineToolTip },
+  data(): BoolLabelData {
+    return {
+      // set to true when bot annotation was manipulated
+      changed: false,
+      editMode: false,
+    };
+  },
+  emits: ['botAnnotationChanged'],
+  props: {
+    info: {
+      type: Object as PropType<FlattenedAnnotationSchemeLabel>,
+      required: true,
+    },
+    users: {
+      type: Object as PropType<Record<string, UserModel>>,
+      required: true,
+    },
+    userAnnotations: {
+      type: Array as PropType<AnnotationModel[]>,
+      required: true,
+    },
+    botAnnotation: {
+      type: Object as PropType<BotAnnotationModel>,
+      required: true,
+    },
+  },
+  methods: {
+    annotation2icon(val: boolean | undefined): string {
+      if (val === undefined) return 'question';
+      return (val) ? 'check' : 'xmark';
+    },
+    annotation2classes(val: boolean | undefined): string[] {
+      if (val === undefined) return ['bg-light', 'text-dark'];
+      return (val) ? ['bg-success', 'text-light'] : ['bg-danger', 'text-light'];
+    },
+    setBotAnnotation(value: boolean | undefined) {
+      if (this.botAnnotation !== undefined) {
+        const anno = this.botAnnotation;
+        anno.value_bool = value;
+        this.$emit('botAnnotationChanged', anno);
+        this.editMode = false;
+      } else {
+        // FIXME: not implemented (handle adding new BotAnnotation, i.e. handle the case where item has no annotation here)
+        // const anno: BotAnnotationModel = {};
+        EventBus.emit(new ToastEvent('WARN', 'Not implemented yet.'));
+      }
+    },
+    getPrettyUsername(userId: string): string {
+      const user: UserModel | undefined = this.users[userId];
+      if (!user) return '??';
+      return `${user.username} (${user.full_name})`;
+    },
+  },
+  computed: {
+    // pass
+  },
+};
+</script>
diff --git a/src/components/annotations/resolve/ChoiceLabel.vue b/src/components/annotations/resolve/ChoiceLabel.vue
new file mode 100644
index 0000000000000000000000000000000000000000..d3c2b445c3c152878694d44f5d14ff13bf47df62
--- /dev/null
+++ b/src/components/annotations/resolve/ChoiceLabel.vue
@@ -0,0 +1,150 @@
+<template>
+  <div v-if="userAnnotations !== undefined">
+
+    <!-- User Annotations -->
+    <span v-for="annotation in userAnnotations" :key="annotation.annotation_id">
+      <InlineToolTip :info="getPrettyUsername(annotation.user_id)">
+        <span
+          class="border text-light p-1 ps-2 pe-2"
+          :style="{ backgroundColor: annotation2bgColor(annotation) }">
+          <template v-if="annotation.value_int === undefined">
+            <font-awesome-icon :icon="['fas', 'question']" class="text-dark" />
+          </template>
+          <template v-else>
+            {{ annotation.value_int }}
+          </template>
+        </span>
+      </InlineToolTip>
+    </span>
+    <!-- / User Annotations -->
+
+    <!-- BotAnnotation -->
+    <div class="dropdown ps-2 d-inline-block">
+      <span
+        class="border text-light p-1 border-dark border-2 rounded-3 dropdown-toggle"
+        :style="{ backgroundColor: annotation2bgColor(botAnnotation) }"
+        role="button"
+        tabindex="-1"
+        @click="editMode = !editMode">
+        <template v-if="!hasValue(botAnnotation)">
+          <font-awesome-icon :icon="['fas', 'question']" class="text-dark" />
+        </template>
+        <template v-else>
+          {{ botAnnotation.value_int }}
+        </template>
+      </span>
+      <ul class="dropdown-menu end-0" :class="{ show: editMode }">
+        <li v-for="choice in info.choices" :key="choice.value">
+          <span class="dropdown-item" role="button" tabindex="-1" @click="setBotAnnotation(choice.value)">
+            {{ choice.name }} ({{ choice.value }})
+          </span>
+        </li>
+        <li><span
+          class="dropdown-item"
+          role="button"
+          tabindex="-1"
+          @click="setBotAnnotation(undefined)">[NONE]</span></li>
+      </ul>
+    </div>
+    <!-- / BotAnnotation -->
+
+  </div>
+</template>
+
+<script lang="ts">
+
+import {
+  AnnotationModel,
+  AnnotationSchemeLabelChoiceFlat,
+  BotAnnotationModel,
+  FlattenedAnnotationSchemeLabel, UserModel,
+} from '@/plugins/api/api-core';
+import InlineToolTip from '@/components/InlineToolTip.vue';
+import { PropType } from 'vue';
+import { cmap10, cmap20 } from '@/types/colours';
+import { EventBus } from '@/plugins/events';
+import { ToastEvent } from '@/plugins/events/events/toast';
+
+function hasValue(model: AnnotationModel | BotAnnotationModel | undefined | null):
+  model is (AnnotationModel | BotAnnotationModel) & { value_int: number } {
+  if (model === null || model === undefined) return false;
+  return (model.value_int !== undefined && model.value_int !== null);
+}
+
+interface ChoiceLabelData {
+  changed: boolean,
+  editMode: boolean,
+}
+
+export default {
+  name: 'ChoiceLabel',
+  components: { InlineToolTip },
+  data(): ChoiceLabelData {
+    return {
+      changed: false,
+      editMode: false,
+    };
+  },
+  emits: ['botAnnotationChanged', 'botAnnotationConfirmed'],
+  props: {
+    info: {
+      type: Object as PropType<FlattenedAnnotationSchemeLabel>,
+      required: true,
+    },
+    users: {
+      type: Object as PropType<Record<string, UserModel>>,
+      required: true,
+    },
+    userAnnotations: {
+      type: Array as PropType<AnnotationModel[]>,
+      required: false,
+      default: () => undefined,
+    },
+    botAnnotation: {
+      type: Object as PropType<BotAnnotationModel>,
+      required: false,
+      default: () => undefined,
+    },
+  },
+  methods: {
+    hasValue(model: AnnotationModel | BotAnnotationModel | undefined | null):
+      model is (AnnotationModel | BotAnnotationModel) & { value_int: number } {
+      return hasValue(model);
+    },
+    annotation2bgColor(val: AnnotationModel | BotAnnotationModel | undefined) {
+      if (hasValue(val)) {
+        return this.cmap[val.value_int % this.cmap.length];
+      }
+      return 'transparent';
+    },
+    setBotAnnotation(value: number | undefined) {
+      if (this.botAnnotation !== undefined) {
+        if (this.botAnnotation.value_int !== value) {
+          this.changed = true;
+          const anno = this.botAnnotation;
+          anno.value_int = value;
+          this.$emit('botAnnotationChanged', anno);
+          this.editMode = false;
+        }
+      } else {
+        // FIXME: not implemented (handle adding new BotAnnotation, i.e. handle the case where item has no annotation here)
+        // const anno: BotAnnotationModel = {};
+        EventBus.emit(new ToastEvent('WARN', 'Not implemented yet.'));
+      }
+    },
+    getPrettyUsername(userId: string): string {
+      const user: UserModel | undefined = this.users[userId];
+      if (!user) return '??';
+      return `${user.username} (${user.full_name})`;
+    },
+  },
+  computed: {
+    cmap(): string[] {
+      return (this.info.choices.length > 10) ? cmap20 : cmap10;
+    },
+    choiceLookup(): Record<number, AnnotationSchemeLabelChoiceFlat> {
+      return Object.fromEntries(this.info.choices.map((choice: AnnotationSchemeLabelChoiceFlat) => [choice.value, choice]));
+    },
+  },
+};
+</script>
diff --git a/src/components/imports/ConfigJSONL.vue b/src/components/imports/ConfigJSONL.vue
index 633b0f729f98d255505a0c267e2411be2d086864..90af2dfedc889e8e494f37db043111afe7f4b86d 100644
--- a/src/components/imports/ConfigJSONL.vue
+++ b/src/components/imports/ConfigJSONL.vue
@@ -50,15 +50,15 @@
 <script lang="ts">
 import FilesUploader, { UploadFile } from '@/components/FilesUploader.vue';
 import { PropType } from 'vue';
-import { ImportConfigJSONL, ProjectType } from '@/plugins/api/api-core';
+import { ImportConfigJSONL, ItemType } from '@/plugins/api/api-core';
 import { currentProjectStore } from '@/stores';
 import useVuelidate, { BaseValidation, ValidationRule } from '@vuelidate/core';
 import { required } from '@vuelidate/validators';
 import types = ImportConfigJSONL.line_type;
 
-type CompatibilityMapping = { [key in ProjectType]: types[] };
+type CompatibilityMapping = { [key in ItemType]: types[] };
 const jsonlTypeCompatibility: CompatibilityMapping = {
-  basic: [types.DB_BASIC_ITEM],
+  generic: [types.DB_GENERIC_ITEM],
   academic: [types.DB_ACADEMIC_ITEM],
   patents: [types.DB_PATENT_ITEM],
   twitter: [types.DB_TWITTER_ITEM, types.TWITTER_API_PAGE],
diff --git a/src/components/items/AnyItem.vue b/src/components/items/AnyItem.vue
new file mode 100644
index 0000000000000000000000000000000000000000..d203800709e46700ecfe66817e524aed5b6caf04
--- /dev/null
+++ b/src/components/items/AnyItem.vue
@@ -0,0 +1,42 @@
+<template>
+  <component :is="component" :item="item" />
+</template>
+
+<script lang="ts">
+import { AnyItem } from '@/types/items.d';
+import { PropType, Component } from 'vue';
+import TwitterItemComponent from '@/components/items/TwitterItem.vue';
+import GenericItemComponent from '@/components/items/GenericItem.vue';
+import { useCurrentProjectStore } from '@/stores/CurrentProjectStore';
+import { ItemType } from '@/plugins/api/api-core';
+
+type TypeMapType = { [key in ItemType]: Component };
+
+export default {
+  name: 'GenericItem',
+  props: {
+    item: {
+      type: Object as PropType<AnyItem>,
+      required: true,
+      default: null,
+    },
+  },
+  data() {
+    const typeMap: TypeMapType = {
+      generic: GenericItemComponent,
+      twitter: TwitterItemComponent,
+      academic: GenericItemComponent, // FIXME: replace with correct component
+      patents: GenericItemComponent, // FIXME: replace with correct component
+    };
+    const store = useCurrentProjectStore();
+    const { type } = store.project;
+    return {
+      component: typeMap[type],
+    };
+  },
+};
+</script>
+
+<style scoped>
+
+</style>
diff --git a/src/components/items/BaseItem.vue b/src/components/items/BaseItem.vue
deleted file mode 100644
index 0fa323e41927f930cb5925ca08e0265caf2b253e..0000000000000000000000000000000000000000
--- a/src/components/items/BaseItem.vue
+++ /dev/null
@@ -1,42 +0,0 @@
-<template>
-  <div class="card m-2 p-0 text-start">
-    <div class="card-body">
-      <p class="card-text" v-html="htmlText" />
-    </div>
-    <div class="card-footer d-flex justify-content-between small text-muted" v-if="item.meta">
-      <ul class="list-unstyled">
-        <template v-for="(value, key) in item.meta" :key="key">
-          <li v-if="!key.startsWith('_')">
-            <strong>{{ key }}:</strong> {{ value }}
-          </li>
-        </template>
-      </ul>
-    </div>
-  </div>
-</template>
-
-<script lang="ts">
-import { PropType } from 'vue';
-import { marked } from 'marked';
-import { BaseItem as BaseItemModel } from '@/types/items.d';
-
-export default {
-  name: 'BaseItem',
-  props: {
-    item: {
-      type: Object as PropType<BaseItemModel>,
-      required: true,
-      default: null,
-    },
-  },
-  computed: {
-    htmlText() {
-      return marked(this.item.text);
-    },
-  },
-};
-</script>
-
-<style scoped>
-
-</style>
diff --git a/src/components/items/GenericItem.vue b/src/components/items/GenericItem.vue
index 267c298271b869d61988739b3f6465c5ab572e05..aee42f84e57cc5d93beef1cb4dcb1e91765c137b 100644
--- a/src/components/items/GenericItem.vue
+++ b/src/components/items/GenericItem.vue
@@ -1,38 +1,38 @@
 <template>
-  <component :is="component" :item="item" />
+  <div class="card m-2 p-0 text-start">
+    <div class="card-body">
+      <p class="card-text" v-html="htmlText" />
+    </div>
+    <div class="card-footer d-flex justify-content-between small text-muted" v-if="item.meta">
+      <ul class="list-unstyled">
+        <template v-for="(value, key) in item.meta" :key="key">
+          <li v-if="!key.startsWith('_')">
+            <strong>{{ key }}:</strong> {{ value }}
+          </li>
+        </template>
+      </ul>
+    </div>
+  </div>
 </template>
 
 <script lang="ts">
-import { AnyItem } from '@/types/items.d';
-import { PropType, Component } from 'vue';
-import TwitterItemComponent from '@/components/items/TwitterItem.vue';
-import BaseItemComponent from '@/components/items/BaseItem.vue';
-import { useCurrentProjectStore } from '@/stores/CurrentProjectStore';
-import { ProjectType } from '@/plugins/api/api-core';
-
-type TypeMapType = { [key in ProjectType]: Component };
+import { PropType } from 'vue';
+import { marked } from 'marked';
+import { BaseItem as BaseItemModel } from '@/types/items.d';
 
 export default {
   name: 'GenericItem',
   props: {
     item: {
-      type: Object as PropType<AnyItem>,
+      type: Object as PropType<BaseItemModel>,
       required: true,
       default: null,
     },
   },
-  data() {
-    const typeMap: TypeMapType = {
-      basic: BaseItemComponent,
-      twitter: TwitterItemComponent,
-      academic: BaseItemComponent, // FIXME: replace with correct component
-      patents: BaseItemComponent, // FIXME: replace with correct component
-    };
-    const store = useCurrentProjectStore();
-    const { type } = store.project;
-    return {
-      component: typeMap[type],
-    };
+  computed: {
+    htmlText() {
+      return marked(this.item.text);
+    },
   },
 };
 </script>
diff --git a/src/components/items/ItemModal.vue b/src/components/items/ItemModal.vue
new file mode 100644
index 0000000000000000000000000000000000000000..8cb5f048cbbe2676839d5a750d8cbc0a291c64c4
--- /dev/null
+++ b/src/components/items/ItemModal.vue
@@ -0,0 +1,110 @@
+<template>
+  <div v-if="showItemModal">
+    <div
+      class="modal fade show"
+      data-bs-backdrop="static"
+      data-bs-keyboard="false"
+      tabindex="-1"
+      style="display: block"
+      @click="dismissModal"
+      aria-hidden="true">
+      <div class="modal-dialog modal-xl modal-dialog-scrollable" @click.stop="stop">
+        <div class="modal-content">
+          <div class="modal-header">
+            <h1 class="modal-title fs-5" id="staticBackdropLabel">Details for item {{ itemId }}</h1>
+            <button type="button" class="btn-close" aria-label="Close" @click="dismissModal" />
+          </div>
+          <div class="modal-body">
+            <template v-if="isLoading">
+              <p class="card-text placeholder-glow">
+                <span class="placeholder col-7" />
+                <span class="placeholder col-4" />
+                <span class="placeholder col-4" />
+                <span class="placeholder col-6" />
+                <span class="placeholder col-8" />
+              </p>
+            </template>
+            <template v-else>
+              <AnyItemComponent :item="itemInfo" />
+            </template>
+          </div>
+          <!--          <div class="modal-footer">-->
+          <!--            <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>-->
+          <!--            <button type="button" class="btn btn-primary">Understood</button>-->
+          <!--          </div>-->
+        </div>
+      </div>
+    </div>
+    <div class="modal-backdrop fade show" />
+  </div>
+</template>
+
+<script lang="ts">
+
+import { AnyItem } from '@/types/items';
+import { API } from '@/plugins/api';
+import { currentProjectStore } from '@/stores';
+import { CancelablePromise } from '@/plugins/api/core/CancelablePromise';
+import AnyItemComponent from '@/components/items/AnyItem.vue';
+
+type ItemModalData = {
+  itemInfo: AnyItem | undefined,
+  requestPromise: CancelablePromise<AnyItem> | undefined,
+};
+
+export default {
+  components: { AnyItemComponent },
+  props: ['itemId'],
+  emits: ['dismissed'],
+  data(): ItemModalData {
+    return {
+      itemInfo: undefined,
+      requestPromise: undefined,
+    };
+  },
+  computed: {
+    showItemModal() {
+      // show modal if data is present or request is running
+      return this.itemInfo !== undefined || this.requestPromise !== undefined;
+    },
+    isLoading() {
+      return this.requestPromise !== undefined;
+    },
+  },
+  methods: {
+    getItemInfo(itemId: string) {
+      this.itemInfo = null;
+      this.requestPromise = API.core.project.getDetailForItemApiProjectItemsDetailItemIdGet({
+        itemId,
+        xProjectId: currentProjectStore.projectId,
+      }).then((result) => {
+        this.itemInfo = result.data;
+        this.requestPromise = undefined;
+      }).catch(() => {
+        this.dismissModal();
+      });
+    },
+    dismissModal() {
+      this.resetRequest();
+      this.itemInfo = undefined;
+      this.$emit('dismissed');
+    },
+    resetRequest() {
+      if (this.requestPromise !== undefined) {
+        this.requestPromise.cancel();
+        this.requestPromise = undefined;
+      }
+    },
+  },
+  watch: {
+    itemId(newId: string | null | undefined) {
+      // reset any prior request (if present)
+      this.resetRequest();
+      // fetch the data
+      if (newId !== null && newId !== undefined) {
+        this.getItemInfo(newId);
+      }
+    },
+  },
+};
+</script>
diff --git a/src/components/items/TwitterItem.vue b/src/components/items/TwitterItem.vue
index 77afd5d453a0eeac0ca51ce31efbc8dbc02b66d8..fc74d3012286f0662c6659fd73e74c8b51adb9eb 100644
--- a/src/components/items/TwitterItem.vue
+++ b/src/components/items/TwitterItem.vue
@@ -90,11 +90,11 @@ export default {
         .sort((a, b) => a.start - b.start)
         .forEach((replacement) => {
           // FIXME: something has to be done with the slicing offsets... sometimes they are off
-          ret += this.item.status.slice(prevEnd, replacement.start);
+          ret += this.item.text.slice(prevEnd, replacement.start);
           ret += replacement.html;
           prevEnd = replacement.end;
         });
-      ret += this.item.status.slice(prevEnd, this.item.status.length);
+      ret += this.item.text.slice(prevEnd, this.item.text.length);
       return ret;
     },
   },
diff --git a/src/plugins/api/api-core/index.ts b/src/plugins/api/api-core/index.ts
index 7e005efbb4e144df85fbd8d735274c12f6f9e5b7..d380149dcfba79cc65370cb426bf94e437a84a4b 100644
--- a/src/plugins/api/api-core/index.ts
+++ b/src/plugins/api/api-core/index.ts
@@ -4,21 +4,35 @@
 export { CoreClient } from './CoreClient';
 
 
+export type { AcademicItemModel } from './models/AcademicItemModel';
 export type { AnnotatedItem } from './models/AnnotatedItem';
+export type { AnnotationCollection } from './models/AnnotationCollection';
+export type { AnnotationCollectionDB } from './models/AnnotationCollectionDB';
+export type { AnnotationFilters } from './models/AnnotationFilters';
 export type { AnnotationItem } from './models/AnnotationItem';
 export type { AnnotationModel } from './models/AnnotationModel';
 export { AnnotationSchemeLabel } from './models/AnnotationSchemeLabel';
 export type { AnnotationSchemeLabelChoice } from './models/AnnotationSchemeLabelChoice';
+export type { AnnotationSchemeLabelChoiceFlat } from './models/AnnotationSchemeLabelChoiceFlat';
 export type { AnnotationSchemeModel } from './models/AnnotationSchemeModel';
+export type { AnnotationSchemeModelFlat } from './models/AnnotationSchemeModelFlat';
 export type { AssignmentCounts } from './models/AssignmentCounts';
 export type { AssignmentModel } from './models/AssignmentModel';
 export type { AssignmentScopeModel } from './models/AssignmentScopeModel';
 export { AssignmentScopeRandomConfig } from './models/AssignmentScopeRandomConfig';
 export { AssignmentStatus } from './models/AssignmentStatus';
 export type { Body_login_for_access_token_api_login_token_post } from './models/Body_login_for_access_token_api_login_token_post';
+export type { BotAnnotationMetaDataBaseModel } from './models/BotAnnotationMetaDataBaseModel';
+export type { BotAnnotationModel } from './models/BotAnnotationModel';
+export { BotKind } from './models/BotKind';
+export { BotMetaResolve } from './models/BotMetaResolve';
 export type { Cashtag } from './models/Cashtag';
 export type { ContextAnnotation } from './models/ContextAnnotation';
 export { Event } from './models/Event';
+export { FlattenedAnnotationSchemeLabel } from './models/FlattenedAnnotationSchemeLabel';
+export type { GenericItemModel } from './models/GenericItemModel';
+export type { GroupedAnnotations } from './models/GroupedAnnotations';
+export type { GroupedBotAnnotation } from './models/GroupedBotAnnotation';
 export type { Hashtag } from './models/Hashtag';
 export type { HTTPValidationError } from './models/HTTPValidationError';
 export { ImportConfigJSONL } from './models/ImportConfigJSONL';
@@ -26,8 +40,9 @@ export type { ImportConfigRIS } from './models/ImportConfigRIS';
 export { ImportConfigTwitter } from './models/ImportConfigTwitter';
 export type { ImportModel } from './models/ImportModel';
 export { ImportType } from './models/ImportType';
-export type { ItemModel } from './models/ItemModel';
+export { ItemType } from './models/ItemType';
 export type { ItemWithCount } from './models/ItemWithCount';
+export type { Label } from './models/Label';
 export type { MakeAssignmentsRequestModel } from './models/MakeAssignmentsRequestModel';
 export type { Mention } from './models/Mention';
 export { PipelineTaskStatusChangedEvent } from './models/PipelineTaskStatusChangedEvent';
@@ -36,8 +51,10 @@ export { PipelineTaskStatusFailedEvent } from './models/PipelineTaskStatusFailed
 export { PipelineTaskStatusStartedEvent } from './models/PipelineTaskStatusStartedEvent';
 export type { ProjectModel } from './models/ProjectModel';
 export type { ProjectPermissionsModel } from './models/ProjectPermissionsModel';
-export { ProjectType } from './models/ProjectType';
 export { ReferencedTweet } from './models/ReferencedTweet';
+export { ResolutionPayload } from './models/ResolutionPayload';
+export type { ResolutionProposalResponse } from './models/ResolutionProposalResponse';
+export type { SavedResolutionResponse } from './models/SavedResolutionResponse';
 export type { Token } from './models/Token';
 export type { TwitterItemModel } from './models/TwitterItemModel';
 export type { TwitterUserModel } from './models/TwitterUserModel';
@@ -46,21 +63,35 @@ export type { UserModel } from './models/UserModel';
 export type { UserProjectAssignmentScope } from './models/UserProjectAssignmentScope';
 export type { ValidationError } from './models/ValidationError';
 
+export { $AcademicItemModel } from './schemas/$AcademicItemModel';
 export { $AnnotatedItem } from './schemas/$AnnotatedItem';
+export { $AnnotationCollection } from './schemas/$AnnotationCollection';
+export { $AnnotationCollectionDB } from './schemas/$AnnotationCollectionDB';
+export { $AnnotationFilters } from './schemas/$AnnotationFilters';
 export { $AnnotationItem } from './schemas/$AnnotationItem';
 export { $AnnotationModel } from './schemas/$AnnotationModel';
 export { $AnnotationSchemeLabel } from './schemas/$AnnotationSchemeLabel';
 export { $AnnotationSchemeLabelChoice } from './schemas/$AnnotationSchemeLabelChoice';
+export { $AnnotationSchemeLabelChoiceFlat } from './schemas/$AnnotationSchemeLabelChoiceFlat';
 export { $AnnotationSchemeModel } from './schemas/$AnnotationSchemeModel';
+export { $AnnotationSchemeModelFlat } from './schemas/$AnnotationSchemeModelFlat';
 export { $AssignmentCounts } from './schemas/$AssignmentCounts';
 export { $AssignmentModel } from './schemas/$AssignmentModel';
 export { $AssignmentScopeModel } from './schemas/$AssignmentScopeModel';
 export { $AssignmentScopeRandomConfig } from './schemas/$AssignmentScopeRandomConfig';
 export { $AssignmentStatus } from './schemas/$AssignmentStatus';
 export { $Body_login_for_access_token_api_login_token_post } from './schemas/$Body_login_for_access_token_api_login_token_post';
+export { $BotAnnotationMetaDataBaseModel } from './schemas/$BotAnnotationMetaDataBaseModel';
+export { $BotAnnotationModel } from './schemas/$BotAnnotationModel';
+export { $BotKind } from './schemas/$BotKind';
+export { $BotMetaResolve } from './schemas/$BotMetaResolve';
 export { $Cashtag } from './schemas/$Cashtag';
 export { $ContextAnnotation } from './schemas/$ContextAnnotation';
 export { $Event } from './schemas/$Event';
+export { $FlattenedAnnotationSchemeLabel } from './schemas/$FlattenedAnnotationSchemeLabel';
+export { $GenericItemModel } from './schemas/$GenericItemModel';
+export { $GroupedAnnotations } from './schemas/$GroupedAnnotations';
+export { $GroupedBotAnnotation } from './schemas/$GroupedBotAnnotation';
 export { $Hashtag } from './schemas/$Hashtag';
 export { $HTTPValidationError } from './schemas/$HTTPValidationError';
 export { $ImportConfigJSONL } from './schemas/$ImportConfigJSONL';
@@ -68,8 +99,9 @@ export { $ImportConfigRIS } from './schemas/$ImportConfigRIS';
 export { $ImportConfigTwitter } from './schemas/$ImportConfigTwitter';
 export { $ImportModel } from './schemas/$ImportModel';
 export { $ImportType } from './schemas/$ImportType';
-export { $ItemModel } from './schemas/$ItemModel';
+export { $ItemType } from './schemas/$ItemType';
 export { $ItemWithCount } from './schemas/$ItemWithCount';
+export { $Label } from './schemas/$Label';
 export { $MakeAssignmentsRequestModel } from './schemas/$MakeAssignmentsRequestModel';
 export { $Mention } from './schemas/$Mention';
 export { $PipelineTaskStatusChangedEvent } from './schemas/$PipelineTaskStatusChangedEvent';
@@ -78,8 +110,10 @@ export { $PipelineTaskStatusFailedEvent } from './schemas/$PipelineTaskStatusFai
 export { $PipelineTaskStatusStartedEvent } from './schemas/$PipelineTaskStatusStartedEvent';
 export { $ProjectModel } from './schemas/$ProjectModel';
 export { $ProjectPermissionsModel } from './schemas/$ProjectPermissionsModel';
-export { $ProjectType } from './schemas/$ProjectType';
 export { $ReferencedTweet } from './schemas/$ReferencedTweet';
+export { $ResolutionPayload } from './schemas/$ResolutionPayload';
+export { $ResolutionProposalResponse } from './schemas/$ResolutionProposalResponse';
+export { $SavedResolutionResponse } from './schemas/$SavedResolutionResponse';
 export { $Token } from './schemas/$Token';
 export { $TwitterItemModel } from './schemas/$TwitterItemModel';
 export { $TwitterUserModel } from './schemas/$TwitterUserModel';
diff --git a/src/plugins/api/api-core/models/AcademicItemModel.ts b/src/plugins/api/api-core/models/AcademicItemModel.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b72aecbea54301d6ccd74d45ac0840c0b2cdfef3
--- /dev/null
+++ b/src/plugins/api/api-core/models/AcademicItemModel.ts
@@ -0,0 +1,16 @@
+/* istanbul ignore file */
+/* tslint:disable */
+/* eslint-disable */
+
+import type { ItemType } from './ItemType';
+
+/**
+ * Corresponds to db.schema.items.academic.AcademicItem
+ */
+export type AcademicItemModel = {
+  item_id?: string;
+  project_id?: string;
+  type?: ItemType;
+  text: string;
+};
+
diff --git a/src/plugins/api/api-core/models/AnnotationCollection.ts b/src/plugins/api/api-core/models/AnnotationCollection.ts
new file mode 100644
index 0000000000000000000000000000000000000000..7552a3451a843e77a6af7752f0a345abed0c59af
--- /dev/null
+++ b/src/plugins/api/api-core/models/AnnotationCollection.ts
@@ -0,0 +1,14 @@
+/* istanbul ignore file */
+/* tslint:disable */
+/* eslint-disable */
+
+import type { Label } from './Label';
+import type { UserModel } from './UserModel';
+
+export type AnnotationCollection = {
+  scheme_id: string;
+  labels: Array<Array<Label>>;
+  annotations: Record<string, Array<Array<any>>>;
+  annotators: Array<UserModel>;
+};
+
diff --git a/src/plugins/api/api-core/models/AnnotationCollectionDB.ts b/src/plugins/api/api-core/models/AnnotationCollectionDB.ts
new file mode 100644
index 0000000000000000000000000000000000000000..92bc5bf354841084967296f5f0057997c431033b
--- /dev/null
+++ b/src/plugins/api/api-core/models/AnnotationCollectionDB.ts
@@ -0,0 +1,13 @@
+/* istanbul ignore file */
+/* tslint:disable */
+/* eslint-disable */
+
+import type { Label } from './Label';
+
+export type AnnotationCollectionDB = {
+  scheme_id: string;
+  labels: Array<Array<Label>>;
+  annotations: Record<string, Array<Array<any>>>;
+  annotators: Array<string>;
+};
+
diff --git a/src/plugins/api/api-core/models/AnnotationFilters.ts b/src/plugins/api/api-core/models/AnnotationFilters.ts
new file mode 100644
index 0000000000000000000000000000000000000000..70a3600ae3e1b73c1eb5abb1a1263d28a9e38f48
--- /dev/null
+++ b/src/plugins/api/api-core/models/AnnotationFilters.ts
@@ -0,0 +1,25 @@
+/* istanbul ignore file */
+/* tslint:disable */
+/* eslint-disable */
+
+/**
+ * Filter rules for fetching all annotations that match these conditions
+ * It is up to the user of this function to make sure to provide sensible filters!
+ * All filters are conjunctive (connected with "AND"); if None, they are not included
+ *
+ * There are no "exclude" filters by design. If needed, they should be simulated in the interface.
+ *
+ * :param scheme_id: if not None: annotation has to be part of this annotation scheme
+ * :param scope_id: if not None: annotation has to be part of this assignment scope
+ * :param user_id: if not None: annotation has to be by this user
+ * :param key: if not None: annotation has to be for this AnnotationSchemeLabel.key (or list/tuple of keys)
+ * :param repeat: if not None: annotation has to be primary/secondary/...
+ */
+export type AnnotationFilters = {
+  scheme_id: string;
+  scope_id?: (string | Array<string>);
+  user_id?: (string | Array<string>);
+  key?: (string | Array<string>);
+  repeat?: (number | Array<number>);
+};
+
diff --git a/src/plugins/api/api-core/models/AnnotationItem.ts b/src/plugins/api/api-core/models/AnnotationItem.ts
index 9c1d2d4174e7ad6b5871a08babf8b7fbdc98fd55..4724781c704a42a28149afda9131364552a1c4b6 100644
--- a/src/plugins/api/api-core/models/AnnotationItem.ts
+++ b/src/plugins/api/api-core/models/AnnotationItem.ts
@@ -2,16 +2,17 @@
 /* tslint:disable */
 /* eslint-disable */
 
+import type { AcademicItemModel } from './AcademicItemModel';
 import type { AnnotationSchemeModel } from './AnnotationSchemeModel';
 import type { AssignmentModel } from './AssignmentModel';
 import type { AssignmentScopeModel } from './AssignmentScopeModel';
-import type { ItemModel } from './ItemModel';
+import type { GenericItemModel } from './GenericItemModel';
 import type { TwitterItemModel } from './TwitterItemModel';
 
 export type AnnotationItem = {
   scheme: AnnotationSchemeModel;
   assignment: AssignmentModel;
   scope: AssignmentScopeModel;
-  item: (ItemModel | TwitterItemModel);
+  item: (GenericItemModel | TwitterItemModel | AcademicItemModel);
 };
 
diff --git a/src/plugins/api/api-core/models/AnnotationModel.ts b/src/plugins/api/api-core/models/AnnotationModel.ts
index 8fe69e1f9c0963ef3117c83daa993960df574e7e..fee4145e49ae4b0248819ba4107c0352aa8ba128 100644
--- a/src/plugins/api/api-core/models/AnnotationModel.ts
+++ b/src/plugins/api/api-core/models/AnnotationModel.ts
@@ -38,6 +38,7 @@ export type AnnotationModel = {
   value_int?: number;
   value_float?: number;
   value_str?: string;
+  multi_int?: Array<number>;
   text_offset_start?: number;
   text_offset_stop?: number;
 };
diff --git a/src/plugins/api/api-core/models/AnnotationSchemeLabel.ts b/src/plugins/api/api-core/models/AnnotationSchemeLabel.ts
index 1d4fa3c142fb67fb98f3e57696ce91ed7a472156..ee89fd172d20cf27f68204bd99a0cedd98a91e18 100644
--- a/src/plugins/api/api-core/models/AnnotationSchemeLabel.ts
+++ b/src/plugins/api/api-core/models/AnnotationSchemeLabel.ts
@@ -21,8 +21,8 @@ export namespace AnnotationSchemeLabel {
   export enum kind {
     BOOL = 'bool',
     STR = 'str',
-    INT = 'int',
     FLOAT = 'float',
+    INT = 'int',
     SINGLE = 'single',
     MULTI = 'multi',
     INTEXT = 'intext',
diff --git a/src/plugins/api/api-core/models/AnnotationSchemeLabelChoiceFlat.ts b/src/plugins/api/api-core/models/AnnotationSchemeLabelChoiceFlat.ts
new file mode 100644
index 0000000000000000000000000000000000000000..eb7611f6adeab50054771c7710921e88566bdd3f
--- /dev/null
+++ b/src/plugins/api/api-core/models/AnnotationSchemeLabelChoiceFlat.ts
@@ -0,0 +1,10 @@
+/* istanbul ignore file */
+/* tslint:disable */
+/* eslint-disable */
+
+export type AnnotationSchemeLabelChoiceFlat = {
+  name: string;
+  hint?: string;
+  value: number;
+};
+
diff --git a/src/plugins/api/api-core/models/AnnotationSchemeModelFlat.ts b/src/plugins/api/api-core/models/AnnotationSchemeModelFlat.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6815b3d2e843f4cac4535c64ebc487939ac2d660
--- /dev/null
+++ b/src/plugins/api/api-core/models/AnnotationSchemeModelFlat.ts
@@ -0,0 +1,17 @@
+/* istanbul ignore file */
+/* tslint:disable */
+/* eslint-disable */
+
+import type { FlattenedAnnotationSchemeLabel } from './FlattenedAnnotationSchemeLabel';
+
+/**
+ * Same as AnnotationSchemeModel but with flattened structure.
+ */
+export type AnnotationSchemeModelFlat = {
+  annotation_scheme_id?: string;
+  project_id?: string;
+  name: string;
+  description?: string;
+  labels: Array<FlattenedAnnotationSchemeLabel>;
+};
+
diff --git a/src/plugins/api/api-core/models/BotAnnotationMetaDataBaseModel.ts b/src/plugins/api/api-core/models/BotAnnotationMetaDataBaseModel.ts
new file mode 100644
index 0000000000000000000000000000000000000000..eb812e88962251ce17b608f857270ee129b83745
--- /dev/null
+++ b/src/plugins/api/api-core/models/BotAnnotationMetaDataBaseModel.ts
@@ -0,0 +1,17 @@
+/* istanbul ignore file */
+/* tslint:disable */
+/* eslint-disable */
+
+import type { BotKind } from './BotKind';
+
+export type BotAnnotationMetaDataBaseModel = {
+  bot_annotation_metadata_id?: string;
+  name: string;
+  kind: BotKind;
+  project_id: string;
+  time_created?: string;
+  time_updated?: string;
+  annotation_scope_id?: string;
+  annotation_scheme_id?: string;
+};
+
diff --git a/src/plugins/api/api-core/models/BotAnnotationModel.ts b/src/plugins/api/api-core/models/BotAnnotationModel.ts
new file mode 100644
index 0000000000000000000000000000000000000000..43358aa32303c6f62a084a79cf5308009fc00489
--- /dev/null
+++ b/src/plugins/api/api-core/models/BotAnnotationModel.ts
@@ -0,0 +1,21 @@
+/* istanbul ignore file */
+/* tslint:disable */
+/* eslint-disable */
+
+export type BotAnnotationModel = {
+  bot_annotation_id?: string;
+  bot_annotation_metadata_id?: string;
+  time_created?: string;
+  time_updated?: string;
+  item_id: string;
+  parent?: string;
+  key?: string;
+  repeat?: number;
+  value_bool?: boolean;
+  value_int?: number;
+  value_float?: number;
+  value_str?: string;
+  multi_int?: Array<number>;
+  confidence?: number;
+};
+
diff --git a/src/plugins/api/api-core/models/BotKind.ts b/src/plugins/api/api-core/models/BotKind.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3f8e7d365d754de1adda440259cc67811e4b8a70
--- /dev/null
+++ b/src/plugins/api/api-core/models/BotKind.ts
@@ -0,0 +1,14 @@
+/* istanbul ignore file */
+/* tslint:disable */
+/* eslint-disable */
+
+/**
+ * An enumeration.
+ */
+export enum BotKind {
+  CLASSIFICATION = 'CLASSIFICATION',
+  RULES = 'RULES',
+  TOPICS = 'TOPICS',
+  RESOLVE = 'RESOLVE',
+  SCRIPT = 'SCRIPT',
+}
diff --git a/src/plugins/api/api-core/models/BotMetaResolve.ts b/src/plugins/api/api-core/models/BotMetaResolve.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3adf0910df331d0b1dd8c14372fb89a3626e2c80
--- /dev/null
+++ b/src/plugins/api/api-core/models/BotMetaResolve.ts
@@ -0,0 +1,28 @@
+/* istanbul ignore file */
+/* tslint:disable */
+/* eslint-disable */
+
+import type { AnnotationCollectionDB } from './AnnotationCollectionDB';
+import type { AnnotationFilters } from './AnnotationFilters';
+
+export type BotMetaResolve = {
+  algorithm: BotMetaResolve.algorithm;
+  filters: AnnotationFilters;
+  ignore_hierarchy: boolean;
+  ignore_repeat: boolean;
+  trust?: Record<string, number>;
+  collection: AnnotationCollectionDB;
+};
+
+export namespace BotMetaResolve {
+
+  export enum algorithm {
+    MAJORITY = 'majority',
+    FIRST = 'first',
+    LAST = 'last',
+    TRUST = 'trust',
+  }
+
+
+}
+
diff --git a/src/plugins/api/api-core/models/Event.ts b/src/plugins/api/api-core/models/Event.ts
index 8f736e2d681a9f41a4414a4ae9c640f88a9d211c..7174362dd785f7b53f0bd6784d85f22dcd6ab2c7 100644
--- a/src/plugins/api/api-core/models/Event.ts
+++ b/src/plugins/api/api-core/models/Event.ts
@@ -9,16 +9,16 @@ import type { PipelineTaskStatusStartedEvent } from './PipelineTaskStatusStarted
 
 export type Event = {
   event: Event.event;
-  payload: (PipelineTaskStatusChangedEvent | PipelineTaskStatusCompletedEvent | PipelineTaskStatusStartedEvent | PipelineTaskStatusFailedEvent);
+  payload: (PipelineTaskStatusFailedEvent | PipelineTaskStatusChangedEvent | PipelineTaskStatusCompletedEvent | PipelineTaskStatusStartedEvent);
 };
 
 export namespace Event {
 
   export enum event {
+    PIPELINE_TASK_STATUS_FAILED_EVENT = 'PipelineTaskStatusFailedEvent',
     PIPELINE_TASK_STATUS_CHANGED_EVENT = 'PipelineTaskStatusChangedEvent',
     PIPELINE_TASK_STATUS_COMPLETED_EVENT = 'PipelineTaskStatusCompletedEvent',
     PIPELINE_TASK_STATUS_STARTED_EVENT = 'PipelineTaskStatusStartedEvent',
-    PIPELINE_TASK_STATUS_FAILED_EVENT = 'PipelineTaskStatusFailedEvent',
   }
 
 
diff --git a/src/plugins/api/api-core/models/FlattenedAnnotationSchemeLabel.ts b/src/plugins/api/api-core/models/FlattenedAnnotationSchemeLabel.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4b976993fe895c4ec80cc158ee304def0904a3fe
--- /dev/null
+++ b/src/plugins/api/api-core/models/FlattenedAnnotationSchemeLabel.ts
@@ -0,0 +1,34 @@
+/* istanbul ignore file */
+/* tslint:disable */
+/* eslint-disable */
+
+import type { AnnotationSchemeLabelChoiceFlat } from './AnnotationSchemeLabelChoiceFlat';
+
+export type FlattenedAnnotationSchemeLabel = {
+  name: string;
+  hint?: string;
+  key: string;
+  required: boolean;
+  max_repeat: number;
+  implicit_max_repeat: number;
+  kind: FlattenedAnnotationSchemeLabel.kind;
+  choices?: Array<AnnotationSchemeLabelChoiceFlat>;
+  parent_label?: string;
+  parent_choice?: number;
+};
+
+export namespace FlattenedAnnotationSchemeLabel {
+
+  export enum kind {
+    BOOL = 'bool',
+    STR = 'str',
+    FLOAT = 'float',
+    INT = 'int',
+    SINGLE = 'single',
+    MULTI = 'multi',
+    INTEXT = 'intext',
+  }
+
+
+}
+
diff --git a/src/plugins/api/api-core/models/GenericItemModel.ts b/src/plugins/api/api-core/models/GenericItemModel.ts
new file mode 100644
index 0000000000000000000000000000000000000000..9067d07807d2e73229c5ce12def4e8a252ba112f
--- /dev/null
+++ b/src/plugins/api/api-core/models/GenericItemModel.ts
@@ -0,0 +1,17 @@
+/* istanbul ignore file */
+/* tslint:disable */
+/* eslint-disable */
+
+import type { ItemType } from './ItemType';
+
+/**
+ * Corresponds to db.models.items.generic.GenericItem
+ */
+export type GenericItemModel = {
+  item_id?: string;
+  project_id?: string;
+  type?: ItemType;
+  text: string;
+  meta: any;
+};
+
diff --git a/src/plugins/api/api-core/models/GroupedAnnotations.ts b/src/plugins/api/api-core/models/GroupedAnnotations.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3dbc746758ffdbbdbb5fdb6f777cd87b1d9ae7a8
--- /dev/null
+++ b/src/plugins/api/api-core/models/GroupedAnnotations.ts
@@ -0,0 +1,12 @@
+/* istanbul ignore file */
+/* tslint:disable */
+/* eslint-disable */
+
+import type { AnnotationModel } from './AnnotationModel';
+import type { Label } from './Label';
+
+export type GroupedAnnotations = {
+  path: Array<Label>;
+  annotations: Array<AnnotationModel>;
+};
+
diff --git a/src/plugins/api/api-core/models/GroupedBotAnnotation.ts b/src/plugins/api/api-core/models/GroupedBotAnnotation.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c0f06651a6c31cbdfc60792e0cf26381aa92920c
--- /dev/null
+++ b/src/plugins/api/api-core/models/GroupedBotAnnotation.ts
@@ -0,0 +1,12 @@
+/* istanbul ignore file */
+/* tslint:disable */
+/* eslint-disable */
+
+import type { BotAnnotationModel } from './BotAnnotationModel';
+import type { Label } from './Label';
+
+export type GroupedBotAnnotation = {
+  path: Array<Label>;
+  annotation: BotAnnotationModel;
+};
+
diff --git a/src/plugins/api/api-core/models/ImportConfigJSONL.ts b/src/plugins/api/api-core/models/ImportConfigJSONL.ts
index f8edfbad3b5abc59e17915e047fabd00254f9a50..045cfb0684b82956e091790963980d3fd5985e7b 100644
--- a/src/plugins/api/api-core/models/ImportConfigJSONL.ts
+++ b/src/plugins/api/api-core/models/ImportConfigJSONL.ts
@@ -12,7 +12,7 @@ export namespace ImportConfigJSONL {
   export enum line_type {
     DB_TWITTER_ITEM = 'db-twitter-item',
     TWITTER_API_PAGE = 'twitter-api-page',
-    DB_BASIC_ITEM = 'db-basic-item',
+    DB_GENERIC_ITEM = 'db-generic-item',
     DB_ACADEMIC_ITEM = 'db-academic-item',
     DB_PATENT_ITEM = 'db-patent-item',
   }
diff --git a/src/plugins/api/api-core/models/ItemModel.ts b/src/plugins/api/api-core/models/ItemModel.ts
deleted file mode 100644
index 1ec6cdcec8a75bcce6675692dc03abab90bf4251..0000000000000000000000000000000000000000
--- a/src/plugins/api/api-core/models/ItemModel.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-/* istanbul ignore file */
-/* tslint:disable */
-/* eslint-disable */
-
-/**
- * Corresponds to db.models.items.Item
- */
-export type ItemModel = {
-  item_id?: string;
-  text: string;
-  meta: any;
-};
-
diff --git a/src/plugins/api/api-core/models/ProjectType.ts b/src/plugins/api/api-core/models/ItemType.ts
similarity index 78%
rename from src/plugins/api/api-core/models/ProjectType.ts
rename to src/plugins/api/api-core/models/ItemType.ts
index db3a98bb29a37224f2ae4d517a38f84316a0a790..0679ef80fe6e1503e6cc38fef9a711fed3d77d3f 100644
--- a/src/plugins/api/api-core/models/ProjectType.ts
+++ b/src/plugins/api/api-core/models/ItemType.ts
@@ -5,8 +5,8 @@
 /**
  * An enumeration.
  */
-export enum ProjectType {
-  BASIC = 'basic',
+export enum ItemType {
+  GENERIC = 'generic',
   TWITTER = 'twitter',
   ACADEMIC = 'academic',
   PATENTS = 'patents',
diff --git a/src/plugins/api/api-core/models/Label.ts b/src/plugins/api/api-core/models/Label.ts
new file mode 100644
index 0000000000000000000000000000000000000000..080b681183fc855adbe37e54504d7c5501ba0895
--- /dev/null
+++ b/src/plugins/api/api-core/models/Label.ts
@@ -0,0 +1,15 @@
+/* istanbul ignore file */
+/* tslint:disable */
+/* eslint-disable */
+
+/**
+ * Convenience type (corresponding to internal type in db annotation_label).
+ * For Annotation or BotAnnotation, this is the combination of their respective key, repeat value.
+ *
+ * Mainly used during resolving annotations.
+ */
+export type Label = {
+  key: string;
+  repeat: number;
+};
+
diff --git a/src/plugins/api/api-core/models/ProjectModel.ts b/src/plugins/api/api-core/models/ProjectModel.ts
index aa5d6f358fdad95c982e656cd3fe08dbc6f8a00f..8adc98fe4d10ce53ff1933c366e9302384dae3f4 100644
--- a/src/plugins/api/api-core/models/ProjectModel.ts
+++ b/src/plugins/api/api-core/models/ProjectModel.ts
@@ -2,7 +2,7 @@
 /* tslint:disable */
 /* eslint-disable */
 
-import type { ProjectType } from './ProjectType';
+import type { ItemType } from './ItemType';
 
 /**
  * Project is the basic structural and conceptual place around which all functionality evolves.
@@ -16,6 +16,6 @@ export type ProjectModel = {
   project_id?: string;
   name: string;
   description?: string;
-  type: ('basic' | 'twitter' | 'academic' | 'patents' | ProjectType);
+  type: ('generic' | 'twitter' | 'academic' | 'patents' | ItemType);
 };
 
diff --git a/src/plugins/api/api-core/models/ResolutionPayload.ts b/src/plugins/api/api-core/models/ResolutionPayload.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e4b06642a9a0f4e8516448b04a07d4cba25710dc
--- /dev/null
+++ b/src/plugins/api/api-core/models/ResolutionPayload.ts
@@ -0,0 +1,30 @@
+/* istanbul ignore file */
+/* tslint:disable */
+/* eslint-disable */
+
+import type { AnnotationCollectionDB } from './AnnotationCollectionDB';
+import type { AnnotationFilters } from './AnnotationFilters';
+import type { BotAnnotationModel } from './BotAnnotationModel';
+
+export type ResolutionPayload = {
+  name: string;
+  strategy: ResolutionPayload.strategy;
+  filters: AnnotationFilters;
+  ignore_order: boolean;
+  ignore_hierarchy: boolean;
+  collection: AnnotationCollectionDB;
+  bot_annotations: Array<BotAnnotationModel>;
+};
+
+export namespace ResolutionPayload {
+
+  export enum strategy {
+    MAJORITY = 'majority',
+    FIRST = 'first',
+    LAST = 'last',
+    TRUST = 'trust',
+  }
+
+
+}
+
diff --git a/src/plugins/api/api-core/models/ResolutionProposalResponse.ts b/src/plugins/api/api-core/models/ResolutionProposalResponse.ts
new file mode 100644
index 0000000000000000000000000000000000000000..2ffc415eac297e3ae8fc9e2f4870dd817e3d594b
--- /dev/null
+++ b/src/plugins/api/api-core/models/ResolutionProposalResponse.ts
@@ -0,0 +1,13 @@
+/* istanbul ignore file */
+/* tslint:disable */
+/* eslint-disable */
+
+import type { AnnotationCollection } from './AnnotationCollection';
+import type { FlattenedAnnotationSchemeLabel } from './FlattenedAnnotationSchemeLabel';
+
+export type ResolutionProposalResponse = {
+  collection: AnnotationCollection;
+  proposal: Record<string, Array<Array<any>>>;
+  scheme_flat: Array<FlattenedAnnotationSchemeLabel>;
+};
+
diff --git a/src/plugins/api/api-core/models/SavedResolutionResponse.ts b/src/plugins/api/api-core/models/SavedResolutionResponse.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3c68457e2dfe973a01b98f927ecfdb74f12c222d
--- /dev/null
+++ b/src/plugins/api/api-core/models/SavedResolutionResponse.ts
@@ -0,0 +1,12 @@
+/* istanbul ignore file */
+/* tslint:disable */
+/* eslint-disable */
+
+import type { BotMetaResolve } from './BotMetaResolve';
+
+export type SavedResolutionResponse = {
+  name: string;
+  meta: BotMetaResolve;
+  saved: Record<string, Array<Array<any>>>;
+};
+
diff --git a/src/plugins/api/api-core/models/TwitterItemModel.ts b/src/plugins/api/api-core/models/TwitterItemModel.ts
index 80fa24ea8883927488200c73845f349d4a7ff939..17e1f8f3cfede8bfd8aadfe118613ed6ea195766 100644
--- a/src/plugins/api/api-core/models/TwitterItemModel.ts
+++ b/src/plugins/api/api-core/models/TwitterItemModel.ts
@@ -5,6 +5,7 @@
 import type { Cashtag } from './Cashtag';
 import type { ContextAnnotation } from './ContextAnnotation';
 import type { Hashtag } from './Hashtag';
+import type { ItemType } from './ItemType';
 import type { Mention } from './Mention';
 import type { ReferencedTweet } from './ReferencedTweet';
 import type { TwitterUserModel } from './TwitterUserModel';
@@ -18,9 +19,11 @@ import type { URL } from './URL';
  */
 export type TwitterItemModel = {
   item_id?: string;
+  project_id?: string;
+  type?: ItemType;
+  text: string;
   twitter_id?: string;
   twitter_author_id?: string;
-  status: string;
   created_at: string;
   language?: string;
   conversation_id?: string;
diff --git a/src/plugins/api/api-core/schemas/$AcademicItemModel.ts b/src/plugins/api/api-core/schemas/$AcademicItemModel.ts
new file mode 100644
index 0000000000000000000000000000000000000000..fa4102b7feee744e1fd47da250b77d3ac79e6584
--- /dev/null
+++ b/src/plugins/api/api-core/schemas/$AcademicItemModel.ts
@@ -0,0 +1,33 @@
+/* istanbul ignore file */
+/* tslint:disable */
+/* eslint-disable */
+export const $AcademicItemModel = {
+  description: `Corresponds to db.schema.items.academic.AcademicItem`,
+  properties: {
+    item_id: {
+      type: 'any-of',
+      contains: [{
+        type: 'string',
+      }, {
+        type: 'string',
+        format: 'uuid',
+      }],
+    },
+    project_id: {
+      type: 'any-of',
+      contains: [{
+        type: 'string',
+      }, {
+        type: 'string',
+        format: 'uuid',
+      }],
+    },
+    type: {
+      type: 'ItemType',
+    },
+    text: {
+      type: 'string',
+      isRequired: true,
+    },
+  },
+} as const;
diff --git a/src/plugins/api/api-core/schemas/$AnnotationCollection.ts b/src/plugins/api/api-core/schemas/$AnnotationCollection.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a155b92731cc669e7aa629ede1fd7f9bc08ae04f
--- /dev/null
+++ b/src/plugins/api/api-core/schemas/$AnnotationCollection.ts
@@ -0,0 +1,42 @@
+/* istanbul ignore file */
+/* tslint:disable */
+/* eslint-disable */
+export const $AnnotationCollection = {
+  properties: {
+    scheme_id: {
+      type: 'string',
+      isRequired: true,
+    },
+    labels: {
+      type: 'array',
+      contains: {
+        type: 'array',
+        contains: {
+          type: 'Label',
+        },
+      },
+      isRequired: true,
+    },
+    annotations: {
+      type: 'dictionary',
+      contains: {
+        type: 'array',
+        contains: {
+          type: 'array',
+          contains: {
+            properties: {
+            },
+          },
+        },
+      },
+      isRequired: true,
+    },
+    annotators: {
+      type: 'array',
+      contains: {
+        type: 'UserModel',
+      },
+      isRequired: true,
+    },
+  },
+} as const;
diff --git a/src/plugins/api/api-core/schemas/$AnnotationCollectionDB.ts b/src/plugins/api/api-core/schemas/$AnnotationCollectionDB.ts
new file mode 100644
index 0000000000000000000000000000000000000000..973be1853db0587874672b5ca05b3800ff62f72a
--- /dev/null
+++ b/src/plugins/api/api-core/schemas/$AnnotationCollectionDB.ts
@@ -0,0 +1,42 @@
+/* istanbul ignore file */
+/* tslint:disable */
+/* eslint-disable */
+export const $AnnotationCollectionDB = {
+  properties: {
+    scheme_id: {
+      type: 'string',
+      isRequired: true,
+    },
+    labels: {
+      type: 'array',
+      contains: {
+        type: 'array',
+        contains: {
+          type: 'Label',
+        },
+      },
+      isRequired: true,
+    },
+    annotations: {
+      type: 'dictionary',
+      contains: {
+        type: 'array',
+        contains: {
+          type: 'array',
+          contains: {
+            properties: {
+            },
+          },
+        },
+      },
+      isRequired: true,
+    },
+    annotators: {
+      type: 'array',
+      contains: {
+        type: 'string',
+      },
+      isRequired: true,
+    },
+  },
+} as const;
diff --git a/src/plugins/api/api-core/schemas/$AnnotationFilters.ts b/src/plugins/api/api-core/schemas/$AnnotationFilters.ts
new file mode 100644
index 0000000000000000000000000000000000000000..35ac5cf06d12f77814678736f586731a6fdd2550
--- /dev/null
+++ b/src/plugins/api/api-core/schemas/$AnnotationFilters.ts
@@ -0,0 +1,66 @@
+/* istanbul ignore file */
+/* tslint:disable */
+/* eslint-disable */
+export const $AnnotationFilters = {
+  description: `Filter rules for fetching all annotations that match these conditions
+  It is up to the user of this function to make sure to provide sensible filters!
+  All filters are conjunctive (connected with "AND"); if None, they are not included
+
+  There are no "exclude" filters by design. If needed, they should be simulated in the interface.
+
+  :param scheme_id: if not None: annotation has to be part of this annotation scheme
+  :param scope_id: if not None: annotation has to be part of this assignment scope
+  :param user_id: if not None: annotation has to be by this user
+  :param key: if not None: annotation has to be for this AnnotationSchemeLabel.key (or list/tuple of keys)
+  :param repeat: if not None: annotation has to be primary/secondary/...`,
+  properties: {
+    scheme_id: {
+      type: 'string',
+      isRequired: true,
+    },
+    scope_id: {
+      type: 'any-of',
+      contains: [{
+        type: 'string',
+      }, {
+        type: 'array',
+        contains: {
+          type: 'string',
+        },
+      }],
+    },
+    user_id: {
+      type: 'any-of',
+      contains: [{
+        type: 'string',
+      }, {
+        type: 'array',
+        contains: {
+          type: 'string',
+        },
+      }],
+    },
+    key: {
+      type: 'any-of',
+      contains: [{
+        type: 'string',
+      }, {
+        type: 'array',
+        contains: {
+          type: 'string',
+        },
+      }],
+    },
+    repeat: {
+      type: 'any-of',
+      contains: [{
+        type: 'number',
+      }, {
+        type: 'array',
+        contains: {
+          type: 'number',
+        },
+      }],
+    },
+  },
+} as const;
diff --git a/src/plugins/api/api-core/schemas/$AnnotationItem.ts b/src/plugins/api/api-core/schemas/$AnnotationItem.ts
index 8171ae732c98f3c79e6095b07472c3c5d39d06d5..952e886f50fe7cf637f7f313b82a24213cf072d8 100644
--- a/src/plugins/api/api-core/schemas/$AnnotationItem.ts
+++ b/src/plugins/api/api-core/schemas/$AnnotationItem.ts
@@ -18,9 +18,11 @@ export const $AnnotationItem = {
     item: {
       type: 'any-of',
       contains: [{
-        type: 'ItemModel',
+        type: 'GenericItemModel',
       }, {
         type: 'TwitterItemModel',
+      }, {
+        type: 'AcademicItemModel',
       }],
       isRequired: true,
     },
diff --git a/src/plugins/api/api-core/schemas/$AnnotationModel.ts b/src/plugins/api/api-core/schemas/$AnnotationModel.ts
index 8a5cc3992337fcc9ca8ab951498ceaf235f280a6..97e55a3242a1a3b3cc2e0b3b0ad893fa5acd9842 100644
--- a/src/plugins/api/api-core/schemas/$AnnotationModel.ts
+++ b/src/plugins/api/api-core/schemas/$AnnotationModel.ts
@@ -107,6 +107,12 @@ export const $AnnotationModel = {
     value_str: {
       type: 'string',
     },
+    multi_int: {
+      type: 'array',
+      contains: {
+        type: 'number',
+      },
+    },
     text_offset_start: {
       type: 'number',
     },
diff --git a/src/plugins/api/api-core/schemas/$AnnotationSchemeLabelChoiceFlat.ts b/src/plugins/api/api-core/schemas/$AnnotationSchemeLabelChoiceFlat.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ee50861b66c8fbcff0f40063e0266c959ca29181
--- /dev/null
+++ b/src/plugins/api/api-core/schemas/$AnnotationSchemeLabelChoiceFlat.ts
@@ -0,0 +1,18 @@
+/* istanbul ignore file */
+/* tslint:disable */
+/* eslint-disable */
+export const $AnnotationSchemeLabelChoiceFlat = {
+  properties: {
+    name: {
+      type: 'string',
+      isRequired: true,
+    },
+    hint: {
+      type: 'string',
+    },
+    value: {
+      type: 'number',
+      isRequired: true,
+    },
+  },
+} as const;
diff --git a/src/plugins/api/api-core/schemas/$AnnotationSchemeModelFlat.ts b/src/plugins/api/api-core/schemas/$AnnotationSchemeModelFlat.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4a98b0961bdbb9803a568bb1bbd9fabca966ed4b
--- /dev/null
+++ b/src/plugins/api/api-core/schemas/$AnnotationSchemeModelFlat.ts
@@ -0,0 +1,40 @@
+/* istanbul ignore file */
+/* tslint:disable */
+/* eslint-disable */
+export const $AnnotationSchemeModelFlat = {
+  description: `Same as AnnotationSchemeModel but with flattened structure.`,
+  properties: {
+    annotation_scheme_id: {
+      type: 'any-of',
+      contains: [{
+        type: 'string',
+      }, {
+        type: 'string',
+        format: 'uuid',
+      }],
+    },
+    project_id: {
+      type: 'any-of',
+      contains: [{
+        type: 'string',
+      }, {
+        type: 'string',
+        format: 'uuid',
+      }],
+    },
+    name: {
+      type: 'string',
+      isRequired: true,
+    },
+    description: {
+      type: 'string',
+    },
+    labels: {
+      type: 'array',
+      contains: {
+        type: 'FlattenedAnnotationSchemeLabel',
+      },
+      isRequired: true,
+    },
+  },
+} as const;
diff --git a/src/plugins/api/api-core/schemas/$BotAnnotationMetaDataBaseModel.ts b/src/plugins/api/api-core/schemas/$BotAnnotationMetaDataBaseModel.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f1aab60ea639e321162970d232d4c417a1cd0779
--- /dev/null
+++ b/src/plugins/api/api-core/schemas/$BotAnnotationMetaDataBaseModel.ts
@@ -0,0 +1,60 @@
+/* istanbul ignore file */
+/* tslint:disable */
+/* eslint-disable */
+export const $BotAnnotationMetaDataBaseModel = {
+  properties: {
+    bot_annotation_metadata_id: {
+      type: 'any-of',
+      contains: [{
+        type: 'string',
+      }, {
+        type: 'string',
+        format: 'uuid',
+      }],
+    },
+    name: {
+      type: 'string',
+      isRequired: true,
+    },
+    kind: {
+      type: 'BotKind',
+      isRequired: true,
+    },
+    project_id: {
+      type: 'any-of',
+      contains: [{
+        type: 'string',
+      }, {
+        type: 'string',
+        format: 'uuid',
+      }],
+      isRequired: true,
+    },
+    time_created: {
+      type: 'string',
+      format: 'date-time',
+    },
+    time_updated: {
+      type: 'string',
+      format: 'date-time',
+    },
+    annotation_scope_id: {
+      type: 'any-of',
+      contains: [{
+        type: 'string',
+      }, {
+        type: 'string',
+        format: 'uuid',
+      }],
+    },
+    annotation_scheme_id: {
+      type: 'any-of',
+      contains: [{
+        type: 'string',
+      }, {
+        type: 'string',
+        format: 'uuid',
+      }],
+    },
+  },
+} as const;
diff --git a/src/plugins/api/api-core/schemas/$BotAnnotationModel.ts b/src/plugins/api/api-core/schemas/$BotAnnotationModel.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b727ba86922be6afe98582c62837cc90a87c69a1
--- /dev/null
+++ b/src/plugins/api/api-core/schemas/$BotAnnotationModel.ts
@@ -0,0 +1,79 @@
+/* istanbul ignore file */
+/* tslint:disable */
+/* eslint-disable */
+export const $BotAnnotationModel = {
+  properties: {
+    bot_annotation_id: {
+      type: 'any-of',
+      contains: [{
+        type: 'string',
+      }, {
+        type: 'string',
+        format: 'uuid',
+      }],
+    },
+    bot_annotation_metadata_id: {
+      type: 'any-of',
+      contains: [{
+        type: 'string',
+      }, {
+        type: 'string',
+        format: 'uuid',
+      }],
+    },
+    time_created: {
+      type: 'string',
+      format: 'date-time',
+    },
+    time_updated: {
+      type: 'string',
+      format: 'date-time',
+    },
+    item_id: {
+      type: 'any-of',
+      contains: [{
+        type: 'string',
+      }, {
+        type: 'string',
+        format: 'uuid',
+      }],
+      isRequired: true,
+    },
+    parent: {
+      type: 'any-of',
+      contains: [{
+        type: 'string',
+      }, {
+        type: 'string',
+        format: 'uuid',
+      }],
+    },
+    key: {
+      type: 'string',
+    },
+    repeat: {
+      type: 'number',
+    },
+    value_bool: {
+      type: 'boolean',
+    },
+    value_int: {
+      type: 'number',
+    },
+    value_float: {
+      type: 'number',
+    },
+    value_str: {
+      type: 'string',
+    },
+    multi_int: {
+      type: 'array',
+      contains: {
+        type: 'number',
+      },
+    },
+    confidence: {
+      type: 'number',
+    },
+  },
+} as const;
diff --git a/src/plugins/api/api-core/schemas/$ProjectType.ts b/src/plugins/api/api-core/schemas/$BotKind.ts
similarity index 76%
rename from src/plugins/api/api-core/schemas/$ProjectType.ts
rename to src/plugins/api/api-core/schemas/$BotKind.ts
index 361b06372a54b214f97c4373847d43e75f37d3df..7fa62d4baf51a5418198da907550bc2bf3661970 100644
--- a/src/plugins/api/api-core/schemas/$ProjectType.ts
+++ b/src/plugins/api/api-core/schemas/$BotKind.ts
@@ -1,6 +1,6 @@
 /* istanbul ignore file */
 /* tslint:disable */
 /* eslint-disable */
-export const $ProjectType = {
+export const $BotKind = {
   type: 'Enum',
 } as const;
diff --git a/src/plugins/api/api-core/schemas/$BotMetaResolve.ts b/src/plugins/api/api-core/schemas/$BotMetaResolve.ts
new file mode 100644
index 0000000000000000000000000000000000000000..445f5d68bfe598cd17ac813062fd13d2474920f4
--- /dev/null
+++ b/src/plugins/api/api-core/schemas/$BotMetaResolve.ts
@@ -0,0 +1,33 @@
+/* istanbul ignore file */
+/* tslint:disable */
+/* eslint-disable */
+export const $BotMetaResolve = {
+  properties: {
+    algorithm: {
+      type: 'Enum',
+      isRequired: true,
+    },
+    filters: {
+      type: 'AnnotationFilters',
+      isRequired: true,
+    },
+    ignore_hierarchy: {
+      type: 'boolean',
+      isRequired: true,
+    },
+    ignore_repeat: {
+      type: 'boolean',
+      isRequired: true,
+    },
+    trust: {
+      type: 'dictionary',
+      contains: {
+        type: 'number',
+      },
+    },
+    collection: {
+      type: 'AnnotationCollectionDB',
+      isRequired: true,
+    },
+  },
+} as const;
diff --git a/src/plugins/api/api-core/schemas/$Event.ts b/src/plugins/api/api-core/schemas/$Event.ts
index 511707a71cd12ad8231882ec382796b1ad46cfbf..66494354076daef1a12887b0e212f530670bf429 100644
--- a/src/plugins/api/api-core/schemas/$Event.ts
+++ b/src/plugins/api/api-core/schemas/$Event.ts
@@ -10,13 +10,13 @@ export const $Event = {
     payload: {
       type: 'any-of',
       contains: [{
+        type: 'PipelineTaskStatusFailedEvent',
+      }, {
         type: 'PipelineTaskStatusChangedEvent',
       }, {
         type: 'PipelineTaskStatusCompletedEvent',
       }, {
         type: 'PipelineTaskStatusStartedEvent',
-      }, {
-        type: 'PipelineTaskStatusFailedEvent',
       }],
       isRequired: true,
     },
diff --git a/src/plugins/api/api-core/schemas/$FlattenedAnnotationSchemeLabel.ts b/src/plugins/api/api-core/schemas/$FlattenedAnnotationSchemeLabel.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a4a3b33a78c73867f0c6752c9093f457ba6ecd81
--- /dev/null
+++ b/src/plugins/api/api-core/schemas/$FlattenedAnnotationSchemeLabel.ts
@@ -0,0 +1,46 @@
+/* istanbul ignore file */
+/* tslint:disable */
+/* eslint-disable */
+export const $FlattenedAnnotationSchemeLabel = {
+  properties: {
+    name: {
+      type: 'string',
+      isRequired: true,
+    },
+    hint: {
+      type: 'string',
+    },
+    key: {
+      type: 'string',
+      isRequired: true,
+    },
+    required: {
+      type: 'boolean',
+      isRequired: true,
+    },
+    max_repeat: {
+      type: 'number',
+      isRequired: true,
+    },
+    implicit_max_repeat: {
+      type: 'number',
+      isRequired: true,
+    },
+    kind: {
+      type: 'Enum',
+      isRequired: true,
+    },
+    choices: {
+      type: 'array',
+      contains: {
+        type: 'AnnotationSchemeLabelChoiceFlat',
+      },
+    },
+    parent_label: {
+      type: 'string',
+    },
+    parent_choice: {
+      type: 'number',
+    },
+  },
+} as const;
diff --git a/src/plugins/api/api-core/schemas/$ItemModel.ts b/src/plugins/api/api-core/schemas/$GenericItemModel.ts
similarity index 56%
rename from src/plugins/api/api-core/schemas/$ItemModel.ts
rename to src/plugins/api/api-core/schemas/$GenericItemModel.ts
index d4dc26d3608da77ab1dd955e27eb0a5474679a42..ed5549973d21b34ee8e21efd44dd7dd878896a37 100644
--- a/src/plugins/api/api-core/schemas/$ItemModel.ts
+++ b/src/plugins/api/api-core/schemas/$GenericItemModel.ts
@@ -1,8 +1,8 @@
 /* istanbul ignore file */
 /* tslint:disable */
 /* eslint-disable */
-export const $ItemModel = {
-  description: `Corresponds to db.models.items.Item`,
+export const $GenericItemModel = {
+  description: `Corresponds to db.models.items.generic.GenericItem`,
   properties: {
     item_id: {
       type: 'any-of',
@@ -13,6 +13,18 @@ export const $ItemModel = {
         format: 'uuid',
       }],
     },
+    project_id: {
+      type: 'any-of',
+      contains: [{
+        type: 'string',
+      }, {
+        type: 'string',
+        format: 'uuid',
+      }],
+    },
+    type: {
+      type: 'ItemType',
+    },
     text: {
       type: 'string',
       isRequired: true,
diff --git a/src/plugins/api/api-core/schemas/$GroupedAnnotations.ts b/src/plugins/api/api-core/schemas/$GroupedAnnotations.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6ac88a3c25edc26f9303333f6d137d970811942c
--- /dev/null
+++ b/src/plugins/api/api-core/schemas/$GroupedAnnotations.ts
@@ -0,0 +1,21 @@
+/* istanbul ignore file */
+/* tslint:disable */
+/* eslint-disable */
+export const $GroupedAnnotations = {
+  properties: {
+    path: {
+      type: 'array',
+      contains: {
+        type: 'Label',
+      },
+      isRequired: true,
+    },
+    annotations: {
+      type: 'array',
+      contains: {
+        type: 'AnnotationModel',
+      },
+      isRequired: true,
+    },
+  },
+} as const;
diff --git a/src/plugins/api/api-core/schemas/$GroupedBotAnnotation.ts b/src/plugins/api/api-core/schemas/$GroupedBotAnnotation.ts
new file mode 100644
index 0000000000000000000000000000000000000000..baab78eb68e5c2ac0bc1a8bdc10a8329ea131088
--- /dev/null
+++ b/src/plugins/api/api-core/schemas/$GroupedBotAnnotation.ts
@@ -0,0 +1,18 @@
+/* istanbul ignore file */
+/* tslint:disable */
+/* eslint-disable */
+export const $GroupedBotAnnotation = {
+  properties: {
+    path: {
+      type: 'array',
+      contains: {
+        type: 'Label',
+      },
+      isRequired: true,
+    },
+    annotation: {
+      type: 'BotAnnotationModel',
+      isRequired: true,
+    },
+  },
+} as const;
diff --git a/src/plugins/api/api-core/schemas/$ItemType.ts b/src/plugins/api/api-core/schemas/$ItemType.ts
new file mode 100644
index 0000000000000000000000000000000000000000..91b58a8378b7aed40561ee68473cc6c679028ebc
--- /dev/null
+++ b/src/plugins/api/api-core/schemas/$ItemType.ts
@@ -0,0 +1,6 @@
+/* istanbul ignore file */
+/* tslint:disable */
+/* eslint-disable */
+export const $ItemType = {
+  type: 'Enum',
+} as const;
diff --git a/src/plugins/api/api-core/schemas/$Label.ts b/src/plugins/api/api-core/schemas/$Label.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a57be1f3601afecc5ad2522cc3e2d36176c795a7
--- /dev/null
+++ b/src/plugins/api/api-core/schemas/$Label.ts
@@ -0,0 +1,19 @@
+/* istanbul ignore file */
+/* tslint:disable */
+/* eslint-disable */
+export const $Label = {
+  description: `Convenience type (corresponding to internal type in db annotation_label).
+  For Annotation or BotAnnotation, this is the combination of their respective key, repeat value.
+
+  Mainly used during resolving annotations.`,
+  properties: {
+    key: {
+      type: 'string',
+      isRequired: true,
+    },
+    repeat: {
+      type: 'number',
+      isRequired: true,
+    },
+  },
+} as const;
diff --git a/src/plugins/api/api-core/schemas/$ProjectModel.ts b/src/plugins/api/api-core/schemas/$ProjectModel.ts
index cb1d201d4159fca498b3f2e486aea5ca91589b45..ac92efa150a78f1a14e0c934a8755740a4c454fb 100644
--- a/src/plugins/api/api-core/schemas/$ProjectModel.ts
+++ b/src/plugins/api/api-core/schemas/$ProjectModel.ts
@@ -30,7 +30,7 @@ export const $ProjectModel = {
       contains: [{
         type: 'Enum',
       }, {
-        type: 'ProjectType',
+        type: 'ItemType',
       }],
       isRequired: true,
     },
diff --git a/src/plugins/api/api-core/schemas/$ResolutionPayload.ts b/src/plugins/api/api-core/schemas/$ResolutionPayload.ts
new file mode 100644
index 0000000000000000000000000000000000000000..164a5a52f8c56441c8f4eec7db879564bf439eae
--- /dev/null
+++ b/src/plugins/api/api-core/schemas/$ResolutionPayload.ts
@@ -0,0 +1,38 @@
+/* istanbul ignore file */
+/* tslint:disable */
+/* eslint-disable */
+export const $ResolutionPayload = {
+  properties: {
+    name: {
+      type: 'string',
+      isRequired: true,
+    },
+    strategy: {
+      type: 'Enum',
+      isRequired: true,
+    },
+    filters: {
+      type: 'AnnotationFilters',
+      isRequired: true,
+    },
+    ignore_order: {
+      type: 'boolean',
+      isRequired: true,
+    },
+    ignore_hierarchy: {
+      type: 'boolean',
+      isRequired: true,
+    },
+    collection: {
+      type: 'AnnotationCollectionDB',
+      isRequired: true,
+    },
+    bot_annotations: {
+      type: 'array',
+      contains: {
+        type: 'BotAnnotationModel',
+      },
+      isRequired: true,
+    },
+  },
+} as const;
diff --git a/src/plugins/api/api-core/schemas/$ResolutionProposalResponse.ts b/src/plugins/api/api-core/schemas/$ResolutionProposalResponse.ts
new file mode 100644
index 0000000000000000000000000000000000000000..98cb12ed663ef504576dc506435c4adcd87365a4
--- /dev/null
+++ b/src/plugins/api/api-core/schemas/$ResolutionProposalResponse.ts
@@ -0,0 +1,32 @@
+/* istanbul ignore file */
+/* tslint:disable */
+/* eslint-disable */
+export const $ResolutionProposalResponse = {
+  properties: {
+    collection: {
+      type: 'AnnotationCollection',
+      isRequired: true,
+    },
+    proposal: {
+      type: 'dictionary',
+      contains: {
+        type: 'array',
+        contains: {
+          type: 'array',
+          contains: {
+            properties: {
+            },
+          },
+        },
+      },
+      isRequired: true,
+    },
+    scheme_flat: {
+      type: 'array',
+      contains: {
+        type: 'FlattenedAnnotationSchemeLabel',
+      },
+      isRequired: true,
+    },
+  },
+} as const;
diff --git a/src/plugins/api/api-core/schemas/$SavedResolutionResponse.ts b/src/plugins/api/api-core/schemas/$SavedResolutionResponse.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8ad91ad4399edad611a773b8d2c438de21bc5c5c
--- /dev/null
+++ b/src/plugins/api/api-core/schemas/$SavedResolutionResponse.ts
@@ -0,0 +1,29 @@
+/* istanbul ignore file */
+/* tslint:disable */
+/* eslint-disable */
+export const $SavedResolutionResponse = {
+  properties: {
+    name: {
+      type: 'string',
+      isRequired: true,
+    },
+    meta: {
+      type: 'BotMetaResolve',
+      isRequired: true,
+    },
+    saved: {
+      type: 'dictionary',
+      contains: {
+        type: 'array',
+        contains: {
+          type: 'array',
+          contains: {
+            properties: {
+            },
+          },
+        },
+      },
+      isRequired: true,
+    },
+  },
+} as const;
diff --git a/src/plugins/api/api-core/schemas/$TwitterItemModel.ts b/src/plugins/api/api-core/schemas/$TwitterItemModel.ts
index 8170ad18220421ca3dd515027330873af6551a03..b3aa32329ab843d5ff0e856ee324c3e4a73ca964 100644
--- a/src/plugins/api/api-core/schemas/$TwitterItemModel.ts
+++ b/src/plugins/api/api-core/schemas/$TwitterItemModel.ts
@@ -16,15 +16,27 @@ export const $TwitterItemModel = {
         format: 'uuid',
       }],
     },
-    twitter_id: {
+    project_id: {
+      type: 'any-of',
+      contains: [{
+        type: 'string',
+      }, {
+        type: 'string',
+        format: 'uuid',
+      }],
+    },
+    type: {
+      type: 'ItemType',
+    },
+    text: {
       type: 'string',
+      isRequired: true,
     },
-    twitter_author_id: {
+    twitter_id: {
       type: 'string',
     },
-    status: {
+    twitter_author_id: {
       type: 'string',
-      isRequired: true,
     },
     created_at: {
       type: 'string',
diff --git a/src/plugins/api/api-core/services/AnnotationsService.ts b/src/plugins/api/api-core/services/AnnotationsService.ts
index 0842e5d26e4ff751d4870e6406c59550027f0765..b4a9b6a50714813b7da11870ef933c3f6fbdf4e3 100644
--- a/src/plugins/api/api-core/services/AnnotationsService.ts
+++ b/src/plugins/api/api-core/services/AnnotationsService.ts
@@ -4,12 +4,19 @@
 import type { AnnotatedItem } from '../models/AnnotatedItem';
 import type { AnnotationItem } from '../models/AnnotationItem';
 import type { AnnotationSchemeModel } from '../models/AnnotationSchemeModel';
+import type { AnnotationSchemeModelFlat } from '../models/AnnotationSchemeModelFlat';
 import type { AssignmentCounts } from '../models/AssignmentCounts';
 import type { AssignmentModel } from '../models/AssignmentModel';
 import type { AssignmentScopeModel } from '../models/AssignmentScopeModel';
 import type { AssignmentStatus } from '../models/AssignmentStatus';
+import type { BotAnnotationMetaDataBaseModel } from '../models/BotAnnotationMetaDataBaseModel';
+import type { BotAnnotationModel } from '../models/BotAnnotationModel';
 import type { ItemWithCount } from '../models/ItemWithCount';
 import type { MakeAssignmentsRequestModel } from '../models/MakeAssignmentsRequestModel';
+import type { ResolutionPayload } from '../models/ResolutionPayload';
+import type { ResolutionProposalResponse } from '../models/ResolutionProposalResponse';
+import type { SavedResolutionResponse } from '../models/SavedResolutionResponse';
+import type { UserModel } from '../models/UserModel';
 import type { UserProjectAssignmentScope } from '../models/UserProjectAssignmentScope';
 
 import type { CancelablePromise } from '@/plugins/api/core/CancelablePromise';
@@ -26,21 +33,33 @@ export class AnnotationsService {
    * This endpoint returns the detailed definition of an annotation scheme.
    *
    * :param annotation_scheme_id: database id of the annotation scheme.
+   * :param flat: True to get the flattened scheme
+   * :param permissions:
    * :return: a single annotation scheme
-   * @returns AnnotationSchemeModel Successful Response
+   * @returns any Successful Response
    * @throws ApiError
    */
   public getSchemeDefinitionApiAnnotationsSchemesDefinitionAnnotationSchemeIdGet({
     annotationSchemeId,
+    xProjectId,
+    flat = false,
   }: {
     annotationSchemeId: string,
-  }, options?: Partial<ApiRequestOptions>): CancelablePromise<AnnotationSchemeModel> {
+    xProjectId: string,
+    flat?: boolean,
+  }, options?: Partial<ApiRequestOptions>): CancelablePromise<(AnnotationSchemeModelFlat | AnnotationSchemeModel)> {
     return this.httpRequest.request({
       method: 'GET',
       url: '/api/annotations/schemes/definition/{annotation_scheme_id}',
       path: {
         'annotation_scheme_id': annotationSchemeId,
       },
+      headers: {
+        'x-project-id': xProjectId,
+      },
+      query: {
+        'flat': flat,
+      },
       errors: {
         422: `Validation Error`,
       },
@@ -108,14 +127,17 @@ export class AnnotationsService {
    * This endpoint returns the detailed definitions of all annotation schemes associated with a project.
    *
    * :param project_id: database id of the project
+   * :param permissions:
    * :return: list of annotation schemes
    * @returns AnnotationSchemeModel Successful Response
    * @throws ApiError
    */
   public getSchemeDefinitionsForProjectApiAnnotationsSchemesListProjectIdGet({
     projectId,
+    xProjectId,
   }: {
     projectId: string,
+    xProjectId: string,
   }, options?: Partial<ApiRequestOptions>): CancelablePromise<Array<AnnotationSchemeModel>> {
     return this.httpRequest.request({
       method: 'GET',
@@ -123,6 +145,9 @@ export class AnnotationsService {
       path: {
         'project_id': projectId,
       },
+      headers: {
+        'x-project-id': xProjectId,
+      },
       errors: {
         422: `Validation Error`,
       },
@@ -540,4 +565,266 @@ export class AnnotationsService {
     });
   }
 
+  /**
+   * Get Assignment Scopes For Scheme
+   * @returns AssignmentScopeModel Successful Response
+   * @throws ApiError
+   */
+  public getAssignmentScopesForSchemeApiAnnotationsConfigScopesSchemeIdGet({
+    schemeId,
+    xProjectId,
+  }: {
+    schemeId: string,
+    xProjectId: string,
+  }, options?: Partial<ApiRequestOptions>): CancelablePromise<Array<AssignmentScopeModel>> {
+    return this.httpRequest.request({
+      method: 'GET',
+      url: '/api/annotations/config/scopes/{scheme_id}',
+      path: {
+        'scheme_id': schemeId,
+      },
+      headers: {
+        'x-project-id': xProjectId,
+      },
+      errors: {
+        422: `Validation Error`,
+      },
+      ...options,
+    });
+  }
+
+  /**
+   * Get Annotators For Scheme
+   * @returns UserModel Successful Response
+   * @throws ApiError
+   */
+  public getAnnotatorsForSchemeApiAnnotationsConfigAnnotatorsSchemeIdGet({
+    schemeId,
+    xProjectId,
+  }: {
+    schemeId: string,
+    xProjectId: string,
+  }, options?: Partial<ApiRequestOptions>): CancelablePromise<Array<UserModel>> {
+    return this.httpRequest.request({
+      method: 'GET',
+      url: '/api/annotations/config/annotators/{scheme_id}',
+      path: {
+        'scheme_id': schemeId,
+      },
+      headers: {
+        'x-project-id': xProjectId,
+      },
+      errors: {
+        422: `Validation Error`,
+      },
+      ...options,
+    });
+  }
+
+  /**
+   * Get Resolved Annotations
+   * Get all annotations that match the filters (e.g. all annotations made by users in scope with :scope_id).
+   * Annotations are returned in a 3D matrix:
+   * rows (dict entries): items (key: item_id)
+   * columns (list index of dict entry): Label (key in scheme + repeat); index map in matrix.keys
+   * cells: list of annotations by each user for item/Label combination
+   *
+   * :param strategy
+   * :param scheme_id:
+   * :param scope_id:
+   * :param user_id:
+   * :param key:
+   * :param repeat:
+   * :param permissions:
+   * :param ignore_order:
+   * :param ignore_hierarchy:
+   * :return:
+   * @returns ResolutionProposalResponse Successful Response
+   * @throws ApiError
+   */
+  public getResolvedAnnotationsApiAnnotationsConfigResolveGet({
+    strategy,
+    schemeId,
+    xProjectId,
+    scopeId,
+    userId,
+    key,
+    repeat,
+    ignoreOrder = false,
+    ignoreHierarchy = false,
+  }: {
+    strategy: 'majority' | 'first' | 'last' | 'trust',
+    schemeId: string,
+    xProjectId: string,
+    scopeId?: Array<string>,
+    userId?: Array<string>,
+    key?: Array<string>,
+    repeat?: Array<number>,
+    ignoreOrder?: boolean,
+    ignoreHierarchy?: boolean,
+  }, options?: Partial<ApiRequestOptions>): CancelablePromise<ResolutionProposalResponse> {
+    return this.httpRequest.request({
+      method: 'GET',
+      url: '/api/annotations/config/resolve/',
+      headers: {
+        'x-project-id': xProjectId,
+      },
+      query: {
+        'strategy': strategy,
+        'scheme_id': schemeId,
+        'scope_id': scopeId,
+        'user_id': userId,
+        'key': key,
+        'repeat': repeat,
+        'ignore_order': ignoreOrder,
+        'ignore_hierarchy': ignoreHierarchy,
+      },
+      errors: {
+        422: `Validation Error`,
+      },
+      ...options,
+    });
+  }
+
+  /**
+   * Save Resolved Annotations
+   * @returns string Successful Response
+   * @throws ApiError
+   */
+  public saveResolvedAnnotationsApiAnnotationsConfigResolvePut({
+    xProjectId,
+    requestBody,
+  }: {
+    xProjectId: string,
+    requestBody: ResolutionPayload,
+  }, options?: Partial<ApiRequestOptions>): CancelablePromise<string> {
+    return this.httpRequest.request({
+      method: 'PUT',
+      url: '/api/annotations/config/resolve/',
+      headers: {
+        'x-project-id': xProjectId,
+      },
+      body: requestBody,
+      mediaType: 'application/json',
+      errors: {
+        422: `Validation Error`,
+      },
+      ...options,
+    });
+  }
+
+  /**
+   * Update Resolved Annotations
+   * @returns any Successful Response
+   * @throws ApiError
+   */
+  public updateResolvedAnnotationsApiAnnotationsConfigResolveUpdatePut({
+    botAnnotationMetadataId,
+    name,
+    xProjectId,
+    requestBody,
+  }: {
+    botAnnotationMetadataId: string,
+    name: string,
+    xProjectId: string,
+    requestBody: Array<BotAnnotationModel>,
+  }, options?: Partial<ApiRequestOptions>): CancelablePromise<any> {
+    return this.httpRequest.request({
+      method: 'PUT',
+      url: '/api/annotations/config/resolve/update',
+      headers: {
+        'x-project-id': xProjectId,
+      },
+      query: {
+        'bot_annotation_metadata_id': botAnnotationMetadataId,
+        'name': name,
+      },
+      body: requestBody,
+      mediaType: 'application/json',
+      errors: {
+        422: `Validation Error`,
+      },
+      ...options,
+    });
+  }
+
+  /**
+   * List Saved Resolved Annotations
+   * @returns BotAnnotationMetaDataBaseModel Successful Response
+   * @throws ApiError
+   */
+  public listSavedResolvedAnnotationsApiAnnotationsConfigResolvedListGet({
+    xProjectId,
+  }: {
+    xProjectId: string,
+  }, options?: Partial<ApiRequestOptions>): CancelablePromise<Array<BotAnnotationMetaDataBaseModel>> {
+    return this.httpRequest.request({
+      method: 'GET',
+      url: '/api/annotations/config/resolved-list/',
+      headers: {
+        'x-project-id': xProjectId,
+      },
+      errors: {
+        422: `Validation Error`,
+      },
+      ...options,
+    });
+  }
+
+  /**
+   * Get Saved Resolved Annotations
+   * @returns SavedResolutionResponse Successful Response
+   * @throws ApiError
+   */
+  public getSavedResolvedAnnotationsApiAnnotationsConfigResolvedBotAnnotationMetaIdGet({
+    botAnnotationMetadataId,
+    xProjectId,
+  }: {
+    botAnnotationMetadataId: string,
+    xProjectId: string,
+  }, options?: Partial<ApiRequestOptions>): CancelablePromise<SavedResolutionResponse> {
+    return this.httpRequest.request({
+      method: 'GET',
+      url: '/api/annotations/config/resolved/:bot_annotation_meta_id',
+      headers: {
+        'x-project-id': xProjectId,
+      },
+      query: {
+        'bot_annotation_metadata_id': botAnnotationMetadataId,
+      },
+      errors: {
+        422: `Validation Error`,
+      },
+      ...options,
+    });
+  }
+
+  /**
+   * Delete Saved Resolved Annotations
+   * @returns any Successful Response
+   * @throws ApiError
+   */
+  public deleteSavedResolvedAnnotationsApiAnnotationsConfigResolvedBotAnnotationMetaIdDelete({
+    botAnnotationMetadataId,
+    xProjectId,
+  }: {
+    botAnnotationMetadataId: string,
+    xProjectId: string,
+  }, options?: Partial<ApiRequestOptions>): CancelablePromise<any> {
+    return this.httpRequest.request({
+      method: 'DELETE',
+      url: '/api/annotations/config/resolved/:bot_annotation_meta_id',
+      headers: {
+        'x-project-id': xProjectId,
+      },
+      query: {
+        'bot_annotation_metadata_id': botAnnotationMetadataId,
+      },
+      errors: {
+        422: `Validation Error`,
+      },
+      ...options,
+    });
+  }
+
 }
diff --git a/src/plugins/api/api-core/services/DefaultService.ts b/src/plugins/api/api-core/services/DefaultService.ts
index 4f40ff749a087588478d82a6f6e672f665baaa64..95e441b1c4b8573bd7c525fbcc231807eb7d202c 100644
--- a/src/plugins/api/api-core/services/DefaultService.ts
+++ b/src/plugins/api/api-core/services/DefaultService.ts
@@ -85,17 +85,4 @@ export class DefaultService {
     });
   }
 
-  /**
-   * Test
-   * @returns any Successful Response
-   * @throws ApiError
-   */
-  public testApiPingTestGet(options?: Partial<ApiRequestOptions>): CancelablePromise<any> {
-    return this.httpRequest.request({
-      method: 'GET',
-      url: '/api/ping/test',
-      ...options,
-    });
-  }
-
 }
diff --git a/src/plugins/api/api-core/services/ProjectService.ts b/src/plugins/api/api-core/services/ProjectService.ts
index 042d9185bef1983d86fa075eac35ae6cad09ee06..054cd0d2b44ba0365ff1b8e32619803bca08f3e4 100644
--- a/src/plugins/api/api-core/services/ProjectService.ts
+++ b/src/plugins/api/api-core/services/ProjectService.ts
@@ -1,7 +1,8 @@
 /* istanbul ignore file */
 /* tslint:disable */
 /* eslint-disable */
-import type { ItemModel } from '../models/ItemModel';
+import type { AcademicItemModel } from '../models/AcademicItemModel';
+import type { GenericItemModel } from '../models/GenericItemModel';
 import type { ProjectModel } from '../models/ProjectModel';
 import type { ProjectPermissionsModel } from '../models/ProjectPermissionsModel';
 import type { TwitterItemModel } from '../models/TwitterItemModel';
@@ -20,19 +21,14 @@ export class ProjectService {
    * @returns ProjectModel Successful Response
    * @throws ApiError
    */
-  public getProjectApiProjectProjectIdInfoGet({
-    projectId,
+  public getProjectApiProjectInfoGet({
     xProjectId,
   }: {
-    projectId: string,
     xProjectId: string,
   }, options?: Partial<ApiRequestOptions>): CancelablePromise<ProjectModel> {
     return this.httpRequest.request({
       method: 'GET',
-      url: '/api/project/{project_id}/info/',
-      path: {
-        'project_id': projectId,
-      },
+      url: '/api/project/info',
       headers: {
         'x-project-id': xProjectId,
       },
@@ -48,14 +44,14 @@ export class ProjectService {
    * @returns ProjectPermissionsModel Successful Response
    * @throws ApiError
    */
-  public getProjectPermissionsCurrentUserApiProjectProjectIdPermissionsMeGet({
+  public getProjectPermissionsCurrentUserApiProjectPermissionsMeGet({
     xProjectId,
   }: {
     xProjectId: string,
   }, options?: Partial<ApiRequestOptions>): CancelablePromise<ProjectPermissionsModel> {
     return this.httpRequest.request({
       method: 'GET',
-      url: '/api/project/{project_id}/permissions/me',
+      url: '/api/project/permissions/me',
       headers: {
         'x-project-id': xProjectId,
       },
@@ -71,7 +67,7 @@ export class ProjectService {
    * @returns ProjectPermissionsModel Successful Response
    * @throws ApiError
    */
-  public getAllProjectPermissionsApiProjectProjectIdPermissionsListGet({
+  public getAllProjectPermissionsApiProjectPermissionsListProjectIdGet({
     projectId,
     xProjectId,
   }: {
@@ -80,7 +76,7 @@ export class ProjectService {
   }, options?: Partial<ApiRequestOptions>): CancelablePromise<Array<ProjectPermissionsModel>> {
     return this.httpRequest.request({
       method: 'GET',
-      url: '/api/project/{project_id}/permissions/list',
+      url: '/api/project/permissions/list/{project_id}',
       path: {
         'project_id': projectId,
       },
@@ -99,7 +95,7 @@ export class ProjectService {
    * @returns ProjectPermissionsModel Successful Response
    * @throws ApiError
    */
-  public getProjectPermissionsByIdApiProjectProjectIdPermissionsProjectPermissionIdGet({
+  public getProjectPermissionsByIdApiProjectPermissionsProjectPermissionIdGet({
     projectPermissionId,
     xProjectId,
   }: {
@@ -108,7 +104,7 @@ export class ProjectService {
   }, options?: Partial<ApiRequestOptions>): CancelablePromise<ProjectPermissionsModel> {
     return this.httpRequest.request({
       method: 'GET',
-      url: '/api/project/{project_id}/permissions/{project_permission_id}',
+      url: '/api/project/permissions/{project_permission_id}',
       path: {
         'project_permission_id': projectPermissionId,
       },
@@ -127,20 +123,17 @@ export class ProjectService {
    * @returns any Successful Response
    * @throws ApiError
    */
-  public listProjectDataApiProjectProjectIdItemsItemTypeListGet({
-    projectId,
+  public listProjectDataApiProjectItemsItemTypeListGet({
     itemType,
     xProjectId,
   }: {
-    projectId: string,
-    itemType: 'basic' | 'twitter' | 'academic' | 'patents',
+    itemType: 'generic' | 'twitter' | 'academic' | 'patents',
     xProjectId: string,
-  }, options?: Partial<ApiRequestOptions>): CancelablePromise<Array<(ItemModel | TwitterItemModel)>> {
+  }, options?: Partial<ApiRequestOptions>): CancelablePromise<Array<(GenericItemModel | TwitterItemModel | AcademicItemModel)>> {
     return this.httpRequest.request({
       method: 'GET',
-      url: '/api/project/{project_id}/items/{item_type}/list',
+      url: '/api/project/items/{item_type}/list',
       path: {
-        'project_id': projectId,
         'item_type': itemType,
       },
       headers: {
@@ -158,24 +151,21 @@ export class ProjectService {
    * @returns any Successful Response
    * @throws ApiError
    */
-  public listProjectDataPagedApiProjectProjectIdItemsItemTypeListPagePageSizeGet({
-    projectId,
+  public listProjectDataPagedApiProjectItemsItemTypeListPagePageSizeGet({
     itemType,
     page,
     pageSize,
     xProjectId,
   }: {
-    projectId: string,
-    itemType: 'basic' | 'twitter' | 'academic' | 'patents',
+    itemType: 'generic' | 'twitter' | 'academic' | 'patents',
     page: number,
     pageSize: number,
     xProjectId: string,
-  }, options?: Partial<ApiRequestOptions>): CancelablePromise<Array<(ItemModel | TwitterItemModel)>> {
+  }, options?: Partial<ApiRequestOptions>): CancelablePromise<Array<(GenericItemModel | TwitterItemModel | AcademicItemModel)>> {
     return this.httpRequest.request({
       method: 'GET',
-      url: '/api/project/{project_id}/items/{item_type}/list/{page}/{page_size}',
+      url: '/api/project/items/{item_type}/list/{page}/{page_size}',
       path: {
-        'project_id': projectId,
         'item_type': itemType,
         'page': page,
         'page_size': pageSize,
@@ -195,25 +185,27 @@ export class ProjectService {
    * @returns any Successful Response
    * @throws ApiError
    */
-  public getDetailForItemApiProjectProjectIdItemsItemTypeDetailItemIdGet({
+  public getDetailForItemApiProjectItemsDetailItemIdGet({
     itemId,
-    itemType,
     xProjectId,
+    itemType,
   }: {
     itemId: string,
-    itemType: 'basic' | 'twitter' | 'academic' | 'patents',
     xProjectId: string,
-  }, options?: Partial<ApiRequestOptions>): CancelablePromise<(ItemModel | TwitterItemModel)> {
+    itemType?: 'generic' | 'twitter' | 'academic' | 'patents',
+  }, options?: Partial<ApiRequestOptions>): CancelablePromise<(GenericItemModel | TwitterItemModel | AcademicItemModel)> {
     return this.httpRequest.request({
       method: 'GET',
-      url: '/api/project/{project_id}/items/{item_type}/detail/{item_id}',
+      url: '/api/project/items/detail/{item_id}',
       path: {
         'item_id': itemId,
-        'item_type': itemType,
       },
       headers: {
         'x-project-id': xProjectId,
       },
+      query: {
+        'item_type': itemType,
+      },
       errors: {
         422: `Validation Error`,
       },
@@ -226,19 +218,14 @@ export class ProjectService {
    * @returns number Successful Response
    * @throws ApiError
    */
-  public countProjectItemsApiProjectProjectIdItemsCountGet({
-    projectId,
+  public countProjectItemsApiProjectItemsCountGet({
     xProjectId,
   }: {
-    projectId: string,
     xProjectId: string,
   }, options?: Partial<ApiRequestOptions>): CancelablePromise<number> {
     return this.httpRequest.request({
       method: 'GET',
-      url: '/api/project/{project_id}/items/count',
-      path: {
-        'project_id': projectId,
-      },
+      url: '/api/project/items/count',
       headers: {
         'x-project-id': xProjectId,
       },
@@ -254,24 +241,24 @@ export class ProjectService {
    * @returns any Successful Response
    * @throws ApiError
    */
-  public addTweetApiProjectProjectIdItemsTwitterAddPost({
-    projectId,
+  public addTweetApiProjectItemsTwitterAddPost({
     xProjectId,
     requestBody,
+    importId,
   }: {
-    projectId: string,
     xProjectId: string,
     requestBody: TwitterItemModel,
+    importId?: string,
   }, options?: Partial<ApiRequestOptions>): CancelablePromise<any> {
     return this.httpRequest.request({
       method: 'POST',
-      url: '/api/project/{project_id}/items/twitter/add',
-      path: {
-        'project_id': projectId,
-      },
+      url: '/api/project/items/twitter/add',
       headers: {
         'x-project-id': xProjectId,
       },
+      query: {
+        'import_id': importId,
+      },
       body: requestBody,
       mediaType: 'application/json',
       errors: {
diff --git a/src/plugins/events/EventHandlers/project.ts b/src/plugins/events/EventHandlers/project.ts
index b3993efe67afab1778092a8172a4f5ffc2021992..ff5f59ce99783d3b776d615192bb23102fcb4b27 100644
--- a/src/plugins/events/EventHandlers/project.ts
+++ b/src/plugins/events/EventHandlers/project.ts
@@ -14,8 +14,8 @@ export default () => {
     currentProjectStore.projectId = projectId;
     Promise
       .allSettled([
-        API.core.project.getProjectApiProjectProjectIdInfoGet({ xProjectId: projectId, projectId }),
-        API.core.project.getProjectPermissionsCurrentUserApiProjectProjectIdPermissionsMeGet({ xProjectId: projectId }),
+        API.core.project.getProjectApiProjectInfoGet({ xProjectId: projectId }),
+        API.core.project.getProjectPermissionsCurrentUserApiProjectPermissionsMeGet({ xProjectId: projectId }),
       ])
       .then((values) => {
         const [projectInfo, projectPermissions] = values;
diff --git a/src/router/index.ts b/src/router/index.ts
index 9529c099cfca9bb2bec482e189d7a2b75d847b0d..cb15a955b6782e6991e88a87c71773fbc14886e0 100644
--- a/src/router/index.ts
+++ b/src/router/index.ts
@@ -137,6 +137,29 @@ const routes: Array<RouteRecordRaw> = [
         name: 'config-annotation-scheme-edit',
         component: () => import(/* webpackChunkName: "AnnotationConfigEditView" */ '../views/Annotations/AnnotationConfigs/AnnotationConfigEditView.vue'),
       },
+      {
+        path: 'resolved/',
+        name: 'config-resolved-annotations-list',
+        component: () => import(/* webpackChunkName: "AnnotationConfigResolveView" */ '../views/Annotations/AnnotationConfigs/AnnotationConfigResolvedListView.vue'),
+      },
+      {
+        path: 'resolve/:bot_annotation_metadata_id?',
+        name: 'config-annotation-resolve',
+        component: () => import(/* webpackChunkName: "AnnotationConfigResolveView" */ '../views/Annotations/AnnotationConfigs/AnnotationConfigResolveView.vue'),
+      },
+    ],
+  },
+  {
+    path: '/project/settings',
+    name: 'project-settings',
+    component: () => import(/* webpackChunkName: "ProjectSettingsContainer" */ '../views/Projects/ProjectSettingsContainer.vue'),
+    children: [
+      {
+        path: '',
+        alias: ['', 'settings'],
+        name: 'project-settings-settings',
+        component: () => import(/* webpackChunkName: "ProjectSettingsView" */ '../views/Projects/ProjectSettingsView.vue'),
+      },
     ],
   },
 ];
@@ -147,7 +170,7 @@ const router = createRouter({
 });
 
 // eslint-disable-next-line @typescript-eslint/no-unused-vars
-router.beforeEach(async (to, from) => {
+router.beforeEach(async (to) => {
   // if user is not authenticated -> redirect to login page
   // prevent infinite redirects if user isn't logged in
   if (!currentUserStore.isLoggedIn && to.name !== 'login') {
diff --git a/src/types/annotations.ts b/src/types/annotations.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/types/colours.ts b/src/types/colours.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5f8d0585a0fe8e57be1c921ecc10f5e2f8106833
--- /dev/null
+++ b/src/types/colours.ts
@@ -0,0 +1,37 @@
+export const cmap20 = [
+  '#e6194B', // # 0
+  '#3cb44b', // # 1
+  '#ffe119', // # 2
+  '#4363d8', // # 3
+  '#f58231', // # 4
+  '#911eb4', // # 5
+  '#42d4f4', // # 6
+  '#f032e6', // # 7
+  '#bfef45', // # 8
+  '#fabed4', // # 9
+  '#469990', // # 10
+  '#dcbeff', // # 11
+  '#9A6324', // # 12
+  '#fffac8', // # 13
+  '#800000', // # 14
+  '#aaffc3', // # 15
+  '#808000', // # 16
+  '#ffd8b1', // # 17
+  '#000075', // # 18
+  '#a9a9a9', // # 19
+  '#ffffff', // # 20
+  '#000000', // # 21
+];
+
+export const cmap10 = [
+  '#4e79a7', // # 0
+  '#f28e2c', // # 1
+  '#e15759', // # 2
+  '#76b7b2', // # 3
+  '#59a14f', // # 4
+  '#edc949', // # 5
+  '#af7aa1', // # 6
+  '#ff9da7', // # 7
+  '#9c755f', // # 8
+  '#bab0ab', // # 9
+];
diff --git a/src/views/Annotations/AnnotationConfigs/AnnotationConfigEditView.vue b/src/views/Annotations/AnnotationConfigs/AnnotationConfigEditView.vue
index 57ae7f13a81ae716c2d663be6b0374837166217b..27565ec7cdc1a1a260ffd75e3a2a5d0243ecd48a 100644
--- a/src/views/Annotations/AnnotationConfigs/AnnotationConfigEditView.vue
+++ b/src/views/Annotations/AnnotationConfigs/AnnotationConfigEditView.vue
@@ -97,6 +97,8 @@ export default {
     if (!this.isNewScheme) {
       API.core.annotations.getSchemeDefinitionApiAnnotationsSchemesDefinitionAnnotationSchemeIdGet({
         annotationSchemeId: this.annotationSchemeId,
+        xProjectId: currentProjectStore.projectId,
+        flat: false,
       })
         .then((response) => {
           this.scheme = ref(response.data);
diff --git a/src/views/Annotations/AnnotationConfigs/AnnotationConfigListView.vue b/src/views/Annotations/AnnotationConfigs/AnnotationConfigListView.vue
index a11652a580bc330e4333ce4ce77671f824046302..4ee57d4cbc1c463001bd061909dc2209b7d5a2ff 100644
--- a/src/views/Annotations/AnnotationConfigs/AnnotationConfigListView.vue
+++ b/src/views/Annotations/AnnotationConfigs/AnnotationConfigListView.vue
@@ -103,6 +103,7 @@ export default {
     try {
       this.projectSchemes = (await API.core.annotations.getSchemeDefinitionsForProjectApiAnnotationsSchemesListProjectIdGet({
         projectId: currentProjectStore.projectId,
+        xProjectId: currentProjectStore.projectId,
       })).data;
       this.projectScopes = (await API.core.annotations.getAssignmentScopesForProjectApiAnnotationsAnnotateScopesGet({
         xProjectId: currentProjectStore.projectId,
@@ -128,6 +129,7 @@ export default {
 
         const schemes = await API.core.annotations.getSchemeDefinitionsForProjectApiAnnotationsSchemesListProjectIdGet({
           projectId: currentProjectStore.projectId,
+          xProjectId: currentProjectStore.projectId,
         });
         this.projectSchemes = schemes.data;
       } catch (e) {
diff --git a/src/views/Annotations/AnnotationConfigs/AnnotationConfigResolveView.vue b/src/views/Annotations/AnnotationConfigs/AnnotationConfigResolveView.vue
new file mode 100644
index 0000000000000000000000000000000000000000..cd0a80f67f7f9300e9fbc6f23d5a436bb7be2b3c
--- /dev/null
+++ b/src/views/Annotations/AnnotationConfigs/AnnotationConfigResolveView.vue
@@ -0,0 +1,668 @@
+<template>
+  <div class="text-start">
+    <div class="row">
+      <h1>Resolve Annotations</h1>
+    </div>
+    <div class="row mx-auto">
+      <div class="accordion">
+        <div class="accordion-item">
+          <h2 class="accordion-header">
+            <button
+              class="accordion-button"
+              type="button"
+              data-bs-toggle="collapse"
+              data-bs-target="#resolve-config"
+              aria-expanded="true"
+              aria-controls="resolve-config">
+              Annotation Export Configuration
+            </button>
+          </h2>
+          <div
+            id="resolve-config"
+            class="accordion-collapse collapse show">
+            <div class="accordion-body">
+              <div class="row">
+                <div class="col">
+                  <div class="mb-3">
+                    <div class="form-floating mb-3">
+                      <input type="text" class="form-control" id="resolve-name" v-model="name" placeholder="Name" />
+                      <label for="resolve-name">Descriptive name for this annotation export</label>
+                    </div>
+                  </div>
+                </div>
+              </div>
+              <div class="row gy-5">
+                <div class="col border-end">
+                  <div class="mb-3">
+                    <label for="schema-selector" class="form-label">Annotation Scheme</label>
+                    <select
+                      :disabled="!isNew"
+                      id="schema-selector"
+                      class="form-select"
+                      aria-label="Schema selector"
+                      v-model="filters.scheme_id">
+                      <option :value="undefined" disabled>Please choose...</option>
+                      <option
+                        v-for="scheme in projectAnnotationSchemes"
+                        :key="scheme.annotation_scheme_id"
+                        :value="scheme.annotation_scheme_id">
+                        {{ scheme.name }}
+                      </option>
+                    </select>
+                  </div>
+                  <div v-if="schemeFlat.length > 0" class="mb-3 border-bottom">
+                    <div class="form-label">Scheme labels to resolve</div>
+                    <ul class="list-unstyled ms-lg-2">
+                      <li v-for="label in schemeFlat" :key="label.key">
+                        <input
+                          class="form-check-input me-1"
+                          type="checkbox"
+                          :id="`schema-label-selector-${label.key}`"
+                          :value="label.key"
+                          v-model="filters.key"
+                          :disabled="!isNew" />
+                        <label
+                          class="form-check-label"
+                          :for="`schema-label-selector-${label.key}`"><strong>{{ label.key }}</strong> – {{
+                            label.name
+                          }}</label>
+                      </li>
+                    </ul>
+                  </div>
+                  <div class="mb-3 border-bottom" v-if="filters.key.length > 0">
+                    <div class="form-label">
+                      Repeats to resolve
+                      <ToolTip>
+                        Allows you to select which annotations to resolve if annotations can have an order.
+                        For example, whether to only resolve primary annotation of a kind (and ignore secondary,...)
+                        annotations.
+                      </ToolTip>
+                    </div>
+                    <div class="form-check form-check-inline" v-if="filters.key.length > 0">
+                      <input
+                        class="form-check-input"
+                        type="checkbox"
+                        id="repeat-selector-1"
+                        :value="1"
+                        v-model="filters.repeat"
+                        :disabled="!isNew">
+                      <label class="form-check-label" for="repeat-selector-1">1</label>
+                    </div>
+                    <div class="form-check form-check-inline">
+                      <input
+                        class="form-check-input"
+                        type="checkbox"
+                        id="repeat-selector-2"
+                        :value="2"
+                        v-model="filters.repeat"
+                        :disabled="!isNew">
+                      <label class="form-check-label" for="repeat-selector-2">2</label>
+                    </div>
+                    <div class="form-check form-check-inline">
+                      <input
+                        class="form-check-input"
+                        type="checkbox"
+                        id="repeat-selector-3"
+                        :value="3"
+                        v-model="filters.repeat"
+                        :disabled="!isNew">
+                      <label class="form-check-label" for="repeat-selector-3">3</label>
+                    </div>
+                    <div class="form-check form-check-inline">
+                      <input
+                        class="form-check-input"
+                        type="checkbox"
+                        id="repeat-selector-4"
+                        :value="4"
+                        v-model="filters.repeat"
+                        :disabled="!isNew">
+                      <label class="form-check-label" for="repeat-selector-4">4</label>
+                    </div>
+                  </div>
+                  <div class="mb-3 border-bottom" v-if="filters.key.length > 0">
+                    <div class="form-check">
+                      <input
+                        class="form-check-input"
+                        type="checkbox"
+                        v-model="ignoreHierarchy"
+                        id="check-ignore-hierarchy"
+                        :disabled="!isNew">
+                      <label class="form-check-label" for="check-ignore-hierarchy">
+                        Ignore scheme hierarchy
+                      </label>
+                    </div>
+                    <div class="form-check">
+                      <input
+                        class="form-check-input"
+                        type="checkbox"
+                        v-model="ignoreOrder"
+                        id="check-ignore-order"
+                        :disabled="!isNew">
+                      <label class="form-check-label" for="check-ignore-order">
+                        Ignore annotation order (<code>repeat</code>s)
+                      </label>
+                    </div>
+                  </div>
+                </div>
+                <div class="col">
+                  <div v-if="(assignmentScopes || []).length > 0" class="mb-3 border-bottom">
+                    <div class="form-label">Source assignment scopes</div>
+                    <ul class="list-unstyled ms-lg-2">
+                      <li v-for="scope in assignmentScopes" :key="scope.assignment_scope_id">
+                        <input
+                          class="form-check-input me-1"
+                          type="checkbox"
+                          :id="`scope-selector-${scope.assignment_scope_id}`"
+                          :value="scope.assignment_scope_id"
+                          v-model="filters.scope_id"
+                          :disabled="!isNew" />
+                        <label
+                          class="form-check-label"
+                          :for="`scope-selector-${scope.assignment_scope_id}`">{{ scope.name }}</label>
+                      </li>
+                    </ul>
+                  </div>
+                  <div v-if="(annotators || []).length > 0" class="mb-3 border-bottom">
+                    <div class="form-label">Annotator selector</div>
+                    <ul class="list-unstyled ms-lg-2">
+                      <li v-for="user in annotators" :key="user.user_id">
+                        <input
+                          class="form-check-input me-1"
+                          type="checkbox"
+                          :id="`annotator-selector-${user.user_id}`"
+                          :value="user.user_id"
+                          v-model="filters.user_id"
+                          :disabled="!isNew" />
+                        <label
+                          class="form-check-label"
+                          :for="`annotator-selector-${user.user_id}`">
+                          <strong>{{ user.username }}</strong> – {{ user.full_name }}
+                        </label>
+                      </li>
+                    </ul>
+                  </div>
+                  <div class="mb-3">
+                    <label for="algorithm-selector" class="form-label">Resolution algorithm</label>
+                    <select
+                      id="algorithm-selector"
+                      class="form-select"
+                      aria-label="Resolution algorithm"
+                      v-model="algorithm"
+                      :disabled="!isNew">
+                      <option value="majority">majority vote</option>
+                      <option value="trust" disabled>weighted majority</option>
+                      <option value="first" disabled>first annotation</option>
+                      <option value="last" disabled>last annotation</option>
+                      <option value="??" disabled>sorcery</option>
+                    </select>
+                  </div>
+                </div>
+              </div>
+              <div class="row">
+                <div class="col text-end">
+                  <button class="btn btn-primary" type="button" disabled v-if="loadingProposals">
+                    <span class="spinner-border spinner-border-sm" role="status" aria-hidden="true" />
+                    Loading...
+                  </button>
+                  <button
+                    class="btn btn-primary"
+                    type="button"
+                    v-else
+                    @click="fetchProposal"
+                    :disabled="!isConfigValid || !isNew">
+                    Load
+                  </button>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+    <div class="row text-end" v-if="isTableReady">
+      <div class="col">
+        <button
+          @click="save"
+          type="button"
+          class="btn btn-success m-2">Save
+        </button>
+      </div>
+    </div>
+    <div class="row" v-if="isTableReady">
+      <div class="table-responsive-sm position-relative">
+        <table class="table" style="width: calc(100% - 1rem)">
+          <thead class="sticky-top bg-light">
+            <tr>
+              <th>
+                Item
+                <label for="item-id-search" class="d-none">Search</label>
+                <input
+                  id="item-id-search"
+                  class="form-control form-control-sm"
+                  type="text"
+                  placeholder="Filter item_id"
+                  v-model="itemIdSearch" />
+              </th>
+              <th v-for="label in collection.labels" :key="label" class="text-end">
+                <div v-for="skey in label.slice().reverse()" :key="skey.key" class="nacsos-tooltip label-pill m-1">
+                  <span>{{ skey.key }}</span>
+                  <span>{{ skey.repeat }}</span>
+                  <div
+                    class="nacsos-tooltiptext popover bs-popover-auto show bg-light p-0"
+                    style="position: absolute; right: 0; margin: 0.5rem 0 0 0;"
+                    role="tooltip"
+                    data-popper-placement="bottom">
+                    <div
+                      class="popover-arrow"
+                      style="position: absolute; right: 0; transform: translateX(-30px);" />
+                    <h3 class="popover-header text-dark">{{ schemeLookup[skey.key].name }}</h3>
+                    <div class="popover-body">
+                      <template v-if="schemeLookup[skey.key].choices">
+                        <ul class="list-unstyled">
+                          <li v-for="choice in schemeLookup[skey.key].choices" :key="choice.value">
+                            <strong>{{ choice.value }}:</strong> {{ choice.name }}
+                          </li>
+                        </ul>
+                      </template>
+                      <template v-else>
+                        {{ schemeLookup[skey.key].kind }}
+                      </template>
+                    </div>
+                  </div>
+                </div>
+              </th>
+            </tr>
+          </thead>
+          <tbody>
+            <tr
+              v-for="itemId in Object.keys(collection.annotations)"
+              :key="itemId"
+              v-show="itemIdSearch === '' || itemId.indexOf(itemIdSearch) >= 0">
+              <td>
+                <span
+                  class="text-muted font-monospace fs-fn text-break me-2 d-inline-block"
+                  style="width: 20ch;"
+                  role="button"
+                  tabindex="-1"
+                  @click="this.focusItem = itemId">
+                  {{ itemId }}
+                </span>
+              </td>
+              <td
+                v-for="(labelInfo, strLabel) in labels"
+                :key="strLabel"
+                class="text-end"
+                :class="{ 'bg-warning': !isValid(labelInfo, itemId, strLabel) }">
+                <template v-if="schemeLookup[labelInfo.path[0].key]?.kind === 'bool'">
+                  <BoolLabel
+                    :user-annotations="matrix[itemId][strLabel].users"
+                    :bot-annotation="matrix[itemId][strLabel].bot"
+                    :info="schemeLookup[labelInfo.path[0].key]"
+                    :users="userLookup"
+                    @bot-annotation-changed="handleChangedBotAnnotation" />
+                </template>
+                <template v-else-if="schemeLookup[labelInfo.path[0].key]?.kind === 'single'">
+                  <ChoiceLabel
+                    :user-annotations="matrix[itemId][strLabel].users"
+                    :bot-annotation="matrix[itemId][strLabel].bot"
+                    :info="schemeLookup[labelInfo.path[0].key]"
+                    :users="userLookup"
+                    @bot-annotation-changed="handleChangedBotAnnotation" />
+                </template>
+                <template v-else>
+                  Unhandled "{{ schemeLookup[labelInfo.path[0].key]?.kind }}"
+                </template>
+              </td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+    </div>
+    <ItemModal :item-id="focusItem" @dismissed="focusItem = undefined" />
+  </div>
+</template>
+
+<script lang="ts">
+import { currentProjectStore } from '@/stores';
+import {
+  AnnotationSchemeModel,
+  AnnotationModel,
+  FlattenedAnnotationSchemeLabel,
+  AssignmentScopeModel,
+  BotMetaResolve,
+  BotAnnotationModel,
+  AnnotationFilters,
+  AnnotationCollection,
+  Label,
+  UserModel,
+  AnnotationCollectionDB,
+} from '@/plugins/api/api-core';
+import { API } from '@/plugins/api';
+import BoolLabel from '@/components/annotations/resolve/BoolLabel.vue';
+import ItemModal from '@/components/items/ItemModal.vue';
+import ChoiceLabel from '@/components/annotations/resolve/ChoiceLabel.vue';
+import ToolTip from '@/components/ToolTip.vue';
+import { EventBus } from '@/plugins/events';
+import { ToastEvent } from '@/plugins/events/events/toast';
+
+type LookupMatrix = Record<string, Record<string, { users: AnnotationModel[], bot: BotAnnotationModel | undefined }>>;
+type LabelLookupValue = {
+  parentChoice?: number,
+  parentKey?: string,
+  path: Label[],
+  strParent?: string,
+};
+type LabelLookup = Record<string, LabelLookupValue>;
+
+type ResolveData = {
+  botAnnotationMetaDataId: string | undefined,
+  isNew: boolean, // set to true if this is not saved yet
+  name: string,
+  algorithm: BotMetaResolve.algorithm,
+  ignoreHierarchy: boolean,
+  ignoreOrder: boolean,
+  filters: Partial<AnnotationFilters>,
+  schemeFlat: FlattenedAnnotationSchemeLabel[],
+  collection: AnnotationCollection | undefined,
+  botAnnotations: Record<string, Array<[Label[], BotAnnotationModel]>>,
+  // id of item in focus (to be opened in modal)
+  focusItem: string | undefined,
+  // only used for setup (empty when botAnnotationMetaDataId not None)
+  projectAnnotationSchemes: AnnotationSchemeModel[],
+  // assignment scopes linking to filters.scheme_id
+  assignmentScopes: AssignmentScopeModel[],
+  annotators: UserModel[],
+  loadingProposals: boolean,
+  itemIdSearch: string,
+};
+
+export default {
+  name: 'AnnotationConfigResolveView',
+  components: { ToolTip, ItemModal, BoolLabel, ChoiceLabel },
+  data(): ResolveData {
+    const botAnnotationMetaDataId: string | undefined = this.$route.params.bot_annotation_metadata_id;
+
+    return {
+      botAnnotationMetaDataId,
+      isNew: !botAnnotationMetaDataId,
+      name: '',
+      filters: {
+        scheme_id: undefined,
+        scope_id: [] as string[],
+        key: [] as string[],
+        user_id: [] as string[],
+        repeat: [1, 2, 3, 4],
+      } as Partial<AnnotationFilters>,
+      algorithm: BotMetaResolve.algorithm.MAJORITY,
+      ignoreHierarchy: false,
+      ignoreOrder: false,
+      schemeFlat: [] as FlattenedAnnotationSchemeLabel[],
+      collection: undefined as AnnotationCollection | undefined,
+      botAnnotations: {} as Record<string, Array<[Label[], BotAnnotationModel]>>,
+      focusItem: undefined as string | undefined,
+      projectAnnotationSchemes: [] as AnnotationSchemeModel[],
+      assignmentScopes: [] as AssignmentScopeModel[],
+      annotators: [] as UserModel[],
+      loadingProposals: false,
+      itemIdSearch: '',
+    };
+  },
+
+  mounted() {
+    this.fetchProjectSchemas();
+
+    if (!this.isNew && this.botAnnotationMetaDataId !== undefined) {
+      API.core.annotations.getSavedResolvedAnnotationsApiAnnotationsConfigResolvedBotAnnotationMetaIdGet({
+        botAnnotationMetadataId: this.botAnnotationMetaDataId,
+        xProjectId: currentProjectStore.projectId,
+      }).then((response) => {
+        const { data } = response;
+
+        this.name = data.name;
+        this.algorithm = data.meta.algorithm;
+        this.filters = data.meta.filters;
+        this.ignoreOrder = data.meta.ignore_repeat;
+        this.ignoreHierarchy = data.meta.ignore_hierarchy;
+        this.collection = data.meta.collection;
+        this.botAnnotations = data.saved;
+      });
+    }
+  },
+
+  watch: {
+    'filters.scheme_id': {
+      handler(schemeId: string) {
+        if (schemeId) {
+          // fetch `AssignmentScope`s for the current `AnnotationScheme`
+          API.core.annotations.getAssignmentScopesForSchemeApiAnnotationsConfigScopesSchemeIdGet({
+            schemeId,
+            xProjectId: currentProjectStore.projectId,
+          }).then((response) => {
+            const { data } = response;
+            this.assignmentScopes = data;
+          });
+
+          // fetch `Users`s that created annotations linked to the current `AnnotationScheme`
+          API.core.annotations.getAnnotatorsForSchemeApiAnnotationsConfigAnnotatorsSchemeIdGet({
+            schemeId,
+            xProjectId: currentProjectStore.projectId,
+          }).then((response) => {
+            const { data } = response;
+            this.annotators = data;
+          });
+
+          // fetch flattened annotation scheme
+          API.core.annotations.getSchemeDefinitionApiAnnotationsSchemesDefinitionAnnotationSchemeIdGet({
+            annotationSchemeId: schemeId,
+            xProjectId: currentProjectStore.projectId,
+            flat: true,
+          }).then((response) => {
+            const { data } = response;
+            this.schemeFlat = data.labels;
+          });
+        }
+      },
+      immediate: true,
+    },
+  },
+
+  methods: {
+    isValid(labelInfo: LabelLookupValue, itemId: string, strPath: string): boolean {
+      /**
+       * This function checks the validity of the resolved label for an item.
+       * A label is invalid, if the parent label does not have this one as a child.
+       */
+
+      // entries w/o parents are always valid
+      if (labelInfo.strParent === undefined) return true;
+      // empty bot annotations are always valid (independent of parent label)
+      if (this.matrix[itemId][strPath] === undefined
+        || this.matrix[itemId][strPath].bot === undefined
+        || (this.matrix[itemId][strPath].bot?.value_int === undefined
+          && this.matrix[itemId][strPath].bot?.value_bool === undefined
+          && this.matrix[itemId][strPath].bot?.value_str === undefined
+          && this.matrix[itemId][strPath].bot?.value_float === undefined
+          && this.matrix[itemId][strPath].bot?.multi_int === undefined)) return true;
+      // ignore if parent label not in this view
+      // FIXME: verify that this is safe to assume (e.g. what if parent choice was never assigned rather
+      //        than explicitly not selected in this configuration)
+      if (!(labelInfo.strParent in this.labels)) return true;
+      // check if parent choice has this label as child
+      return this.matrix[itemId][labelInfo.strParent].bot?.value_int === this.schemeLookup[labelInfo.path[0].key].parent_choice;
+    },
+    fetchProposal() {
+      this.loadingProposals = true;
+      API.core.annotations.getResolvedAnnotationsApiAnnotationsConfigResolveGet({
+        strategy: this.algorithm,
+        xProjectId: currentProjectStore.projectId,
+        schemeId: this.filters.scheme_id,
+        scopeId: (!this.filters.scope_id) ? undefined : [this.filters.scope_id],
+        userId: (!this.filters.user_id) ? undefined : [this.filters.user_id],
+        key: (!this.filters.key) ? undefined : [this.filters.key],
+        repeat: (!this.filters.repeat) ? undefined : [this.filters.repeat],
+        ignoreHierarchy: this.ignoreHierarchy,
+        ignoreOrder: this.ignoreOrder,
+      }).then((response) => {
+        const { data } = response;
+        this.collection = data.collection;
+        this.botAnnotations = data.proposal;
+        this.loadingProposals = false;
+      });
+    },
+    fetchProjectSchemas() {
+      API.core.annotations.getSchemeDefinitionsForProjectApiAnnotationsSchemesListProjectIdGet({
+        projectId: currentProjectStore.projectId,
+        xProjectId: currentProjectStore.projectId,
+      }).then((response) => {
+        const { data } = response;
+        this.projectAnnotationSchemes = data;
+      });
+    },
+    handleChangedBotAnnotation(updatedBotAnnotation: BotAnnotationModel) {
+      console.log(updatedBotAnnotation);
+      console.log('asd');
+    },
+    save() {
+      if (!this.isNew) {
+        this.update();
+      } else {
+        this.saveNew();
+      }
+    },
+    update() {
+      API.core.annotations.updateResolvedAnnotationsApiAnnotationsConfigResolveUpdatePut({
+        botAnnotationMetadataId: this.botAnnotationMetaDataId,
+        name: this.name,
+        xProjectId: currentProjectStore.projectId,
+        requestBody: this.flattenBotAnnotations(),
+      });
+    },
+    flattenBotAnnotations(): BotAnnotationModel[] {
+      return (Object.values(this.botAnnotations) as [Label[], BotAnnotationModel][][])
+        .map((itemAnnotations) => (itemAnnotations as [Label[], BotAnnotationModel][])
+          .map(([, annotation]) => annotation)).flat();
+    },
+    saveNew() {
+      const collection: AnnotationCollectionDB = JSON.parse(JSON.stringify(this.collection));
+      collection.annotators = this.collection.annotators.map((user: UserModel) => user.user_id);
+      API.core.annotations.saveResolvedAnnotationsApiAnnotationsConfigResolvePut({
+        xProjectId: currentProjectStore.projectId,
+        requestBody: {
+          name: this.name,
+          strategy: this.algorithm,
+          filters: this.filters,
+          ignore_order: this.ignoreOrder,
+          ignore_hierarchy: this.ignoreHierarchy,
+          collection,
+          bot_annotations: this.flattenBotAnnotations(),
+        },
+      }).then((response) => {
+        const { data } = response;
+        EventBus.emit(new ToastEvent('SUCCESS', `Saved new annotation resolution as ${data}`));
+        this.isNew = false;
+        this.botAnnotationMetaDataId = data;
+        this.$router.replace({ name: 'config-annotation-resolve', params: { bot_annotation_metadata_id: data } });
+      }).catch((reason) => {
+        console.error(reason);
+        EventBus.emit(new ToastEvent('ERROR', 'Failed to save new annotation resolution!'));
+      });
+    },
+    label2string(label: Label[]) {
+      return label.map((label_: Label) => `${label_.key}:${label_.repeat}`).join('-');
+    },
+  },
+  computed: {
+    userLookup(): Record<string, UserModel> {
+      if (!this.annotators) {
+        return {};
+      }
+      return Object.fromEntries(this.annotators.map((user: UserModel) => [user.user_id, user]));
+    },
+    labels(): LabelLookup {
+      if (!this.collection || !this.collection.labels || Object.keys(this.schemeLookup).length === 0) {
+        return {};
+      }
+      return Object.fromEntries(this.collection.labels.map((label: Label[]) => [this.label2string(label),
+        {
+          path: label,
+          strParent: (label.length > 1) ? this.label2string(label.slice(1)) : undefined,
+          parentChoice: this.schemeLookup[label[0].key]?.parent_choice,
+          parentKey: this.schemeLookup[label[0].key]?.parent_label,
+        }]));
+    },
+    schemeLookup(): Record<string, FlattenedAnnotationSchemeLabel> {
+      if (!this.schemeFlat) return {};
+      return Object.fromEntries(this.schemeFlat.map((label: FlattenedAnnotationSchemeLabel) => [label.key, label]));
+    },
+    isTableReady(): boolean {
+      return this.collection && this.collection.annotations && Object.keys(this.labels).length > 0;
+    },
+    isConfigValid(): boolean {
+      // returns true if all necessary data is available to request a resolution proposal
+      return this.filters.scheme_id && this.filters.key.length > 0 && this.filters.user_id.length > 0;
+    },
+    matrix(): LookupMatrix {
+      if (!this.collection || !this.collection.annotations) {
+        return {};
+      }
+      const itemIds = Object.keys(this.collection.annotations);
+      const strPaths = Object.keys(this.labels);
+
+      const matrix = Object.fromEntries(itemIds.map((itemId) => [
+        itemId,
+        Object.fromEntries(strPaths.map((strPath) => [
+          strPath,
+          {
+            users: [] as AnnotationModel[],
+            bot: undefined as BotAnnotationModel | undefined,
+          }]))]));
+
+      Object.entries(this.collection.annotations).forEach((entry) => {
+        const [itemId, groupedAnnotations] = entry as [string, Array<[Label[], AnnotationModel[]]>];
+        groupedAnnotations.forEach(([path, annotations]) => {
+          matrix[itemId][this.label2string(path)].users = annotations;
+        });
+      });
+      if (this.botAnnotations) {
+        Object.entries(this.botAnnotations).forEach((entry) => {
+          const [itemId, botAnnotationEntry] = entry as [string, Array<[Label[], BotAnnotationModel]>];
+          botAnnotationEntry.forEach(([path, botAnnotation]) => {
+            const strPath = this.label2string(path);
+            matrix[itemId][strPath].bot = botAnnotation;
+          });
+        });
+      }
+      return matrix;
+    },
+  },
+};
+</script>
+
+<style scoped>
+.label-pill {
+  display: block !important;
+}
+
+.label-pill span {
+  border-radius: var(--bs-border-radius-pill);
+  border: 1px solid var(--bs-gray-500);
+  font-weight: normal;
+  /*font-size: var(--bs-badge-font-size);*/
+  font-size: 0.75em;
+  /*padding:  var(--bs-badge-padding-y) var(--bs-badge-padding-x);*/
+  padding: .35em .65em;
+}
+
+.label-pill span:first-child {
+  border-top-right-radius: 0;
+  border-bottom-right-radius: 0;
+}
+
+.label-pill span:last-of-type {
+  border-top-left-radius: 0;
+  border-bottom-left-radius: 0;
+  border-left: 0;
+  background-color: var(--bs-gray-300);
+}
+
+</style>
diff --git a/src/views/Annotations/AnnotationConfigs/AnnotationConfigResolvedListView.vue b/src/views/Annotations/AnnotationConfigs/AnnotationConfigResolvedListView.vue
new file mode 100644
index 0000000000000000000000000000000000000000..32a8ea67bc9fed620f41b34d089eca6065ba9347
--- /dev/null
+++ b/src/views/Annotations/AnnotationConfigs/AnnotationConfigResolvedListView.vue
@@ -0,0 +1,137 @@
+<template>
+  <div class="text-start">
+    <h1>Resolve and Export Annotations</h1>
+    <ul>
+      <li v-for="meta in exports" :key="meta.b">
+        {{ meta.name }}
+        <router-link
+          :to="{ name: 'config-annotation-resolve', params: { bot_annotation_metadata_id: meta.bot_annotation_metadata_id } }"
+          class="link-secondary me-1">
+          <InlineToolTip info="View & Resolve Annotations">
+            <font-awesome-icon :icon="['fas', 'pen']" />
+          </InlineToolTip>
+        </router-link>
+        <a
+          @click="clone(meta.bot_annotation_metadata_id)"
+          tabindex="0"
+          aria-label="Copy scheme"
+          class="link-secondary me-1"
+          role="button">
+          <InlineToolTip info="Copy">
+            <font-awesome-icon :icon="['far', 'clone']" />
+          </InlineToolTip>
+        </a>
+        <a
+          role="button"
+          class="link-secondary me-1"
+          tabindex="0"
+          aria-label="Delete resolved annotations"
+          @click="remove(meta)">
+          <InlineToolTip info="Delete">
+            <font-awesome-icon :icon="['fas', 'trash-can']" />
+          </InlineToolTip>
+        </a>
+        <a
+          role="button"
+          class="link-secondary me-1"
+          tabindex="0"
+          aria-label="Download annotations"
+          @click="download(meta.bot_annotation_metadata_id)">
+          <InlineToolTip info="Export data">
+            <font-awesome-icon :icon="['fas', 'file-export']" />
+          </InlineToolTip>
+        </a>
+      </li>
+    </ul>
+    <router-link
+      role="button"
+      class="btn btn-outline-primary m-2 btn-sm"
+      :to="{ name: 'config-annotation-resolve' }">
+      <font-awesome-icon :icon="['far', 'square-plus']" />
+      Create new export
+    </router-link>
+  </div>
+</template>
+
+<script lang="ts">
+import { currentProjectStore } from '@/stores';
+import { EventBus } from '@/plugins/events';
+import InlineToolTip from '@/components/InlineToolTip.vue';
+import { ToastEvent } from '@/plugins/events/events/toast';
+import { API, ApiResponseReject } from '@/plugins/api';
+import { BotAnnotationMetaDataBaseModel } from '@/plugins/api/api-core';
+import { ConfirmationRequestEvent } from '@/plugins/events/events/confirmation';
+
+type DataModel = {
+  exports: BotAnnotationMetaDataBaseModel[],
+};
+
+export default {
+  name: 'AnnotationConfigResolvedListView',
+  components: { InlineToolTip },
+  data(): DataModel {
+    return {
+      exports: [] as BotAnnotationMetaDataBaseModel[],
+    } as DataModel;
+  },
+  mounted() {
+    this.refreshData();
+  },
+  methods: {
+    refreshData() {
+      API.core.annotations.listSavedResolvedAnnotationsApiAnnotationsConfigResolvedListGet({
+        xProjectId: currentProjectStore.projectId,
+      }).then((response) => {
+        const { data } = response;
+        this.exports = data;
+      }).catch((reason) => {
+        console.error(reason);
+        const err = reason as ApiResponseReject;
+        EventBus.emit(new ToastEvent('ERROR', `Failed to load data (${err.error.type}: ${err.error.message})`));
+      });
+    },
+    clone(bot_annotation_metadata_id: string) {
+      // TODO
+      EventBus.emit(new ToastEvent(
+        'INFO',
+        `Not implemented yet, can't clone ${bot_annotation_metadata_id}.`,
+      ));
+    },
+    download(bot_annotation_metadata_id: string) {
+      // TODO
+      EventBus.emit(new ToastEvent(
+        'INFO',
+        `Not implemented yet, can't export ${bot_annotation_metadata_id}.`,
+      ));
+    },
+    remove(meta: BotAnnotationMetaDataBaseModel) {
+      EventBus.emit(new ConfirmationRequestEvent(
+        'Do you really want to **permanently delete** all resolved annotations associated to the scope shown below?\n'
+        + `- "${meta.name}"\n`
+        + `- ID: ${meta.bot_annotation_metadata_id}`,
+        (confirmationResponse) => {
+          if (confirmationResponse === 'ACCEPT') {
+            API.core.annotations.deleteSavedResolvedAnnotationsApiAnnotationsConfigResolvedBotAnnotationMetaIdDelete({
+              botAnnotationMetadataId: meta.bot_annotation_metadata_id!,
+              xProjectId: currentProjectStore.projectId,
+            }).then(() => {
+              EventBus.emit(new ToastEvent('SUCCESS', `Deleted ${meta.bot_annotation_metadata_id}`));
+              this.refreshData();
+            }).catch(() => {
+              EventBus.emit(new ToastEvent(
+                'ERROR',
+                `Failed to delete ${meta.bot_annotation_metadata_id}.`,
+              ));
+            });
+          }
+        },
+        'Delete resolved annotations',
+      ));
+    },
+  },
+};
+</script>
+
+<style scoped>
+
+</style>
diff --git a/src/views/Annotations/Annotations/AnnotationsView.vue b/src/views/Annotations/Annotations/AnnotationsView.vue
index ddb1f4daf25810549ea33d0bb3ac2c7449b400fe..275d19d4e4f3b71e5e6cebaf1dd1ab3cc495088d 100644
--- a/src/views/Annotations/Annotations/AnnotationsView.vue
+++ b/src/views/Annotations/Annotations/AnnotationsView.vue
@@ -17,7 +17,7 @@
           </ul>
         </div>
         <div class="row g-0">
-          <GenericItemComponent :item="item" />
+          <AnyItemComponent :item="item" />
         </div>
       </div>
       <div class="col border-start p-2 overflow-auto h-md-100 position-relative" :class="sidebarWidthClass">
@@ -69,7 +69,7 @@
 
 <script lang="ts">
 import { marked } from 'marked';
-import GenericItemComponent from '@/components/items/GenericItem.vue';
+import AnyItemComponent from '@/components/items/AnyItem.vue';
 import AnnotationLabels from '@/components/annotations/AnnotationLabels.vue';
 import { EventBus } from '@/plugins/events';
 import { ToastEvent } from '@/plugins/events/events/toast';
@@ -124,7 +124,7 @@ type AnnotationsViewData = {
 
 export default {
   name: 'AnnotationsView',
-  components: { AnnotationLabels, GenericItemComponent },
+  components: { AnnotationLabels, AnyItemComponent },
   data(): AnnotationsViewData {
     return {
       item: undefined,
diff --git a/src/views/Dataset/DatasetListView.vue b/src/views/Dataset/DatasetListView.vue
index 8715799dfd62137dac842cbb0b3bfa5a38dcd4a2..a1ff13de04539336adf735f1edc8a28ebdc7965a 100644
--- a/src/views/Dataset/DatasetListView.vue
+++ b/src/views/Dataset/DatasetListView.vue
@@ -61,7 +61,7 @@
           <div class="d-flex flex-row flex-wrap p-2 overflow-auto">
             <template v-if="this.itemList && this.itemList.length > 0">
               <template v-if="projectType === 'twitter'">
-                <GenericItemComponent
+                <AnyItemComponent
                   v-for="(item) in itemList"
                   :key="item.item_id"
                   :item="item" />
@@ -150,7 +150,7 @@
 
 <script lang="ts">
 import { currentProjectStore } from '@/stores';
-import GenericItemComponent from '@/components/items/GenericItem.vue';
+import AnyItemComponent from '@/components/items/AnyItem.vue';
 import { useOffsetPagination, UseOffsetPaginationReturn } from '@vueuse/core';
 import ClosablePill from '@/components/ClosablePill.vue';
 import { reactive } from 'vue';
@@ -159,7 +159,7 @@ import { API, toastReject } from '@/plugins/api';
 
 export default {
   name: 'ProjectDataView',
-  components: { ClosablePill, GenericItemComponent },
+  components: { ClosablePill, AnyItemComponent },
   data() {
     return {
       projectType: currentProjectStore.project.type,
@@ -171,8 +171,7 @@ export default {
     };
   },
   async mounted() {
-    API.core.project.countProjectItemsApiProjectProjectIdItemsCountGet({
-      projectId: currentProjectStore.projectId,
+    API.core.project.countProjectItemsApiProjectItemsCountGet({
       xProjectId: currentProjectStore.projectId,
     })
       .then((response) => {
@@ -190,9 +189,8 @@ export default {
   },
   methods: {
     fetchData({ currentPage, currentPageSize }: UseOffsetPaginationReturn): void {
-      API.core.project.listProjectDataPagedApiProjectProjectIdItemsItemTypeListPagePageSizeGet({
+      API.core.project.listProjectDataPagedApiProjectItemsItemTypeListPagePageSizeGet({
         xProjectId: currentProjectStore.projectId,
-        projectId: currentProjectStore.projectId,
         page: this.pagination.currentPage,
         pageSize: this.pagination.currentPageSize,
         itemType: currentProjectStore.project.type,
diff --git a/src/views/Imports/ImportDetailsView.vue b/src/views/Imports/ImportDetailsView.vue
index 86e0b65ee8e66f757358b620930f2d596503b32d..ca845d5e3b66145a1fc852b384aa780093907181 100644
--- a/src/views/Imports/ImportDetailsView.vue
+++ b/src/views/Imports/ImportDetailsView.vue
@@ -94,7 +94,7 @@ import { Component } from 'vue';
 import { ToastEvent } from '@/plugins/events/events/toast';
 import { EventBus } from '@/plugins/events';
 import { CompatibilityMapping, ComponentMapping } from '@/types/imports.d';
-import { ImportModel, ImportType, ProjectModel, ProjectPermissionsModel, ProjectType } from '@/plugins/api/api-core';
+import { ImportModel, ImportType, ItemType, ProjectModel, ProjectPermissionsModel } from '@/plugins/api/api-core';
 import ConfigTwitter from '@/components/imports/ConfigTwitter.vue';
 import ConfigJSONL from '@/components/imports/ConfigJSONL.vue';
 import ConfigRIS from '@/components/imports/ConfigRIS.vue';
@@ -248,7 +248,7 @@ export default {
       return undefined;
     },
     compatibleImportTypes() {
-      const projectType: ProjectType = this.currentProject.type;
+      const projectType: ItemType = this.currentProject.type;
       const compatibleTypes = projectTypeImportTypeCompatibility[projectType];
 
       return Object.fromEntries(
diff --git a/src/views/Projects/ProjectSettingsContainer.vue b/src/views/Projects/ProjectSettingsContainer.vue
new file mode 100644
index 0000000000000000000000000000000000000000..0f07ccd71fba5572a63a4e6804372453b2d32dd4
--- /dev/null
+++ b/src/views/Projects/ProjectSettingsContainer.vue
@@ -0,0 +1,28 @@
+<template>
+  <div>
+    <div v-if="projectPermissions.owner">
+      <router-view />
+    </div>
+    <div v-else>
+      Unfortunately, you don't have permission to access this page.
+    </div>
+  </div>
+</template>
+
+<script lang="ts">
+import { currentProjectStore } from '@/stores';
+import { ProjectPermissionsModel } from '@/plugins/api/api-core';
+
+export default {
+  name: 'ProjectSettingsContainer',
+  data() {
+    return {
+      projectPermissions: currentProjectStore.projectPermissions as ProjectPermissionsModel,
+    };
+  },
+};
+</script>
+
+<style scoped>
+
+</style>
diff --git a/src/views/Projects/ProjectSettingsView.vue b/src/views/Projects/ProjectSettingsView.vue
new file mode 100644
index 0000000000000000000000000000000000000000..2f579f2835701e761dd2a9650b1de403f09806cc
--- /dev/null
+++ b/src/views/Projects/ProjectSettingsView.vue
@@ -0,0 +1,14 @@
+<template>
+  settings
+</template>
+<script lang="ts">
+
+export default {
+  name: 'ProjectSettingsView',
+  data() {
+    return {
+      // pass
+    };
+  },
+};
+</script>