diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index ea8f3e20..7c377e6c 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,5 +1,3 @@ -// For format details, see https://aka.ms/devcontainer.json. For config options, see the -// README at: https://github.com/devcontainers/templates/tree/main/src/docker-existing-docker-compose { "name": "ztnet dev", // Update the 'dockerComposeFile' list if you have more compose files or use different names. @@ -35,7 +33,7 @@ "bourhaouta.tailwindshades", "Gruntfuggly.todo-tree", "yoavbls.pretty-ts-errors", - "rome.rome", + "biomejs.biome", "GitHub.copilot" ] } diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 7b59e591..370a756b 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,7 +1,7 @@ { "recommendations": [ "prisma.prisma", - "rome.rome", + "biomejs.biome", "bradlc.vscode-tailwindcss" ] } \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 73feec8a..424de89d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -63,9 +63,6 @@ ENV NODE_ENV production # Disable telemetry during runtime. ENV NEXT_TELEMETRY_DISABLED 1 -# adding internal url. https://github.com/sinamics/ztnet/issues/105 -ENV NEXTAUTH_URL_INTERNAL http://localhost:3000 - RUN addgroup --system --gid 1001 nodejs RUN adduser --system --uid 1001 nextjs RUN apt update && apt install -y curl sudo postgresql-client && apt clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* diff --git a/biome.json b/biome.json index 58fd3e59..2e7cca3e 100644 --- a/biome.json +++ b/biome.json @@ -6,7 +6,8 @@ "files": { "ignore": [ "**/*.js", - "install.ztnet/**/*" + "install.ztnet/**/*", + ".devcontainer/**/*" ] }, "formatter": { diff --git a/docs/ztnet/docs/Installation/docker-compose.md b/docs/ztnet/docs/Installation/docker-compose.md index 75d34b2d..2a905b0e 100644 --- a/docs/ztnet/docs/Installation/docker-compose.md +++ b/docs/ztnet/docs/Installation/docker-compose.md @@ -104,13 +104,16 @@ Please note that while admins have visibility over registered accounts, they **c ## Ztnet Environment Variables The following environment variables are available for configuration. They can be set in the `.env` file or passed directly to the docker-compose.yml file. -- **ZT_ADDR** zerotier controller address. Defaults to `http://zerotier:9993` for docker environment, and `http://127.0.0.1:9993` for standalone. -- **ZT_SECRET** zerotier controller secret. Defaults to the content of `/var/lib/zerotier-one/authtoken.secret`. -- **NEXT_PUBLIC_SITE_NAME** Site name. Defaults to `ZTNET`. -- **POSTGRES_HOST** Default: postgres -- **POSTGRES_PORT** Default: 5432 -- **POSTGRES_USER** Default: postgres -- **POSTGRES_PASSWORD** Default: postgres -- **POSTGRES_DB** Default: ztnet -- **NEXTAUTH_URL** Default: "http://localhost:3000" # Change `localhost` to your production domain when deploying. -- **NEXTAUTH_SECRET** Default: "random_secret", change this to a random string for security. \ No newline at end of file +```bash +ZT_ADDR # zerotier controller address. Defaults to `http://zerotier:9993` for docker environment, and `http://127.0.0.1:9993` for standalone. +ZT_SECRET #zerotier controller secret. Defaults to the content of `/var/lib/zerotier-one/authtoken.secret`. +NEXT_PUBLIC_SITE_NAME #Site name. Defaults to `ZTNET`. +POSTGRES_HOST #Default: postgres +POSTGRES_PORT #Default: 5432 +POSTGRES_USER #Default: postgres +POSTGRES_PASSWORD #Default: postgres +POSTGRES_DB #Default: ztnet +NEXTAUTH_URL #Default: "http://localhost:3000" # Change `localhost` to your production domain when deploying. +NEXTAUTH_URL_INTERNAL #Default: "http://localhost:3000" # Change `localhost` to your production domain when deploying. +NEXTAUTH_SECRET #Default: "random_secret", change this to a random string for security. +``` \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 62be00e9..9bf28618 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,6 +23,7 @@ "@trpc/next": "^10.37.1", "@trpc/react-query": "^10.37.1", "@trpc/server": "^10.37.1", + "@types/socket.io-client": "^3.0.0", "@uiw/codemirror-extensions-classname": "^4.21.7", "@uiw/codemirror-theme-okaidia": "^4.21.7", "@uiw/react-codemirror": "^4.21.7", @@ -36,9 +37,9 @@ "ip-address": "^8.1.0", "jsonwebtoken": "^9.0.1", "lru-cache": "^10.0.1", - "next": "13.4.10", - "next-auth": "4.22.1", - "next-intl": "2.19.0", + "next": "14.0.3", + "next-auth": "4.24.5", + "next-intl": "3.1.4", "next-themes": "^0.2.1", "nodemailer": "^6.9.4", "pug": "^3.0.2", @@ -49,6 +50,8 @@ "react-hot-toast": "^2.4.0", "react-timeago": "^7.1.0", "sharp": "0.32.3", + "socket.io": "^4.7.2", + "socket.io-client": "^4.7.2", "superjson": "1.9.1", "unique-names-generator": "^4.7.1", "unzipper": "^0.10.14", @@ -87,7 +90,7 @@ "ts-jest": "^29.1.0", "ts-node": "^10.9.1", "type-fest": "^4.2.0", - "typescript": "^5.1.6" + "typescript": "5.3.2" } }, "node_modules/@adobe/css-tools": { @@ -122,12 +125,12 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.4.tgz", + "integrity": "sha512-r1IONyb6Ia+jYR2vvIDhdWdlTGhqbBoFqLTQidzZ4kepUFH15ejXvFHxCVbtl7BOXIudsIubf4E81xeA3h3IXA==", "dev": true, "dependencies": { - "@babel/highlight": "^7.22.13", + "@babel/highlight": "^7.23.4", "chalk": "^2.4.2" }, "engines": { @@ -206,30 +209,30 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.2.tgz", - "integrity": "sha512-0S9TQMmDHlqAZ2ITT95irXKfxN9bncq8ZCoJhun3nHL/lLUxd2NKBJYoNGWH7S0hz6fRQwWlAWn/ILM0C70KZQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.3.tgz", + "integrity": "sha512-BmR4bWbDIoFJmJ9z2cZ8Gmm2MXgEDgjdWgpKmKWUt54UGFJdlj31ECtbaDvCG/qVdG3AQ1SfpZEs01lUFbzLOQ==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.2.tgz", - "integrity": "sha512-n7s51eWdaWZ3vGT2tD4T7J6eJs3QoBXydv7vkUM06Bf1cbVD2Kc2UrkzhiQwobfV7NwOnQXYL7UBJ5VPU+RGoQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.3.tgz", + "integrity": "sha512-Jg+msLuNuCJDyBvFv5+OKOUjWMZgd85bKjbICd3zWrKAo+bJ49HJufi7CQE0q0uR8NGyO6xkCACScNqyjHSZew==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", + "@babel/generator": "^7.23.3", "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-module-transforms": "^7.23.0", + "@babel/helper-module-transforms": "^7.23.3", "@babel/helpers": "^7.23.2", - "@babel/parser": "^7.23.0", + "@babel/parser": "^7.23.3", "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.2", - "@babel/types": "^7.23.0", + "@babel/traverse": "^7.23.3", + "@babel/types": "^7.23.3", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -245,12 +248,12 @@ } }, "node_modules/@babel/generator": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", - "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.4.tgz", + "integrity": "sha512-esuS49Cga3HcThFNebGhlgsrVLkvhqvYDTzgjfFFlHJcIfLe5jFmRRfCQ1KuBfc4Jrtn3ndLgKWAKjBE+IraYQ==", "dev": true, "dependencies": { - "@babel/types": "^7.23.0", + "@babel/types": "^7.23.4", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -331,9 +334,9 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz", - "integrity": "sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.22.20", @@ -383,9 +386,9 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", + "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", "engines": { "node": ">=6.9.0" } @@ -408,23 +411,23 @@ } }, "node_modules/@babel/helpers": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.2.tgz", - "integrity": "sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.4.tgz", + "integrity": "sha512-HfcMizYz10cr3h29VqyfGL6ZWIjTwWfvYBMsBVGwpcbhNGe3wQ1ZXZRPzZoAHhd9OqHadHqjQ89iVKINXnbzuw==", "dev": true, "dependencies": { "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.2", - "@babel/types": "^7.23.0" + "@babel/traverse": "^7.23.4", + "@babel/types": "^7.23.4" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", - "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", "dev": true, "dependencies": { "@babel/helper-validator-identifier": "^7.22.20", @@ -507,9 +510,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", - "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.4.tgz", + "integrity": "sha512-vf3Xna6UEprW+7t6EtOmFpHNAuxw3xqPZghy+brsnusscJRW5BMUzzHZc5ICjULee81WeUV2jjakG09MDglJXQ==", "bin": { "parser": "bin/babel-parser.js" }, @@ -578,9 +581,9 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", - "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz", + "integrity": "sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -680,9 +683,9 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz", - "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz", + "integrity": "sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -695,9 +698,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.2.tgz", - "integrity": "sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.4.tgz", + "integrity": "sha512-2Yv65nlWnWlSpe3fXEyX5i7fx5kIKo4Qbcj+hMO0odwaneFjfXw5fdum+4yL20O0QiaHpia0cYQ9xpNMqrBwHg==", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -720,19 +723,19 @@ } }, "node_modules/@babel/traverse": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", - "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.4.tgz", + "integrity": "sha512-IYM8wSUwunWTB6tFC2dkKZhxbIjHoWemdK+3f8/wq8aKhbUscxD5MX72ubd90fxvFknaLPeGw5ycU84V1obHJg==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", + "@babel/code-frame": "^7.23.4", + "@babel/generator": "^7.23.4", "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.0", - "@babel/types": "^7.23.0", + "@babel/parser": "^7.23.4", + "@babel/types": "^7.23.4", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -741,11 +744,11 @@ } }, "node_modules/@babel/types": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", - "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.4.tgz", + "integrity": "sha512-7uIFwVYpoplT5jp/kVv6EF93VaJ8H+Yn5IczYiaAi98ajzjfoZfslet/e0sLh+wVBjb2qqIut1b0S26VSafsSQ==", "dependencies": { - "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-string-parser": "^7.23.4", "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" }, @@ -881,9 +884,9 @@ } }, "node_modules/@codemirror/autocomplete": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.10.2.tgz", - "integrity": "sha512-3dCL7b0j2GdtZzWN5j7HDpRAJ26ip07R4NGYz7QYthIYMiX8I4E4TNrYcdTayPJGeVQtd/xe7lWU4XL7THFb/w==", + "version": "6.11.1", + "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.11.1.tgz", + "integrity": "sha512-L5UInv8Ffd6BPw0P3EF7JLYAMeEbclY7+6Q11REt8vhih8RuLreKtPy/xk8wPxs4EQgYqzI7cdgpiYwWlbS/ow==", "dependencies": { "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.0.0", @@ -898,9 +901,9 @@ } }, "node_modules/@codemirror/commands": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.3.0.tgz", - "integrity": "sha512-tFfcxRIlOWiQDFhjBSWJ10MxcvbCIsRr6V64SgrcaY0MwNk32cUOcCuNlWo8VjV4qRQCgNgUAnIeo0svkk4R5Q==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.3.1.tgz", + "integrity": "sha512-mgVour3mg9pnZUp53LzWQLPTRIBI3aZcoMJiJu6R0FadsLrydmMFxq/HMcI1zkElWWXcjaIZXemyog5IMKVIIA==", "dependencies": { "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.2.0", @@ -943,9 +946,9 @@ } }, "node_modules/@codemirror/lang-html": { - "version": "6.4.6", - "resolved": "https://registry.npmjs.org/@codemirror/lang-html/-/lang-html-6.4.6.tgz", - "integrity": "sha512-E4C8CVupBksXvgLSme/zv31x91g06eZHSph7NczVxZW+/K+3XgJGWNT//2WLzaKSBoxpAjaOi5ZnPU1SHhjh3A==", + "version": "6.4.7", + "resolved": "https://registry.npmjs.org/@codemirror/lang-html/-/lang-html-6.4.7.tgz", + "integrity": "sha512-y9hWSSO41XlcL4uYwWyk0lEgTHcelWWfRuqmvcAmxfCs0HNWZdriWo/EU43S63SxEZpc1Hd50Itw7ktfQvfkUg==", "dependencies": { "@codemirror/autocomplete": "^6.0.0", "@codemirror/lang-css": "^6.0.0", @@ -1002,9 +1005,9 @@ } }, "node_modules/@codemirror/lang-markdown": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/@codemirror/lang-markdown/-/lang-markdown-6.2.2.tgz", - "integrity": "sha512-wmwM9Y5n/e4ndU51KcYDaQnb9goYdhXjU71dDW9goOc1VUTIPph6WKAPdJ6BzC0ZFy+UTsDwTXGWSP370RH69Q==", + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/@codemirror/lang-markdown/-/lang-markdown-6.2.3.tgz", + "integrity": "sha512-wCewRLWpdefWi7uVkHIDiE8+45Fe4buvMDZkihqEom5uRUQrl76Zb13emjeK3W+8pcRgRfAmwelURBbxNEKCIg==", "dependencies": { "@codemirror/autocomplete": "^6.7.1", "@codemirror/lang-html": "^6.0.0", @@ -1106,9 +1109,9 @@ } }, "node_modules/@codemirror/language": { - "version": "6.9.2", - "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.9.2.tgz", - "integrity": "sha512-QGTQXSpAKDIzaSE96zNK1UfIUhPgkT1CLjh1N5qVzZuxgsEOhz5RqaN8QCIdyOQklGLx3MgHd9YrE3X3+Pl1ow==", + "version": "6.9.3", + "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.9.3.tgz", + "integrity": "sha512-qq48pYzoi6ldYWV/52+Z9Ou6QouVI+8YwvxFbUypI33NbjG2UeRHKENRyhwljTTiOqjQ33FjyZj6EREQ9apAOQ==", "dependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.0.0", @@ -1163,9 +1166,9 @@ } }, "node_modules/@codemirror/search": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.4.tgz", - "integrity": "sha512-YoTrvjv9e8EbPs58opjZKyJ3ewFrVSUzQ/4WXlULQLSDDr1nGPJ67mMXFNNVYwdFhybzhrzrtqgHmtpJwIF+8g==", + "version": "6.5.5", + "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.5.tgz", + "integrity": "sha512-PIEN3Ke1buPod2EHbJsoQwlbpkz30qGZKcnmH1eihq9+bPQx8gelauUwLYaY4vBOuBAuEhmpDLii4rj/uO0yMA==", "dependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.0.0", @@ -1173,9 +1176,9 @@ } }, "node_modules/@codemirror/state": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.3.1.tgz", - "integrity": "sha512-88e4HhMtKJyw6fKprGaN/yZfiaoGYOi2nM45YCUC6R/kex9sxFWBDGatS1vk4lMgnWmdIIB9tk8Gj1LmL8YfvA==" + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.3.2.tgz", + "integrity": "sha512-5jEikOfU0r9y+OTlZn5AEQB15mibu3deLBUp+GnLzVUNezEEuPt/JdSeniQNi+0YviblAvOPO2JQAlgJ3SYYaA==" }, "node_modules/@codemirror/theme-one-dark": { "version": "6.1.2", @@ -1189,9 +1192,9 @@ } }, "node_modules/@codemirror/view": { - "version": "6.21.4", - "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.21.4.tgz", - "integrity": "sha512-WKVZ7nvN0lwWPfAf05WxWqTpwjC8YN3q5goj3CsSig7//DD81LULgOx3nBegqpqP0iygBqRmW8z0KSc2QTAdAg==", + "version": "6.22.1", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.22.1.tgz", + "integrity": "sha512-38BRn1nPqZqiHbmWfI8zri23IbRVbmSpSmh1E/Ysvc+lIGGdBC17K8zlK7ZU6fhfy9x4De9Zyj5JQqScPq5DkA==", "dependencies": { "@codemirror/state": "^6.1.4", "style-mod": "^4.1.0", @@ -1221,9 +1224,9 @@ } }, "node_modules/@faker-js/faker": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-8.2.0.tgz", - "integrity": "sha512-VacmzZqVxdWdf9y64lDOMZNDMM/FQdtM9IsaOPKOm2suYwEatb8VkdHqOzXcDnZbk7YDE2BmsJmy/2Hmkn563g==", + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-8.3.1.tgz", + "integrity": "sha512-FdgpFxY6V6rLZE9mmIBb9hM0xpfvQOSNOLnzolzKwsE1DH+gC7lEKV1p1IbR0lAYyvYd5a4u3qWJzowUkw1bIw==", "funding": [ { "type": "opencollective", @@ -1236,18 +1239,18 @@ } }, "node_modules/@formatjs/ecma402-abstract": { - "version": "1.17.2", - "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.17.2.tgz", - "integrity": "sha512-k2mTh0m+IV1HRdU0xXM617tSQTi53tVR2muvYOsBeYcUgEAyxV1FOC7Qj279th3fBVQ+Dj6muvNJZcHSPNdbKg==", + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.18.0.tgz", + "integrity": "sha512-PEVLoa3zBevWSCZzPIM/lvPCi8P5l4G+NXQMc/CjEiaCWgyHieUoo0nM7Bs0n/NbuQ6JpXEolivQ9pKSBHaDlA==", "dependencies": { - "@formatjs/intl-localematcher": "0.4.2", + "@formatjs/intl-localematcher": "0.5.2", "tslib": "^2.4.0" } }, "node_modules/@formatjs/ecma402-abstract/node_modules/@formatjs/intl-localematcher": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.4.2.tgz", - "integrity": "sha512-BGdtJFmaNJy5An/Zan4OId/yR9Ih1OojFjcduX/xOvq798OgWSyDtd6Qd5jqJXwJs1ipe4Fxu9+cshic5Ox2tA==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.5.2.tgz", + "integrity": "sha512-txaaE2fiBMagLrR4jYhxzFO6wEdEG4TPMqrzBAcbr4HFUYzH/YC+lg6OIzKCHm8WgDdyQevxbAAV1OgcXctuGw==", "dependencies": { "tslib": "^2.4.0" } @@ -1755,9 +1758,9 @@ } }, "node_modules/@lezer/common": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.1.0.tgz", - "integrity": "sha512-XPIN3cYDXsoJI/oDWoR2tD++juVrhgIago9xyKhZ7IhGlzdDM9QgC8D8saKNCz5pindGcznFr2HBSsEQSWnSjw==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.1.1.tgz", + "integrity": "sha512-aAPB9YbvZHqAW+bIwiuuTDGB4DG0sYNRObGLxud8cW7osw1ZQxfDuTZ8KQiqfZ0QJGcR34CvpTMDXEyo/+Htgg==" }, "node_modules/@lezer/cpp": { "version": "1.1.1", @@ -1769,26 +1772,26 @@ } }, "node_modules/@lezer/css": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@lezer/css/-/css-1.1.3.tgz", - "integrity": "sha512-SjSM4pkQnQdJDVc80LYzEaMiNy9txsFbI7HsMgeVF28NdLaAdHNtQ+kB/QqDUzRBV/75NTXjJ/R5IdC8QQGxMg==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@lezer/css/-/css-1.1.4.tgz", + "integrity": "sha512-CuUwjidrU7FOBokqASRJc72SmJ9g1PsHXDOWMoKg4md6+2u/Zxzwx5YsYrAFxRDsLrjLlsIyEF1rZHK3gFEJbw==", "dependencies": { "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.0.0" } }, "node_modules/@lezer/highlight": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.1.6.tgz", - "integrity": "sha512-cmSJYa2us+r3SePpRCjN5ymCqCPv+zyXmDl0ciWtVaNiORT/MxM7ZgOMQZADD0o51qOaOg24qc/zBViOIwAjJg==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.0.tgz", + "integrity": "sha512-WrS5Mw51sGrpqjlh3d4/fOwpEV2Hd3YOkp9DBt4k8XZQcoTHZFB7sx030A6OcahF4J1nDQAa3jXlTVVYH50IFA==", "dependencies": { "@lezer/common": "^1.0.0" } }, "node_modules/@lezer/html": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@lezer/html/-/html-1.3.6.tgz", - "integrity": "sha512-Kk9HJARZTc0bAnMQUqbtuhFVsB4AnteR2BFUWfZV7L/x1H0aAKz6YabrfJ2gk/BEgjh9L3hg5O4y2IDZRBdzuQ==", + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/@lezer/html/-/html-1.3.7.tgz", + "integrity": "sha512-Wo+rZ5UjLP0VqUTyXjzgmTYRW5bvTJUFn4Uw0K3HCQjX2/+f+zRo9GLN5BCAojwHQISPvaQk8BWSv2SSKx/UcQ==", "dependencies": { "@lezer/common": "^1.0.0", "@lezer/highlight": "^1.0.0", @@ -1796,9 +1799,9 @@ } }, "node_modules/@lezer/java": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@lezer/java/-/java-1.0.4.tgz", - "integrity": "sha512-POc53LHf2AuNeRXjqZbXNu88GKj0KZTjjSx0L7tYeXlrEHF+3NAQx+dEwKVuCbkl0ZMtpRy2VsDYOV7KKV0oyg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@lezer/java/-/java-1.1.0.tgz", + "integrity": "sha512-RmBS+P9LJ4P9SU7ZewahMkBUNOEz1zQTMOKLq8OEa7ge8FZxz7mKjoEIGewRSn9kom1z5GKQjtxNE++m6u8SYw==", "dependencies": { "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.0.0" @@ -1823,17 +1826,17 @@ } }, "node_modules/@lezer/lr": { - "version": "1.3.13", - "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.3.13.tgz", - "integrity": "sha512-RLAbau/4uSzKgIKj96mI5WUtG1qtiR0Frn0Ei9zhPj8YOkHM+1Bb8SgdVvmR/aWJCFIzjo2KFnDiRZ75Xf5NdQ==", + "version": "1.3.14", + "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.3.14.tgz", + "integrity": "sha512-z5mY4LStlA3yL7aHT/rqgG614cfcvklS+8oFRFBYrs4YaWLJyKKM4+nN6KopToX0o9Hj6zmH6M5kinOYuy06ug==", "dependencies": { "@lezer/common": "^1.0.0" } }, "node_modules/@lezer/markdown": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@lezer/markdown/-/markdown-1.1.0.tgz", - "integrity": "sha512-JYOI6Lkqbl83semCANkO3CKbKc0pONwinyagBufWBm+k4yhIcqfCF8B8fpEpvJLmIy7CAfwiq7dQ/PzUZA340g==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@lezer/markdown/-/markdown-1.1.1.tgz", + "integrity": "sha512-kmxvLnXCogUx2mexslWwVME1W2GQP76pwUODcFXLsuubuK41TcEJhKRm2FTKugNfEkUIspJNq9+jNo6b7dxVLA==", "dependencies": { "@lezer/common": "^1.0.0", "@lezer/highlight": "^1.0.0" @@ -1894,14 +1897,14 @@ } }, "node_modules/@next/env": { - "version": "13.4.10", - "resolved": "https://registry.npmjs.org/@next/env/-/env-13.4.10.tgz", - "integrity": "sha512-3G1yD/XKTSLdihyDSa8JEsaWOELY+OWe08o0LUYzfuHp1zHDA8SObQlzKt+v+wrkkPcnPweoLH1ImZeUa0A1NQ==" + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/@next/env/-/env-14.0.3.tgz", + "integrity": "sha512-7xRqh9nMvP5xrW4/+L0jgRRX+HoNRGnfJpD+5Wq6/13j3dsdzxO3BCXn7D3hMqsDb+vjZnJq+vI7+EtgrYZTeA==" }, "node_modules/@next/swc-darwin-arm64": { - "version": "13.4.10", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.10.tgz", - "integrity": "sha512-4bsdfKmmg7mgFGph0UorD1xWfZ5jZEw4kKRHYEeTK9bT1QnMbPVPlVXQRIiFPrhoDQnZUoa6duuPUJIEGLV1Jg==", + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.0.3.tgz", + "integrity": "sha512-64JbSvi3nbbcEtyitNn2LEDS/hcleAFpHdykpcnrstITFlzFgB/bW0ER5/SJJwUPj+ZPY+z3e+1jAfcczRLVGw==", "cpu": [ "arm64" ], @@ -1914,9 +1917,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "13.4.10", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.10.tgz", - "integrity": "sha512-ngXhUBbcZIWZWqNbQSNxQrB9T1V+wgfCzAor2olYuo/YpaL6mUYNUEgeBMhr8qwV0ARSgKaOp35lRvB7EmCRBg==", + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.0.3.tgz", + "integrity": "sha512-RkTf+KbAD0SgYdVn1XzqE/+sIxYGB7NLMZRn9I4Z24afrhUpVJx6L8hsRnIwxz3ERE2NFURNliPjJ2QNfnWicQ==", "cpu": [ "x64" ], @@ -1929,9 +1932,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "13.4.10", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.10.tgz", - "integrity": "sha512-SjCZZCOmHD4uyM75MVArSAmF5Y+IJSGroPRj2v9/jnBT36SYFTORN8Ag/lhw81W9EeexKY/CUg2e9mdebZOwsg==", + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.0.3.tgz", + "integrity": "sha512-3tBWGgz7M9RKLO6sPWC6c4pAw4geujSwQ7q7Si4d6bo0l6cLs4tmO+lnSwFp1Tm3lxwfMk0SgkJT7EdwYSJvcg==", "cpu": [ "arm64" ], @@ -1944,9 +1947,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "13.4.10", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.10.tgz", - "integrity": "sha512-F+VlcWijX5qteoYIOxNiBbNE8ruaWuRlcYyIRK10CugqI/BIeCDzEDyrHIHY8AWwbkTwe6GRHabMdE688Rqq4Q==", + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.0.3.tgz", + "integrity": "sha512-v0v8Kb8j8T23jvVUWZeA2D8+izWspeyeDGNaT2/mTHWp7+37fiNfL8bmBWiOmeumXkacM/AB0XOUQvEbncSnHA==", "cpu": [ "arm64" ], @@ -1959,9 +1962,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "13.4.10", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.10.tgz", - "integrity": "sha512-WDv1YtAV07nhfy3i1visr5p/tjiH6CeXp4wX78lzP1jI07t4PnHHG1WEDFOduXh3WT4hG6yN82EQBQHDi7hBrQ==", + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.0.3.tgz", + "integrity": "sha512-VM1aE1tJKLBwMGtyBR21yy+STfl0MapMQnNrXkxeyLs0GFv/kZqXS5Jw/TQ3TSUnbv0QPDf/X8sDXuMtSgG6eg==", "cpu": [ "x64" ], @@ -1974,9 +1977,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "13.4.10", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.10.tgz", - "integrity": "sha512-zFkzqc737xr6qoBgDa3AwC7jPQzGLjDlkNmt/ljvQJ/Veri5ECdHjZCUuiTUfVjshNIIpki6FuP0RaQYK9iCRg==", + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.0.3.tgz", + "integrity": "sha512-64EnmKy18MYFL5CzLaSuUn561hbO1Gk16jM/KHznYP3iCIfF9e3yULtHaMy0D8zbHfxset9LTOv6cuYKJgcOxg==", "cpu": [ "x64" ], @@ -1989,9 +1992,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "13.4.10", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.10.tgz", - "integrity": "sha512-IboRS8IWz5mWfnjAdCekkl8s0B7ijpWeDwK2O8CdgZkoCDY0ZQHBSGiJ2KViAG6+BJVfLvcP+a2fh6cdyBr9QQ==", + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.0.3.tgz", + "integrity": "sha512-WRDp8QrmsL1bbGtsh5GqQ/KWulmrnMBgbnb+59qNTW1kVi1nG/2ndZLkcbs2GX7NpFLlToLRMWSQXmPzQm4tog==", "cpu": [ "arm64" ], @@ -2004,9 +2007,9 @@ } }, "node_modules/@next/swc-win32-ia32-msvc": { - "version": "13.4.10", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.10.tgz", - "integrity": "sha512-bSA+4j8jY4EEiwD/M2bol4uVEu1lBlgsGdvM+mmBm/BbqofNBfaZ2qwSbwE2OwbAmzNdVJRFRXQZ0dkjopTRaQ==", + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.0.3.tgz", + "integrity": "sha512-EKffQeqCrj+t6qFFhIFTRoqb2QwX1mU7iTOvMyLbYw3QtqTw9sMwjykyiMlZlrfm2a4fA84+/aeW+PMg1MjuTg==", "cpu": [ "ia32" ], @@ -2019,9 +2022,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "13.4.10", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.10.tgz", - "integrity": "sha512-g2+tU63yTWmcVQKDGY0MV1PjjqgZtwM4rB1oVVi/v0brdZAcrcTV+04agKzWtvWroyFz6IqtT0MoZJA7PNyLVw==", + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.0.3.tgz", + "integrity": "sha512-ERhKPSJ1vQrPiwrs15Pjz/rvDHZmkmvbf/BjPN/UCOI++ODftT0GtasDPi0j+y6PPJi5HsXw+dpRaXUaw4vjuQ==", "cpu": [ "x64" ], @@ -2105,12 +2108,12 @@ } }, "node_modules/@prisma/client": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.5.2.tgz", - "integrity": "sha512-54XkqR8M+fxbzYqe+bIXimYnkkcGqgOh0dn0yWtIk6CQT4IUCAvNFNcQZwk2KqaLU+/1PHTSWrcHtx4XjluR5w==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.6.0.tgz", + "integrity": "sha512-mUDefQFa1wWqk4+JhKPYq8BdVoFk9NFMBXUI8jAkBfQTtgx8WPx02U2HB/XbAz3GSUJpeJOKJQtNvaAIDs6sug==", "hasInstallScript": true, "dependencies": { - "@prisma/engines-version": "5.5.1-1.aebc046ce8b88ebbcb45efe31cbe7d06fd6abc0a" + "@prisma/engines-version": "5.6.0-32.e95e739751f42d8ca026f6b910f5a2dc5adeaeee" }, "engines": { "node": ">=16.13" @@ -2125,16 +2128,16 @@ } }, "node_modules/@prisma/engines": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.5.2.tgz", - "integrity": "sha512-Be5hoNF8k+lkB3uEMiCHbhbfF6aj1GnrTBnn5iYFT7GEr3TsOEp1soviEcBR0tYCgHbxjcIxJMhdbvxALJhAqg==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.6.0.tgz", + "integrity": "sha512-Mt2q+GNJpU2vFn6kif24oRSBQv1KOkYaterQsi0k2/lA+dLvhRX6Lm26gon6PYHwUM8/h8KRgXIUMU0PCLB6bw==", "devOptional": true, "hasInstallScript": true }, "node_modules/@prisma/engines-version": { - "version": "5.5.1-1.aebc046ce8b88ebbcb45efe31cbe7d06fd6abc0a", - "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.5.1-1.aebc046ce8b88ebbcb45efe31cbe7d06fd6abc0a.tgz", - "integrity": "sha512-O+qHFnZvAyOFk1tUco2/VdiqS0ym42a3+6CYLScllmnpbyiTplgyLt2rK/B9BTjYkSHjrgMhkG47S0oqzdIckA==" + "version": "5.6.0-32.e95e739751f42d8ca026f6b910f5a2dc5adeaeee", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.6.0-32.e95e739751f42d8ca026f6b910f5a2dc5adeaeee.tgz", + "integrity": "sha512-UoFgbV1awGL/3wXuUK3GDaX2SolqczeeJ5b4FVec9tzeGbSWJboPSbT0psSrmgYAKiKnkOPFSLlH6+b+IyOwAw==" }, "node_modules/@sinclair/typebox": { "version": "0.27.8", @@ -2160,10 +2163,15 @@ "@sinonjs/commons": "^3.0.0" } }, + "node_modules/@socket.io/component-emitter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", + "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" + }, "node_modules/@swc/helpers": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.1.tgz", - "integrity": "sha512-sJ902EfIzn1Fa+qYmjdQqh8tPsoxyBz+8yBKC2HKUxyezKJFwPGOn7pv4WY6QuQW//ySQi5lJjA/ZT9sNWWNTg==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.2.tgz", + "integrity": "sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw==", "dependencies": { "tslib": "^2.4.0" } @@ -2334,9 +2342,9 @@ } }, "node_modules/@testing-library/react": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-14.0.0.tgz", - "integrity": "sha512-S04gSNJbYE30TlIMLTzv6QCTzt9AqIF5y6s6SzVFILNcNvbV/jU96GeiTPillGQo+Ny64M/5PV7klNYYgv5Dfg==", + "version": "14.1.2", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-14.1.2.tgz", + "integrity": "sha512-z4p7DVBTPjKM5qDZ0t5ZjzkpSNb+fZy1u6bzO7kk8oeGagpPCAtgh4cx1syrfp7a+QWkM021jGqjJaxJJnXAZg==", "dev": true, "dependencies": { "@babel/runtime": "^7.12.5", @@ -2374,20 +2382,20 @@ } }, "node_modules/@trpc/client": { - "version": "10.43.0", - "resolved": "https://registry.npmjs.org/@trpc/client/-/client-10.43.0.tgz", - "integrity": "sha512-8LbSpPHmIseb/Ke+GzL45y0itkKunGQWfxqHf2uy69RSRvER0vj+Gu67L8YD86FBgc/nsX/6GBuJiUet5lIDIw==", + "version": "10.44.1", + "resolved": "https://registry.npmjs.org/@trpc/client/-/client-10.44.1.tgz", + "integrity": "sha512-vTWsykNcgz1LnwePVl2fKZnhvzP9N3GaaLYPkfGINo314ZOS0OBqe9x0ytB2LLUnRVTAAZ2WoONzARd8nHiqrA==", "funding": [ "https://trpc.io/sponsor" ], "peerDependencies": { - "@trpc/server": "10.43.0" + "@trpc/server": "10.44.1" } }, "node_modules/@trpc/next": { - "version": "10.43.0", - "resolved": "https://registry.npmjs.org/@trpc/next/-/next-10.43.0.tgz", - "integrity": "sha512-yakRlkvf6+uc3igYZi8nPkppJ8jFaCyd/7kvSckgsdLC8ofM+N9rrBkfqdfS5Pd53awkK/MMK8js9v/vabKb6A==", + "version": "10.44.1", + "resolved": "https://registry.npmjs.org/@trpc/next/-/next-10.44.1.tgz", + "integrity": "sha512-ez2oYUzmaQ+pGch627sRBfeEk3h+UIwNicR8WjTAM54TPcdP5W9ZyWCyO5HZTEfjHgGixYM4tCIxewdKOWY9yA==", "funding": [ "https://trpc.io/sponsor" ], @@ -2396,36 +2404,39 @@ }, "peerDependencies": { "@tanstack/react-query": "^4.18.0", - "@trpc/client": "10.43.0", - "@trpc/react-query": "10.43.0", - "@trpc/server": "10.43.0", + "@trpc/client": "10.44.1", + "@trpc/react-query": "10.44.1", + "@trpc/server": "10.44.1", "next": "*", "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "node_modules/@trpc/react-query": { - "version": "10.43.0", - "resolved": "https://registry.npmjs.org/@trpc/react-query/-/react-query-10.43.0.tgz", - "integrity": "sha512-5+pBnnV9QqnwpO5Li9T60hXHylV1USEjFkRjrnd7mJul/t2dKxs5ouv+YDRnOJ36oD9wDki5lBGk2sOgFrzGUw==", + "version": "10.44.1", + "resolved": "https://registry.npmjs.org/@trpc/react-query/-/react-query-10.44.1.tgz", + "integrity": "sha512-Sgi/v0YtdunOXjBRi7om9gILGkOCFYXPzn5KqLuEHiZw5dr5w4qGHFwCeMAvndZxmwfblJrl1tk2AznmsVu8MA==", "funding": [ "https://trpc.io/sponsor" ], "peerDependencies": { "@tanstack/react-query": "^4.18.0", - "@trpc/client": "10.43.0", - "@trpc/server": "10.43.0", + "@trpc/client": "10.44.1", + "@trpc/server": "10.44.1", "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "node_modules/@trpc/server": { - "version": "10.43.0", - "resolved": "https://registry.npmjs.org/@trpc/server/-/server-10.43.0.tgz", - "integrity": "sha512-1/h9KCPkTNNmpN5VKfKO4kPcl/W4Y9VQla4YGg4pydSh/+4b//0IPfvk3Oz4tz/tvWyAUlBKkBVhD3GfDLcAQA==", + "version": "10.44.1", + "resolved": "https://registry.npmjs.org/@trpc/server/-/server-10.44.1.tgz", + "integrity": "sha512-mF7B+K6LjuboX8I1RZgKE5GA/fJhsJ8tKGK2UBt3Bwik7hepEPb4NJgNr7vO6BK5IYwPdBLRLTctRw6XZx0sRg==", "funding": [ "https://trpc.io/sponsor" - ] + ], + "engines": { + "node": ">=18.0.0" + } }, "node_modules/@tsconfig/node10": { "version": "1.0.9", @@ -2461,15 +2472,15 @@ } }, "node_modules/@types/aria-query": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.3.tgz", - "integrity": "sha512-0Z6Tr7wjKJIk4OUEjVUQMtyunLDy339vcMaj38Kpj6jM2OE1p3S4kXExKZ7a3uXQAPCoy3sbrP1wibDKaf39oA==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", "dev": true }, "node_modules/@types/babel__core": { - "version": "7.20.3", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.3.tgz", - "integrity": "sha512-54fjTSeSHwfan8AyHWrKbfBWiEUrNTZsUwPTDSNaaP1QDQIZbeNUg3a59E9D+375MzUw/x1vx2/0F5LBz+AeYA==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", "dev": true, "dependencies": { "@babel/parser": "^7.20.7", @@ -2480,18 +2491,18 @@ } }, "node_modules/@types/babel__generator": { - "version": "7.6.6", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.6.tgz", - "integrity": "sha512-66BXMKb/sUWbMdBNdMvajU7i/44RkrA3z/Yt1c7R5xejt8qh84iU54yUWCtm0QwGJlDcf/gg4zd/x4mpLAlb/w==", + "version": "7.6.7", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.7.tgz", + "integrity": "sha512-6Sfsq+EaaLrw4RmdFWE9Onp63TOUue71AWb4Gpa6JxzgTYtimbM086WnYTy2U67AofR++QKCo08ZP6pwx8YFHQ==", "dev": true, "dependencies": { "@babel/types": "^7.0.0" } }, "node_modules/@types/babel__template": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.3.tgz", - "integrity": "sha512-ciwyCLeuRfxboZ4isgdNZi/tkt06m8Tw6uGbBSBgWrnnZGNXiEyM27xc/PjXGQLqlZ6ylbgHMnm7ccF9tCkOeQ==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", "dev": true, "dependencies": { "@babel/parser": "^7.1.0", @@ -2499,72 +2510,85 @@ } }, "node_modules/@types/babel__traverse": { - "version": "7.20.3", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.3.tgz", - "integrity": "sha512-Lsh766rGEFbaxMIDH7Qa+Yha8cMVI3qAK6CHt3OR0YfxOIn5Z54iHiyDRycHrBqeIiqGa20Kpsv1cavfBKkRSw==", + "version": "7.20.4", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.4.tgz", + "integrity": "sha512-mSM/iKUk5fDDrEV/e83qY+Cr3I1+Q3qqTuEn++HAWYjEa1+NxZr6CNrcJGf2ZTnq4HoFGC3zaTPZTobCzCFukA==", "dev": true, "dependencies": { "@babel/types": "^7.20.7" } }, "node_modules/@types/bcryptjs": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/@types/bcryptjs/-/bcryptjs-2.4.5.tgz", - "integrity": "sha512-tOF6TivOIvq+TWQm78335CMdyVJhpBG3NUdWQDAp95ax4E2rSKbws/ELHLk5EBoucwx/tHt3/hhLOHwWJgVrSw==", + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/@types/bcryptjs/-/bcryptjs-2.4.6.tgz", + "integrity": "sha512-9xlo6R2qDs5uixm0bcIqCeMCE6HiQsIyel9KQySStiyqNl2tnj2mP3DX1Nf56MD6KMenNNlBBsy3LJ7gUEQPXQ==", "dev": true }, + "node_modules/@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" + }, + "node_modules/@types/cors": { + "version": "2.8.17", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", + "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/ejs": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/@types/ejs/-/ejs-3.1.4.tgz", - "integrity": "sha512-fnM/NjByiWdSRJRrmGxgqOSAnmOnsvX1QcNYk5TVyIIj+7ZqOKMb9gQa4OIl/lil2w/8TiTWV+nz3q8yqxez/w==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@types/ejs/-/ejs-3.1.5.tgz", + "integrity": "sha512-nv+GSx77ZtXiJzwKdsASqi+YQ5Z7vwHsTP0JY2SiQgjGckkBRKZnk8nIM+7oUZ1VCtuTz0+By4qVR7fqzp/Dfg==", "dev": true }, "node_modules/@types/formidable": { - "version": "3.4.4", - "resolved": "https://registry.npmjs.org/@types/formidable/-/formidable-3.4.4.tgz", - "integrity": "sha512-0yRhMir7fdWIGfiCoYcqF6fQ2NXpb/0WwWQzg6n+K4IEIeqDVDDiDZfgfLJpi1Tbj8nvVKOAcyLVKAT3f0ZTiw==", + "version": "3.4.5", + "resolved": "https://registry.npmjs.org/@types/formidable/-/formidable-3.4.5.tgz", + "integrity": "sha512-s7YPsNVfnsng5L8sKnG/Gbb2tiwwJTY1conOkJzTMRvJAlLFW1nEua+ADsJQu8N1c0oTHx9+d5nqg10WuT9gHQ==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/graceful-fs": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.8.tgz", - "integrity": "sha512-NhRH7YzWq8WiNKVavKPBmtLYZHxNY19Hh+az28O/phfp68CF45pMFud+ZzJ8ewnxnC5smIdF3dqFeiSUQ5I+pw==", + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", - "integrity": "sha512-zONci81DZYCZjiLe0r6equvZut0b+dBRPBN5kBDjsONnutYNtJMoWQ9uR2RkL1gLG9NMTzvf+29e5RFfPbeKhQ==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", "dev": true }, "node_modules/@types/istanbul-lib-report": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.2.tgz", - "integrity": "sha512-8toY6FgdltSdONav1XtUHl4LN1yTmLza+EuDazb/fEmRNCwjyqNVIQWs2IfC74IqjHkREs/nQ2FWq5kZU9IC0w==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", "dev": true, "dependencies": { "@types/istanbul-lib-coverage": "*" } }, "node_modules/@types/istanbul-reports": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.3.tgz", - "integrity": "sha512-1nESsePMBlf0RPRffLZi5ujYh7IH1BWL4y9pr+Bn3cJBdxz+RTP8bUFljLz9HvzhhOSWKdyBZ4DIivdL6rvgZg==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", "dev": true, "dependencies": { "@types/istanbul-lib-report": "*" } }, "node_modules/@types/jest": { - "version": "29.5.6", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.6.tgz", - "integrity": "sha512-/t9NnzkOpXb4Nfvg17ieHE6EeSjDS2SGSpNYfoLbUAeL/EOueU/RSdOWFpfQTXBEM7BguYW1XQ0EbM+6RlIh6w==", + "version": "29.5.10", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.10.tgz", + "integrity": "sha512-tE4yxKEphEyxj9s4inideLHktW/x6DwesIwWZ9NN1FKf9zbJYsnhBoA9vrHA/IuIOKwPa5PcFBNV4lpMIOEzyQ==", "dev": true, "dependencies": { "expect": "^29.0.0", @@ -2621,9 +2645,9 @@ "dev": true }, "node_modules/@types/jsonwebtoken": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.4.tgz", - "integrity": "sha512-8UYapdmR0QlxgvJmyE8lP7guxD0UGVMfknsdtCFZh4ovShdBl3iOI4zdvqBHrB/IS+xUj3PSx73Qkey1fhWz+g==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.5.tgz", + "integrity": "sha512-VRLSGzik+Unrup6BsouBeHsf4d1hOEgYWTm/7Nmw1sXoN1+tRly/Gy/po3yeahnP4jfnQWWAhQAqcNfH7ngOkA==", "dev": true, "dependencies": { "@types/node": "*" @@ -2640,38 +2664,37 @@ } }, "node_modules/@types/luxon": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-3.3.3.tgz", - "integrity": "sha512-/BJF3NT0pRMuxrenr42emRUF67sXwcZCd+S1ksG/Fcf9O7C3kKCY4uJSbKBE4KDUIYr3WMsvfmWD8hRjXExBJQ==" + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-3.3.5.tgz", + "integrity": "sha512-1cyf6Ge/94zlaWIZA2ei1pE6SZ8xpad2hXaYa5JEFiaUH0YS494CZwyi4MXNpXD9oEuv6ZH0Bmh0e7F9sPhmZA==" }, "node_modules/@types/node": { - "version": "18.18.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.7.tgz", - "integrity": "sha512-bw+lEsxis6eqJYW8Ql6+yTqkE6RuFtsQPSe5JxXbqYRFQEER5aJA9a5UH9igqDWm3X4iLHIKOHlnAXLM4mi7uQ==", - "dev": true, + "version": "18.18.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.13.tgz", + "integrity": "sha512-vXYZGRrSCreZmq1rEjMRLXJhiy8MrIeVasx+PCVlP414N7CJLHnMf+juVvjdprHyH+XRy3zKZLHeNueOpJCn0g==", "dependencies": { "undici-types": "~5.26.4" } }, "node_modules/@types/nodemailer": { - "version": "6.4.13", - "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.13.tgz", - "integrity": "sha512-889Vq/77eEpidCwh52sVWpbnqQmIwL8yVBekNbrztVEaWKOCRH3Eq6hjIJh1jwsGDEAJEH0RR+YhpH9mfELLKA==", + "version": "6.4.14", + "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.14.tgz", + "integrity": "sha512-fUWthHO9k9DSdPCSPRqcu6TWhYyxTBg382vlNIttSe9M7XfsT06y0f24KHXtbnijPGGRIcVvdKHTNikOI6qiHA==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/prop-types": { - "version": "15.7.9", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.9.tgz", - "integrity": "sha512-n1yyPsugYNSmHgxDFjicaI2+gCNjsBck8UX9kuofAKlc0h1bL+20oSF72KeNaW2DUlesbEVCFgyV2dPGTiY42g==", + "version": "15.7.11", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz", + "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==", "devOptional": true }, "node_modules/@types/react": { - "version": "18.2.33", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.33.tgz", - "integrity": "sha512-v+I7S+hu3PIBoVkKGpSYYpiBT1ijqEzWpzQD62/jm4K74hPpSP7FF9BnKG6+fg2+62weJYkkBWDJlZt5JO/9hg==", + "version": "18.2.39", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.39.tgz", + "integrity": "sha512-Oiw+ppED6IremMInLV4HXGbfbG6GyziY3kqAwJYOR0PNbkYDmLWQA3a95EhdSmamsvbkJN96ZNN+YD+fGjzSBA==", "devOptional": true, "dependencies": { "@types/prop-types": "*", @@ -2680,33 +2703,42 @@ } }, "node_modules/@types/react-dom": { - "version": "18.2.14", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.14.tgz", - "integrity": "sha512-V835xgdSVmyQmI1KLV2BEIUgqEuinxp9O4G6g3FqO/SqLac049E53aysv0oEFD2kHfejeKU+ZqL2bcFWj9gLAQ==", + "version": "18.2.17", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.17.tgz", + "integrity": "sha512-rvrT/M7Df5eykWFxn6MYt5Pem/Dbyc1N8Y0S9Mrkw2WFCRiqUgw9P7ul2NpwsXCSM1DVdENzdG9J5SreqfAIWg==", "dev": true, "dependencies": { "@types/react": "*" } }, "node_modules/@types/readdir-glob": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@types/readdir-glob/-/readdir-glob-1.1.3.tgz", - "integrity": "sha512-trCChHpWDGCJCUPJRwD62eapW4KOru6h4S7n9KUIESaxhyBM/2Jh20P3XrFRQQ6Df78E/rq2DbUCVZlI8CXPnA==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@types/readdir-glob/-/readdir-glob-1.1.5.tgz", + "integrity": "sha512-raiuEPUYqXu+nvtY2Pe8s8FEmZ3x5yAH4VkLdihcPdalvsHltomrRC9BzuStrJ9yk06470hS0Crw0f1pXqD+Hg==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/scheduler": { - "version": "0.16.5", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.5.tgz", - "integrity": "sha512-s/FPdYRmZR8SjLWGMCuax7r3qCWQw9QKHzXVukAuuIJkXkDRwp+Pu5LMIVFi0Fxbav35WURicYr8u1QsoybnQw==", + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz", + "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==", "devOptional": true }, + "node_modules/@types/socket.io-client": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/socket.io-client/-/socket.io-client-3.0.0.tgz", + "integrity": "sha512-s+IPvFoEIjKA3RdJz/Z2dGR4gLgysKi8owcnrVwNjgvc01Lk68LJDDsG2GRqegFITcxmvCMYM7bhMpwEMlHmDg==", + "deprecated": "This is a stub types definition. socket.io-client provides its own type definitions, so you do not need this installed.", + "dependencies": { + "socket.io-client": "*" + } + }, "node_modules/@types/stack-utils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.2.tgz", - "integrity": "sha512-g7CK9nHdwjK2n0ymT2CW698FuWJRIx+RP6embAzZ2Qi8/ilIrA1Imt2LVSeHUzKvpoi7BhmmQcXz95eS0f2JXw==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", "dev": true }, "node_modules/@types/testing-library__jest-dom": { @@ -2719,39 +2751,39 @@ } }, "node_modules/@types/tough-cookie": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.4.tgz", - "integrity": "sha512-95Sfz4nvMAb0Nl9DTxN3j64adfwfbBPEYq14VN7zT5J5O2M9V6iZMIIQU1U+pJyl9agHYHNCqhCXgyEtIRRa5A==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", + "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", "dev": true }, "node_modules/@types/unzipper": { - "version": "0.10.8", - "resolved": "https://registry.npmjs.org/@types/unzipper/-/unzipper-0.10.8.tgz", - "integrity": "sha512-Cior/4Y78R1ZVF6tnWEHWIkAMDqKxU5pPCbaC62826oEfchPGg90fKdi3sLZ2D7oB7GrFu3+PW2elEMBOtd27w==", + "version": "0.10.9", + "resolved": "https://registry.npmjs.org/@types/unzipper/-/unzipper-0.10.9.tgz", + "integrity": "sha512-vHbmFZAw8emNAOVkHVbS3qBnbr0x/qHQZ+ei1HE7Oy6Tyrptl+jpqnOX+BF5owcu/HZLOV0nJK+K9sjs1Ox2JA==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/yargs": { - "version": "17.0.29", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.29.tgz", - "integrity": "sha512-nacjqA3ee9zRF/++a3FUY1suHTFKZeHba2n8WeDw9cCVdmzmHpIxyzOJBcpHvvEmS8E9KqWlSnWHUkOrkhWcvA==", + "version": "17.0.32", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", + "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", "dev": true, "dependencies": { "@types/yargs-parser": "*" } }, "node_modules/@types/yargs-parser": { - "version": "21.0.2", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.2.tgz", - "integrity": "sha512-5qcvofLPbfjmBfKaLfj/+f+Sbd6pN4zl7w7VSVI5uz7m9QZTuB2aZAa2uo1wHFBNN2x6g/SoTkXmd8mQnQF2Cw==", + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", "dev": true }, "node_modules/@uiw/codemirror-extensions-basic-setup": { - "version": "4.21.20", - "resolved": "https://registry.npmjs.org/@uiw/codemirror-extensions-basic-setup/-/codemirror-extensions-basic-setup-4.21.20.tgz", - "integrity": "sha512-Wyi9q4uw0xGYd/tJ6bULG7tkCLqcUsQT0AQBfCDtnkV3LdiLU0LceTrzJoHJyIKSHsKDJxFQxa1qg3QLt4gIUA==", + "version": "4.21.21", + "resolved": "https://registry.npmjs.org/@uiw/codemirror-extensions-basic-setup/-/codemirror-extensions-basic-setup-4.21.21.tgz", + "integrity": "sha512-+0i9dPrRSa8Mf0CvyrMvnAhajnqwsP3IMRRlaHDRgsSGL8igc4z7MhvUPn+7cWFAAqWzQRhMdMSWzo6/TEa3EA==", "dependencies": { "@codemirror/autocomplete": "^6.0.0", "@codemirror/commands": "^6.0.0", @@ -2761,6 +2793,9 @@ "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.0.0" }, + "funding": { + "url": "https://jaywcjlove.github.io/#/sponsor" + }, "peerDependencies": { "@codemirror/autocomplete": ">=6.0.0", "@codemirror/commands": ">=6.0.0", @@ -2772,31 +2807,40 @@ } }, "node_modules/@uiw/codemirror-extensions-classname": { - "version": "4.21.20", - "resolved": "https://registry.npmjs.org/@uiw/codemirror-extensions-classname/-/codemirror-extensions-classname-4.21.20.tgz", - "integrity": "sha512-RgN58q2UKVpauMw8PklBt1JNXQZU1MVPMpo2UdQ4tupkig/m1wDYj/Mv2/VOoNtfIrXc50iHL4WEKf+RVBiLjw==", + "version": "4.21.21", + "resolved": "https://registry.npmjs.org/@uiw/codemirror-extensions-classname/-/codemirror-extensions-classname-4.21.21.tgz", + "integrity": "sha512-QTVY7yEHZLHCpSolO5K1QG6hfZ4gcF7Lrcytqed7IwGXw6BGuNPBP4eWND0rJndhC0Ali30yNBVBE34TyUUJ8A==", + "funding": { + "url": "https://jaywcjlove.github.io/#/sponsor" + }, "peerDependencies": { "@codemirror/state": ">=6.0.0", "@codemirror/view": ">=6.0.0" } }, "node_modules/@uiw/codemirror-theme-okaidia": { - "version": "4.21.20", - "resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-okaidia/-/codemirror-theme-okaidia-4.21.20.tgz", - "integrity": "sha512-Gqlu7RJVQBUl6zkgTdtHAt+ZVt3vCiutA834FNqrY/nk+g5TT45Jpwzcyy+nUW3FiecT8WG1y+nkTH6dXdFRlQ==", + "version": "4.21.21", + "resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-okaidia/-/codemirror-theme-okaidia-4.21.21.tgz", + "integrity": "sha512-jZQ3YV+taTroqGmnAnFwU1uhAc+BZmuN1vjOJ9of7b6nmav1cohd8pdinZgDLag/ZrJt6TVr/KYBH8NF1Sm//g==", "dependencies": { - "@uiw/codemirror-themes": "4.21.20" + "@uiw/codemirror-themes": "4.21.21" + }, + "funding": { + "url": "https://jaywcjlove.github.io/#/sponsor" } }, "node_modules/@uiw/codemirror-themes": { - "version": "4.21.20", - "resolved": "https://registry.npmjs.org/@uiw/codemirror-themes/-/codemirror-themes-4.21.20.tgz", - "integrity": "sha512-/Ncc88v5RroeDAOfhao5lmkobmH4aJZqlSAJJTxXE7AzM85BjuCnnUYXVT7VFeEslFtfTiIgriyLmJQoGOi2mA==", + "version": "4.21.21", + "resolved": "https://registry.npmjs.org/@uiw/codemirror-themes/-/codemirror-themes-4.21.21.tgz", + "integrity": "sha512-ljVcMGdaxo75UaH+EqxJ+jLyMVVgeSfW2AKyT1VeLy+4SDpuqNQ7wq5XVxktsG6LH+OvgSFndWXgPANf4+gQcA==", "dependencies": { "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.0.0" }, + "funding": { + "url": "https://jaywcjlove.github.io/#/sponsor" + }, "peerDependencies": { "@codemirror/language": ">=6.0.0", "@codemirror/state": ">=6.0.0", @@ -2804,17 +2848,20 @@ } }, "node_modules/@uiw/react-codemirror": { - "version": "4.21.20", - "resolved": "https://registry.npmjs.org/@uiw/react-codemirror/-/react-codemirror-4.21.20.tgz", - "integrity": "sha512-PdyewPvNXnvT3JHj888yjpbWsAGw5qlxW6w1sMdsqJ0R6vPV++ob1iZXCGrM1FVpbqPK0DNfpXvjzp2gIr3lYw==", + "version": "4.21.21", + "resolved": "https://registry.npmjs.org/@uiw/react-codemirror/-/react-codemirror-4.21.21.tgz", + "integrity": "sha512-PaxBMarufMWoR0qc5zuvBSt76rJ9POm9qoOaJbqRmnNL2viaF+d+Paf2blPSlm1JSnqn7hlRjio+40nZJ9TKzw==", "dependencies": { "@babel/runtime": "^7.18.6", "@codemirror/commands": "^6.1.0", "@codemirror/state": "^6.1.1", "@codemirror/theme-one-dark": "^6.0.0", - "@uiw/codemirror-extensions-basic-setup": "4.21.20", + "@uiw/codemirror-extensions-basic-setup": "4.21.21", "codemirror": "^6.0.0" }, + "funding": { + "url": "https://jaywcjlove.github.io/#/sponsor" + }, "peerDependencies": { "@babel/runtime": ">=7.11.0", "@codemirror/state": ">=6.0.0", @@ -2829,8 +2876,21 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "deprecated": "Use your platform's native atob() and btoa() methods instead", "dev": true }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/acorn": { "version": "8.11.2", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", @@ -3030,9 +3090,9 @@ "integrity": "sha512-TaTivMB6pYI1kXwrFlEhLeGfOqoDNdTxjCdwRfFFkEA30Eu+k48W34nlok2EYWJfFFzqaEmichdNM7th6M5HNw==" }, "node_modules/async": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", + "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==" }, "node_modules/asynckit": { "version": "0.4.0", @@ -3089,9 +3149,9 @@ } }, "node_modules/axios": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.0.tgz", - "integrity": "sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz", + "integrity": "sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==", "dependencies": { "follow-redirects": "^1.15.0", "form-data": "^4.0.0", @@ -3245,15 +3305,23 @@ } ] }, + "node_modules/base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "engines": { + "node": "^4.5.0 || >= 5.9" + } + }, "node_modules/bcryptjs": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==" }, "node_modules/big-integer": { - "version": "1.6.51", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", - "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", + "version": "1.6.52", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", + "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", "engines": { "node": ">=0.6" } @@ -3477,9 +3545,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001558", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001558.tgz", - "integrity": "sha512-/Et7DwLqpjS47JPEcz6VnxU9PwcIdVi0ciLXRWBQdj1XFye68pSQYpV0QtPTfUKWuOaEig+/Vez2l74eDc1tPQ==", + "version": "1.0.30001565", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001565.tgz", + "integrity": "sha512-xrE//a3O7TP0vaJ8ikzkD2c2NgcVUvsEe2IvFTntV4Yd1Z9FVzh+gW+enX96L0psrbaFMcVcH2l90xNuGDWc8w==", "funding": [ { "type": "opencollective", @@ -3789,6 +3857,18 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/crc-32": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", @@ -3977,7 +4057,6 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, "dependencies": { "ms": "2.1.2" }, @@ -4025,15 +4104,15 @@ } }, "node_modules/deep-equal": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.2.tgz", - "integrity": "sha512-xjVyBf0w5vH0I42jdAZzOKVldmPgSulmiyPRywoyq7HXC9qdgo17kxJE+rdnif5Tz6+pIrpJI8dCpMNLIGkUiA==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", + "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==", "dev": true, "dependencies": { "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.2", + "call-bind": "^1.0.5", "es-get-iterator": "^1.1.3", - "get-intrinsic": "^1.2.1", + "get-intrinsic": "^1.2.2", "is-arguments": "^1.1.1", "is-array-buffer": "^3.0.2", "is-date-object": "^1.0.5", @@ -4043,11 +4122,14 @@ "object-is": "^1.1.5", "object-keys": "^1.1.1", "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.0", + "regexp.prototype.flags": "^1.5.1", "side-channel": "^1.0.4", "which-boxed-primitive": "^1.0.2", "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" + "which-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -4179,6 +4261,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", + "deprecated": "Use your platform's native DOMException instead", "dev": true, "dependencies": { "webidl-conversions": "^7.0.0" @@ -4262,9 +4345,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.570", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.570.tgz", - "integrity": "sha512-5GxH0PLSIfXKOUMMHMCT4M0olwj1WwAxsQHzVW5Vh3kbsvGw8b4k7LHQmTLC2aRhsgFzrF57XJomca4XLc/WHA==", + "version": "1.4.595", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.595.tgz", + "integrity": "sha512-+ozvXuamBhDOKvMNUQvecxfbyICmIAwS4GpLmR0bsiSBlGnLaOcs2Cj7J8XSbW+YEaN3Xl3ffgpm+srTUWFwFQ==", "dev": true }, "node_modules/emittery": { @@ -4293,6 +4376,94 @@ "once": "^1.4.0" } }, + "node_modules/engine.io": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.4.tgz", + "integrity": "sha512-KdVSDKhVKyOi+r5uEabrDLZw2qXStVvCsEB/LN3mw4WFi6Gx50jTyuxYVCwAAC0U46FdnzP/ScKRBTXb/NiEOg==", + "dependencies": { + "@types/cookie": "^0.4.1", + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.4.1", + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.11.0" + }, + "engines": { + "node": ">=10.2.0" + } + }, + "node_modules/engine.io-client": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.3.tgz", + "integrity": "sha512-9Z0qLB0NIisTRt1DZ/8U2k12RJn8yls/nXMZLn+/N8hANT3TcYjKFKcwbw5zFQiN4NTde3TSY9zb79e1ij6j9Q==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.11.0", + "xmlhttprequest-ssl": "~2.0.0" + } + }, + "node_modules/engine.io-client/node_modules/ws": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/engine.io-parser": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.1.tgz", + "integrity": "sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/engine.io/node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/engine.io/node_modules/ws": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/entities": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", @@ -4466,9 +4637,9 @@ "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==" }, "node_modules/fast-glob": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", - "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -5438,9 +5609,9 @@ "dev": true }, "node_modules/istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", "dev": true, "engines": { "node": ">=8" @@ -7008,17 +7179,17 @@ } }, "node_modules/lru-cache": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.1.tgz", - "integrity": "sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.1.0.tgz", + "integrity": "sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==", "engines": { "node": "14 || >=16.14" } }, "node_modules/luxon": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.4.3.tgz", - "integrity": "sha512-tFWBiv3h7z+T/tDaoxA8rqTxy1CHV6gHS//QdaH4pulbq/JuBSGgQspQQqcgnwdAx6pNI7cmvz5Sv/addzHmUg==", + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.4.4.tgz", + "integrity": "sha512-zobTr7akeGHnv7eBOXcRgMeCP6+uyYsczwmeRCauvpvaAltgNyTbLH/+VaEAPUeWBT+1GuNmz4wC/6jtQzbbVA==", "engines": { "node": ">=12" } @@ -7223,9 +7394,9 @@ } }, "node_modules/nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", "funding": [ { "type": "github", @@ -7259,39 +7430,37 @@ } }, "node_modules/next": { - "version": "13.4.10", - "resolved": "https://registry.npmjs.org/next/-/next-13.4.10.tgz", - "integrity": "sha512-4ep6aKxVTQ7rkUW2fBLhpBr/5oceCuf4KmlUpvG/aXuDTIf9mexNSpabUD6RWPspu6wiJJvozZREhXhueYO36A==", + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/next/-/next-14.0.3.tgz", + "integrity": "sha512-AbYdRNfImBr3XGtvnwOxq8ekVCwbFTv/UJoLwmaX89nk9i051AEY4/HAWzU0YpaTDw8IofUpmuIlvzWF13jxIw==", "dependencies": { - "@next/env": "13.4.10", - "@swc/helpers": "0.5.1", + "@next/env": "14.0.3", + "@swc/helpers": "0.5.2", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001406", - "postcss": "8.4.14", + "postcss": "8.4.31", "styled-jsx": "5.1.1", - "watchpack": "2.4.0", - "zod": "3.21.4" + "watchpack": "2.4.0" }, "bin": { "next": "dist/bin/next" }, "engines": { - "node": ">=16.8.0" + "node": ">=18.17.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "13.4.10", - "@next/swc-darwin-x64": "13.4.10", - "@next/swc-linux-arm64-gnu": "13.4.10", - "@next/swc-linux-arm64-musl": "13.4.10", - "@next/swc-linux-x64-gnu": "13.4.10", - "@next/swc-linux-x64-musl": "13.4.10", - "@next/swc-win32-arm64-msvc": "13.4.10", - "@next/swc-win32-ia32-msvc": "13.4.10", - "@next/swc-win32-x64-msvc": "13.4.10" + "@next/swc-darwin-arm64": "14.0.3", + "@next/swc-darwin-x64": "14.0.3", + "@next/swc-linux-arm64-gnu": "14.0.3", + "@next/swc-linux-arm64-musl": "14.0.3", + "@next/swc-linux-x64-gnu": "14.0.3", + "@next/swc-linux-x64-musl": "14.0.3", + "@next/swc-win32-arm64-msvc": "14.0.3", + "@next/swc-win32-ia32-msvc": "14.0.3", + "@next/swc-win32-x64-msvc": "14.0.3" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", - "fibers": ">= 3.1.0", "react": "^18.2.0", "react-dom": "^18.2.0", "sass": "^1.3.0" @@ -7300,18 +7469,15 @@ "@opentelemetry/api": { "optional": true }, - "fibers": { - "optional": true - }, "sass": { "optional": true } } }, "node_modules/next-auth": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/next-auth/-/next-auth-4.22.1.tgz", - "integrity": "sha512-NTR3f6W7/AWXKw8GSsgSyQcDW6jkslZLH8AiZa5PQ09w1kR8uHtR9rez/E9gAq/o17+p0JYHE8QjF3RoniiObA==", + "version": "4.24.5", + "resolved": "https://registry.npmjs.org/next-auth/-/next-auth-4.24.5.tgz", + "integrity": "sha512-3RafV3XbfIKk6rF6GlLE4/KxjTcuMCifqrmD+98ejFq73SRoj2rmzoca8u764977lH/Q7jo6Xu6yM+Re1Mz/Og==", "dependencies": { "@babel/runtime": "^7.20.13", "@panva/hkdf": "^1.0.2", @@ -7324,7 +7490,7 @@ "uuid": "^8.3.2" }, "peerDependencies": { - "next": "^12.2.5 || ^13", + "next": "^12.2.5 || ^13 || ^14", "nodemailer": "^6.6.5", "react": "^17.0.2 || ^18", "react-dom": "^17.0.2 || ^18" @@ -7336,19 +7502,16 @@ } }, "node_modules/next-intl": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/next-intl/-/next-intl-2.19.0.tgz", - "integrity": "sha512-vK/3Lk1A2zPVl+D6n/cft+MsD6nsZO5/F4l+pHXSXrNQIjdClvGMKouM3xK/u5n75E4mmHQevVdyJQ1a7zWICw==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/next-intl/-/next-intl-3.1.4.tgz", + "integrity": "sha512-/mewUryIPdoZT7j+8ipN2rfWuuNGdl+xiwxWxYkYko0kGY/a2IlcgqaMBKwue5V5M17Vk9bwiydv/2wySJXG8w==", "dependencies": { "@formatjs/intl-localematcher": "^0.2.32", "negotiator": "^0.6.3", - "use-intl": "^2.19.0" - }, - "engines": { - "node": ">=10" + "use-intl": "^3.1.4" }, "peerDependencies": { - "next": "^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0", + "next": "^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0 || ^14.0.0", "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, @@ -7362,37 +7525,6 @@ "react-dom": "*" } }, - "node_modules/next/node_modules/postcss": { - "version": "8.4.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", - "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - } - ], - "dependencies": { - "nanoid": "^3.3.4", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/next/node_modules/zod": { - "version": "3.21.4", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.21.4.tgz", - "integrity": "sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, "node_modules/node-abi": { "version": "3.51.0", "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.51.0.tgz", @@ -7791,7 +7923,6 @@ "version": "8.4.31", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", - "dev": true, "funding": [ { "type": "opencollective", @@ -7852,21 +7983,27 @@ } }, "node_modules/postcss-load-config": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.1.tgz", - "integrity": "sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "dependencies": { - "lilconfig": "^2.0.5", - "yaml": "^2.1.1" + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" }, "engines": { "node": ">= 14" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, "peerDependencies": { "postcss": ">=8.0.9", "ts-node": ">=9.0.0" @@ -7880,6 +8017,15 @@ } } }, + "node_modules/postcss-load-config/node_modules/lilconfig": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.0.0.tgz", + "integrity": "sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==", + "dev": true, + "engines": { + "node": ">=14" + } + }, "node_modules/postcss-nested": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz", @@ -7919,9 +8065,9 @@ "dev": true }, "node_modules/preact": { - "version": "10.18.1", - "resolved": "https://registry.npmjs.org/preact/-/preact-10.18.1.tgz", - "integrity": "sha512-mKUD7RRkQQM6s7Rkmi7IFkoEHjuFqRQUaXamO61E6Nn7vqF/bo7EZCmSyrUnp2UWHw0O7XjZ2eeXis+m7tf4lg==", + "version": "10.19.2", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.19.2.tgz", + "integrity": "sha512-UA9DX/OJwv6YwP9Vn7Ti/vF80XL+YA5H2l7BpCtUr3ya8LWHFzpiO5R+N7dN16ujpIxhekRFuOOF82bXX7K/lg==", "funding": { "type": "opencollective", "url": "https://opencollective.com/preact" @@ -8021,13 +8167,13 @@ } }, "node_modules/prisma": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/prisma/-/prisma-5.5.2.tgz", - "integrity": "sha512-WQtG6fevOL053yoPl6dbHV+IWgKo25IRN4/pwAGqcWmg7CrtoCzvbDbN9fXUc7QS2KK0LimHIqLsaCOX/vHl8w==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-5.6.0.tgz", + "integrity": "sha512-EEaccku4ZGshdr2cthYHhf7iyvCcXqwJDvnoQRAJg5ge2Tzpv0e2BaMCp+CbbDUwoVTzwgOap9Zp+d4jFa2O9A==", "devOptional": true, "hasInstallScript": true, "dependencies": { - "@prisma/engines": "5.5.2" + "@prisma/engines": "5.6.0" }, "bin": { "prisma": "build/index.js" @@ -8311,9 +8457,9 @@ } }, "node_modules/react-datepicker": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-4.21.0.tgz", - "integrity": "sha512-z0DtuRrKMz9i7dcTusW29VacbM9pn08g1yw0cG+Y5GpodJDxSWv7zUMxl3IwKN9Ap/AMphiepvmT5P+iNCgEiA==", + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-4.23.0.tgz", + "integrity": "sha512-w+msqlOZ14v6H1UknTKtZw/dw9naFMgAOspf59eY130gWpvy5dvKj/bgsFICDdvxB7PtKWxDcbGlAqCloY1d2A==", "dependencies": { "@popperjs/core": "^2.11.8", "classnames": "^2.2.6", @@ -8885,6 +9031,77 @@ "node": ">=8" } }, + "node_modules/socket.io": { + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.2.tgz", + "integrity": "sha512-bvKVS29/I5fl2FGLNHuXlQaUH/BlzX1IN6S+NKLNZpBsPZIDH+90eQmCs2Railn4YUiww4SzUedJ6+uzwFnKLw==", + "dependencies": { + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "cors": "~2.8.5", + "debug": "~4.3.2", + "engine.io": "~6.5.2", + "socket.io-adapter": "~2.5.2", + "socket.io-parser": "~4.2.4" + }, + "engines": { + "node": ">=10.2.0" + } + }, + "node_modules/socket.io-adapter": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz", + "integrity": "sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==", + "dependencies": { + "ws": "~8.11.0" + } + }, + "node_modules/socket.io-adapter/node_modules/ws": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/socket.io-client": { + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.2.tgz", + "integrity": "sha512-vtA0uD4ibrYD793SOIAwlo8cj6haOeMHrGvwPxJsxH7CeIksqJ+3Zc06RvWTIFgiSqx4A3sOnTXpfAEE2Zyz6w==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.2", + "engine.io-client": "~6.5.2", + "socket.io-parser": "~4.2.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-parser": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -8950,9 +9167,9 @@ } }, "node_modules/streamx": { - "version": "2.15.2", - "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.15.2.tgz", - "integrity": "sha512-b62pAV/aeMjUoRN2C/9F0n+G8AfcJjNC0zw/ZmOHeFsIe4m4GzjVW9m6VHXVjk536NbdU9JRwKMJRfkc+zUFTg==", + "version": "2.15.5", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.15.5.tgz", + "integrity": "sha512-9thPGMkKC2GctCzyCUjME3yR03x2xNo0GPKGkRw2UMYN+gqWa9uqpyNWhmsNCutU5zHmkUum0LsCRQTXUgUCAg==", "dependencies": { "fast-fifo": "^1.1.0", "queue-tick": "^1.0.1" @@ -9590,9 +9807,9 @@ } }, "node_modules/type-fest": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.6.0.tgz", - "integrity": "sha512-rLjWJzQFOq4xw7MgJrCZ6T1jIOvvYElXT12r+y0CC6u67hegDHaxcPqb2fZHOGlqxugGQPNB1EnTezjBetkwkw==", + "version": "4.8.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.8.2.tgz", + "integrity": "sha512-mcvrCjixA5166hSrUoJgGb9gBQN4loMYyj9zxuMs/66ibHNEFd5JXMw37YVDx58L4/QID9jIzdTBB4mDwDJ6KQ==", "dev": true, "engines": { "node": ">=16" @@ -9602,9 +9819,9 @@ } }, "node_modules/typescript": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", - "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.2.tgz", + "integrity": "sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -9617,8 +9834,7 @@ "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" }, "node_modules/unique-names-generator": { "version": "4.7.1", @@ -9727,16 +9943,13 @@ } }, "node_modules/use-intl": { - "version": "2.21.0", - "resolved": "https://registry.npmjs.org/use-intl/-/use-intl-2.21.0.tgz", - "integrity": "sha512-m0gAKo/2OHw1tJtGQV226NIIpUy4Ualf+FKa/whk7hM1W7MXQ2v8c/N54UPrSy+PvJLCrIe7aOQ5xYEmUjnztQ==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/use-intl/-/use-intl-3.1.4.tgz", + "integrity": "sha512-iBIHPetLeEdAuIhAXRI9ukfjjvadP2EWoAEl6IvbWojrwYgcP52A6Al1nyzIwZD7iWBU1T3Ri3Hg4HsV7cWlVA==", "dependencies": { "@formatjs/ecma402-abstract": "^1.11.4", "intl-messageformat": "^9.3.18" }, - "engines": { - "node": ">=10" - }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } @@ -9782,9 +9995,9 @@ "dev": true }, "node_modules/v8-to-istanbul": { - "version": "9.1.3", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.3.tgz", - "integrity": "sha512-9lDD+EVI2fjFsMWXc6dy5JJzBsVTcQ2fVkfBvncZ6xJWG9wtBhOldG+mHkSL0+V1K/xgZz0JDO5UT5hFwHUghg==", + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz", + "integrity": "sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==", "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.12", @@ -9795,6 +10008,14 @@ "node": ">=10.12.0" } }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/void-elements": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", @@ -10042,6 +10263,14 @@ "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", "dev": true }, + "node_modules/xmlhttprequest-ssl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz", + "integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -10058,9 +10287,9 @@ "dev": true }, "node_modules/yaml": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.3.tgz", - "integrity": "sha512-zw0VAJxgeZ6+++/su5AFoqBbZbrEakwu+X0M5HmcwUiBL7AzcuPKjj5we4xfQLp78LkEMpD0cOnUhmgOVy3KdQ==", + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", + "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", "dev": true, "engines": { "node": ">= 14" @@ -10136,9 +10365,9 @@ } }, "node_modules/zustand": { - "version": "4.4.4", - "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.4.4.tgz", - "integrity": "sha512-5UTUIAiHMNf5+mFp7/AnzJXS7+XxktULFN0+D1sCiZWyX7ZG+AQpqs2qpYrynRij4QvoDdCD+U+bmg/cG3Ucxw==", + "version": "4.4.7", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.4.7.tgz", + "integrity": "sha512-QFJWJMdlETcI69paJwhSMJz7PPWjVP8Sjhclxmxmxv/RYI7ZOvR5BHX+ktH0we9gTWQMxcne8q1OY8xxz604gw==", "dependencies": { "use-sync-external-store": "1.2.0" }, diff --git a/package.json b/package.json index edba04d1..842b73ee 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "@trpc/next": "^10.37.1", "@trpc/react-query": "^10.37.1", "@trpc/server": "^10.37.1", + "@types/socket.io-client": "^3.0.0", "@uiw/codemirror-extensions-classname": "^4.21.7", "@uiw/codemirror-theme-okaidia": "^4.21.7", "@uiw/react-codemirror": "^4.21.7", @@ -43,9 +44,9 @@ "ip-address": "^8.1.0", "jsonwebtoken": "^9.0.1", "lru-cache": "^10.0.1", - "next": "13.4.10", - "next-auth": "4.22.1", - "next-intl": "2.19.0", + "next": "14.0.3", + "next-auth": "4.24.5", + "next-intl": "3.1.4", "next-themes": "^0.2.1", "nodemailer": "^6.9.4", "pug": "^3.0.2", @@ -56,6 +57,8 @@ "react-hot-toast": "^2.4.0", "react-timeago": "^7.1.0", "sharp": "0.32.3", + "socket.io": "^4.7.2", + "socket.io-client": "^4.7.2", "superjson": "1.9.1", "unique-names-generator": "^4.7.1", "unzipper": "^0.10.14", @@ -94,7 +97,7 @@ "ts-jest": "^29.1.0", "ts-node": "^10.9.1", "type-fest": "^4.2.0", - "typescript": "^5.1.6" + "typescript": "5.3.2" }, "ct3aMetadata": { "initVersion": "7.8.0" diff --git a/prisma/migrations/20231203075656_organization/migration.sql b/prisma/migrations/20231203075656_organization/migration.sql new file mode 100644 index 00000000..92be2e13 --- /dev/null +++ b/prisma/migrations/20231203075656_organization/migration.sql @@ -0,0 +1,158 @@ +-- AlterEnum +ALTER TYPE "Role" ADD VALUE 'READ_ONLY'; + +-- AlterTable +ALTER TABLE "GlobalOptions" ADD COLUMN "inviteOrganizationTemplate" JSONB; + +-- AlterTable +ALTER TABLE "network" ADD COLUMN "organizationId" TEXT, +ALTER COLUMN "authorId" DROP NOT NULL; + +-- CreateTable +CREATE TABLE "Organization" ( + "id" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "ownerId" TEXT NOT NULL, + "orgName" TEXT NOT NULL, + "description" TEXT, + "isActive" BOOLEAN NOT NULL DEFAULT true, + + CONSTRAINT "Organization_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "UserOrganizationRole" ( + "userId" TEXT NOT NULL, + "organizationId" TEXT NOT NULL, + "role" "Role" NOT NULL, + + CONSTRAINT "UserOrganizationRole_pkey" PRIMARY KEY ("userId","organizationId") +); + +-- CreateTable +CREATE TABLE "Messages" ( + "id" SERIAL NOT NULL, + "content" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "userId" TEXT NOT NULL, + "organizationId" TEXT NOT NULL, + + CONSTRAINT "Messages_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "LastReadMessage" ( + "id" SERIAL NOT NULL, + "lastMessageId" INTEGER NOT NULL, + "userId" TEXT NOT NULL, + "organizationId" TEXT NOT NULL, + + CONSTRAINT "LastReadMessage_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "OrganizationSettings" ( + "id" SERIAL NOT NULL, + "organizationId" TEXT NOT NULL, + + CONSTRAINT "OrganizationSettings_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "OrganizationInvitation" ( + "id" SERIAL NOT NULL, + "token" TEXT NOT NULL, + "email" TEXT NOT NULL, + "organizationId" TEXT NOT NULL, + + CONSTRAINT "OrganizationInvitation_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "MembershipRequest" ( + "id" SERIAL NOT NULL, + "userId" TEXT NOT NULL, + "organizationId" TEXT NOT NULL, + + CONSTRAINT "MembershipRequest_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "ActivityLog" ( + "id" SERIAL NOT NULL, + "action" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "performedById" TEXT NOT NULL, + "organizationId" TEXT, + + CONSTRAINT "ActivityLog_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "_MemberRelation" ( + "A" TEXT NOT NULL, + "B" TEXT NOT NULL +); + +-- CreateIndex +CREATE UNIQUE INDEX "LastReadMessage_userId_organizationId_key" ON "LastReadMessage"("userId", "organizationId"); + +-- CreateIndex +CREATE UNIQUE INDEX "OrganizationSettings_organizationId_key" ON "OrganizationSettings"("organizationId"); + +-- CreateIndex +CREATE UNIQUE INDEX "OrganizationInvitation_token_key" ON "OrganizationInvitation"("token"); + +-- CreateIndex +CREATE UNIQUE INDEX "_MemberRelation_AB_unique" ON "_MemberRelation"("A", "B"); + +-- CreateIndex +CREATE INDEX "_MemberRelation_B_index" ON "_MemberRelation"("B"); + +-- AddForeignKey +ALTER TABLE "network" ADD CONSTRAINT "network_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "UserOrganizationRole" ADD CONSTRAINT "UserOrganizationRole_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "UserOrganizationRole" ADD CONSTRAINT "UserOrganizationRole_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Messages" ADD CONSTRAINT "Messages_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Messages" ADD CONSTRAINT "Messages_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "LastReadMessage" ADD CONSTRAINT "LastReadMessage_lastMessageId_fkey" FOREIGN KEY ("lastMessageId") REFERENCES "Messages"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "LastReadMessage" ADD CONSTRAINT "LastReadMessage_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "LastReadMessage" ADD CONSTRAINT "LastReadMessage_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "OrganizationSettings" ADD CONSTRAINT "OrganizationSettings_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "OrganizationInvitation" ADD CONSTRAINT "OrganizationInvitation_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "MembershipRequest" ADD CONSTRAINT "MembershipRequest_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "MembershipRequest" ADD CONSTRAINT "MembershipRequest_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ActivityLog" ADD CONSTRAINT "ActivityLog_performedById_fkey" FOREIGN KEY ("performedById") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ActivityLog" ADD CONSTRAINT "ActivityLog_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_MemberRelation" ADD CONSTRAINT "_MemberRelation_A_fkey" FOREIGN KEY ("A") REFERENCES "Organization"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_MemberRelation" ADD CONSTRAINT "_MemberRelation_B_fkey" FOREIGN KEY ("B") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 489f8ded..30b3305b 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -12,6 +12,13 @@ datasource db { shadowDatabaseUrl = env("MIGRATE_DATABASE_URL") } +enum Role { + READ_ONLY + USER + MODERATOR + ADMIN +} + model GlobalOptions { id Int @id @default(autoincrement()) @@ -31,6 +38,7 @@ model GlobalOptions { smtpIgnoreTLS Boolean @default(false) inviteUserTemplate Json? inviteAdminTemplate Json? + inviteOrganizationTemplate Json? forgotPasswordTemplate Json? verifyEmailTemplate Json? notificationTemplate Json? @@ -52,11 +60,6 @@ model GlobalOptions { welcomeMessageBody String? } -enum Role { - USER - MODERATOR - ADMIN -} model network_members { nodeid Int @id @default(autoincrement()) @@ -81,10 +84,14 @@ model network { lastModifiedTime DateTime? flowRule String? autoAssignIp Boolean? @default(true) - nw_userid User @relation(fields: [authorId], references: [id], onDelete: Cascade) - authorId String + nw_userid User? @relation(fields: [authorId], references: [id], onDelete: Cascade) + authorId String? tagsByName Json? capabilitiesByName Json? + + organizationId String? + organization Organization? @relation(fields: [organizationId], references: [id], onDelete: Cascade) + networkMembers network_members[] notations Notation[] } @@ -187,36 +194,45 @@ model APIToken { } model User { - id String @id @default(cuid()) + id String @id @default(cuid()) name String - email String @unique + email String @unique emailVerified DateTime? lastLogin DateTime lastseen DateTime? - expirationDate String @default("") - online Boolean? @default(false) - role Role @default(USER) + expirationDate String @default("") + online Boolean? @default(false) + role Role @default(USER) image String? hash String licenseStatus String? orderStatus String? - orderId Int @default(0) - product_id Int? @default(0) - licenseKey String? @default("") + orderId Int @default(0) + product_id Int? @default(0) + licenseKey String? @default("") tempPassword String? - firstTime Boolean @default(true) + firstTime Boolean @default(true) userGroupId Int? + + memberOfOrgs Organization[] @relation("MemberRelation") // user can be member of multiple organizations + organizationRoles UserOrganizationRole[] + membershipRequests MembershipRequest[] @relation("MembershipRequestsForUser") + messages Messages[] + lastReadByUsers LastReadMessage[] + ActivityLog ActivityLog[] expiresAt DateTime? // null means it never expires - isActive Boolean @default(true) - - userGroup UserGroup? @relation(fields: [userGroupId], references: [id], onDelete: Restrict) - options UserOptions? - accounts Account[] - sessions Session[] - network network[] - apiTokens APIToken[] + isActive Boolean @default(true) + + userGroup UserGroup? @relation(fields: [userGroupId], references: [id], onDelete: Restrict) + options UserOptions? + accounts Account[] + sessions Session[] + network network[] + apiTokens APIToken[] } + + model VerificationToken { identifier String token String @unique @@ -240,6 +256,96 @@ model UserInvitation { } +// +// ORGANIZATION +// + +model Organization { + id String @id @default(cuid()) + createdAt DateTime @default(now()) + ownerId String + orgName String + description String? + users User[] @relation("MemberRelation") + networks network[] + settings OrganizationSettings? + invitations OrganizationInvitation[] + membershipRequests MembershipRequest[] @relation("MembershipRequestsForOrganization") + isActive Boolean @default(true) + userRoles UserOrganizationRole[] + messages Messages[] + lastReadByUsers LastReadMessage[] + ActivityLog ActivityLog[] +} + +model UserOrganizationRole { + userId String + organizationId String + role Role + user User @relation(fields: [userId], references: [id]) + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + + @@id([userId, organizationId]) +} + +model Messages { + id Int @id @default(autoincrement()) + content String + createdAt DateTime @default(now()) + userId String // Reference to the User model + user User @relation(fields: [userId], references: [id]) + organizationId String // Reference to the Organization model + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + lastReadByUsers LastReadMessage[] +} + +model LastReadMessage { + id Int @id @default(autoincrement()) + lastMessageId Int // ID of the last read message + userId String + organizationId String + + lastMessage Messages @relation(fields: [lastMessageId], references: [id]) + user User @relation(fields: [userId], references: [id]) + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + + @@unique([userId, organizationId]) +} + +model OrganizationSettings { + id Int @id @default(autoincrement()) + organizationId String @unique + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + // Add specific settings fields here +} + +model OrganizationInvitation { + id Int @id @default(autoincrement()) + token String @unique + email String + organizationId String + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) +} + +model MembershipRequest { + id Int @id @default(autoincrement()) + userId String + organizationId String + user User @relation(fields: [userId], references: [id], name: "MembershipRequestsForUser") + organization Organization @relation(fields: [organizationId], references: [id], name: "MembershipRequestsForOrganization", onDelete: Cascade) +} + +model ActivityLog { + id Int @id @default(autoincrement()) + action String + createdAt DateTime @default(now()) + performedById String + performedBy User @relation(fields: [performedById], references: [id]) + organizationId String? // Make this optional + organization Organization? @relation(fields: [organizationId], references: [id], onDelete: Cascade) +} + + // To map your data model to the database schema, you need to use the prisma migrate CLI commands: // npx prisma migrate dev --name (NAME) diff --git a/src/__tests__/components/inputField.test.tsx b/src/__tests__/components/inputField.test.tsx index 7b015827..33c7ba8d 100644 --- a/src/__tests__/components/inputField.test.tsx +++ b/src/__tests__/components/inputField.test.tsx @@ -1,7 +1,7 @@ import React from "react"; import { render, fireEvent, screen } from "@testing-library/react"; import InputField from "~/components/elements/inputField"; -import { NextIntlProvider } from "next-intl"; +import { NextIntlClientProvider } from "next-intl"; import enTranslation from "~/locales/en/common.json"; describe("InputField", () => { @@ -20,9 +20,9 @@ describe("InputField", () => { const submitHandler = jest.fn(); const { container } = render( - + - , + , ); // Click the edit icon to render the inputs diff --git a/src/__tests__/components/loginForm.test.tsx b/src/__tests__/components/loginForm.test.tsx index f6db5c95..488f74a5 100644 --- a/src/__tests__/components/loginForm.test.tsx +++ b/src/__tests__/components/loginForm.test.tsx @@ -21,12 +21,12 @@ describe("LoginForm", () => { }); it("renders the LoginForm component", () => { - render( {}} />); + render(); expect(screen.getByRole("heading", { name: /Sign In/i })).toBeInTheDocument(); }); it("updates email and password inputs on change", () => { - render( {}} />); + render(); const emailInput = screen.getByPlaceholderText("mail@example.com"); const passwordInput = screen.getByPlaceholderText("Enter your password"); @@ -39,7 +39,7 @@ describe("LoginForm", () => { }); it("submits the form with correct email and password", async () => { - render( {}} />); + render(); (signIn as jest.Mock).mockResolvedValue({}); diff --git a/src/__tests__/components/modal.test.tsx b/src/__tests__/components/modal.test.tsx index d086d80f..9f6c282d 100644 --- a/src/__tests__/components/modal.test.tsx +++ b/src/__tests__/components/modal.test.tsx @@ -1,7 +1,7 @@ import { render, fireEvent, screen } from "@testing-library/react"; import { useModalStore } from "~/utils/store"; import enTranslation from "~/locales/en/common.json"; -import { NextIntlProvider } from "next-intl"; +import { NextIntlClientProvider } from "next-intl"; import Modal from "~/components/shared/modal"; jest.mock("../../utils/store", () => ({ @@ -30,9 +30,9 @@ describe("Modal", () => { test("renders modal with title and description", () => { render( - + - , + , ); expect(screen.getByText("Test title")).toBeInTheDocument(); expect(screen.getByText("Test description")).toBeInTheDocument(); @@ -40,9 +40,9 @@ describe("Modal", () => { test("handles yes and cancel actions", () => { render( - + - , + , ); fireEvent.click(screen.getByText("Yes")); expect(yesAction).toHaveBeenCalledTimes(1); diff --git a/src/__tests__/components/networkDns.test.tsx b/src/__tests__/components/networkDns.test.tsx index ee7de4e5..4a2c596b 100644 --- a/src/__tests__/components/networkDns.test.tsx +++ b/src/__tests__/components/networkDns.test.tsx @@ -3,7 +3,7 @@ import { render, screen, fireEvent, waitFor } from "@testing-library/react"; import { NextRouter, useRouter } from "next/router"; import { api } from "~/utils/api"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; -import { NextIntlProvider } from "next-intl"; +import { NextIntlClientProvider } from "next-intl"; import enTranslation from "~/locales/en/common.json"; import { NetworkDns } from "~/components/networkByIdPage/networkDns"; @@ -55,9 +55,9 @@ describe("", () => { render( - + - + , ); diff --git a/src/__tests__/components/networkIpAssignments.test.tsx b/src/__tests__/components/networkIpAssignments.test.tsx index ddeaf76e..19702c38 100644 --- a/src/__tests__/components/networkIpAssignments.test.tsx +++ b/src/__tests__/components/networkIpAssignments.test.tsx @@ -3,7 +3,7 @@ import { render, screen, fireEvent, waitFor } from "@testing-library/react"; import { NextRouter, useRouter } from "next/router"; import { api } from "~/utils/api"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; -import { NextIntlProvider } from "next-intl"; +import { NextIntlClientProvider } from "next-intl"; import enTranslation from "~/locales/en/common.json"; import { NetworkIpAssignment } from "~/components/networkByIdPage/networkIpAssignments"; @@ -41,9 +41,9 @@ describe("", () => { render( - + - + , ); @@ -68,9 +68,9 @@ describe("", () => { render( - + - + , ); @@ -106,9 +106,9 @@ describe("", () => { // Render the component render( - + - + , ); @@ -145,9 +145,9 @@ describe("", () => { render( - + - + , ); @@ -180,9 +180,9 @@ describe("", () => { render( - + - + , ); diff --git a/src/__tests__/components/networkMulticast.test.tsx b/src/__tests__/components/networkMulticast.test.tsx index 16ff849d..183a0dac 100644 --- a/src/__tests__/components/networkMulticast.test.tsx +++ b/src/__tests__/components/networkMulticast.test.tsx @@ -3,7 +3,7 @@ import { render, screen, fireEvent, waitFor } from "@testing-library/react"; import { NextRouter, useRouter } from "next/router"; import { api } from "~/utils/api"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; -import { NextIntlProvider } from "next-intl"; +import { NextIntlClientProvider } from "next-intl"; import enTranslation from "~/locales/en/common.json"; import { NetworkMulticast } from "~/components/networkByIdPage/networkMulticast"; @@ -54,9 +54,9 @@ describe("", () => { render( - + - + , ); @@ -103,9 +103,9 @@ describe("", () => { }); render( - + - + , ); diff --git a/src/__tests__/pages/network/[id].test.tsx b/src/__tests__/pages/network/[id].test.tsx index 5ff0e84d..c8ee2bc0 100644 --- a/src/__tests__/pages/network/[id].test.tsx +++ b/src/__tests__/pages/network/[id].test.tsx @@ -6,7 +6,7 @@ import NetworkById from "~/pages/network/[id]"; import userEvent from "@testing-library/user-event"; import { useRouter } from "next/router"; import { api } from "../../../utils/api"; -import { NextIntlProvider } from "next-intl"; +import { NextIntlClientProvider } from "next-intl"; import enTranslation from "~/locales/en/common.json"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; @@ -43,9 +43,9 @@ describe("NetworkById component", () => { render( - + - + , ); // expect(screen.getByText(/loading/i)).toBeInTheDocument(); @@ -73,9 +73,9 @@ describe("NetworkById component", () => { render( - + - + , ); // await waitForElementToBeRemoved(() => screen.queryByText(/loading/i)); @@ -89,9 +89,9 @@ describe("NetworkById component", () => { test("renders Network Settings divider", () => { render( - + - + , ); expect(screen.getByText(/Network Settings/i)).toBeInTheDocument(); @@ -100,9 +100,9 @@ describe("NetworkById component", () => { test("renders Network Members divider", () => { render( - + - + , ); const matches = screen.getAllByText(/Network Members/i); @@ -112,9 +112,9 @@ describe("NetworkById component", () => { test("renders Network Start, Network End, and Network Cidr labels", () => { render( - + - + , ); expect(screen.getByText(/Network Start:/i)).toBeInTheDocument(); @@ -125,9 +125,9 @@ describe("NetworkById component", () => { test("renders warning message", () => { render( - + - + , ); expect( @@ -141,9 +141,9 @@ describe("NetworkById component", () => { // screen.debug(); render( - + - + , ); const editIcon = screen.getByTestId("changeNetworkName"); @@ -195,9 +195,9 @@ describe("NetworkById component", () => { render( - + - + , ); // await waitForElementToBeRemoved(() => screen.queryByText(/loading/i)); @@ -241,9 +241,9 @@ describe("NetworkById component", () => { render( - + - + , ); await waitFor( @@ -280,9 +280,9 @@ describe("NetworkById component", () => { render( - + - + , ); await waitFor( @@ -319,9 +319,9 @@ describe("NetworkById component", () => { render( - + - + , ); await waitFor( diff --git a/src/__tests__/pages/network/index.test.tsx b/src/__tests__/pages/network/index.test.tsx index d82aa59d..3ae8482d 100644 --- a/src/__tests__/pages/network/index.test.tsx +++ b/src/__tests__/pages/network/index.test.tsx @@ -4,7 +4,7 @@ import { useRouter } from "next/router"; import userEvent from "@testing-library/user-event"; import { api } from "../../../utils/api"; import Networks from "~/pages/network"; -import { NextIntlProvider } from "next-intl"; +import { NextIntlClientProvider } from "next-intl"; import enTranslation from "~/locales/en/common.json"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; @@ -46,9 +46,9 @@ describe("Networks page", () => { }); render( - + - + , ); expect(screen.getByRole("progressbar")).toBeInTheDocument(); @@ -77,9 +77,9 @@ describe("Networks page", () => { // }); render( - + - , + , ); expect(screen.getByText("Network 1")).toBeInTheDocument(); diff --git a/src/components/adminPage/mail/mailOrganizationInviteTemplate.tsx b/src/components/adminPage/mail/mailOrganizationInviteTemplate.tsx new file mode 100644 index 00000000..5b1aa21b --- /dev/null +++ b/src/components/adminPage/mail/mailOrganizationInviteTemplate.tsx @@ -0,0 +1,193 @@ +import { useState, useEffect } from "react"; +import { api } from "~/utils/api"; +import { toast } from "react-hot-toast"; +import cn from "classnames"; +import { useTranslations } from "use-intl"; + +type IMailTemplate = { + subject: string; + body: string; +}; + +const OrganizationInviteTemplate = () => { + const t = useTranslations("admin"); + const [changes, setChanges] = useState({ + subject: false, + body: false, + }); + + const [stateTemplate, setEmailTemplate] = useState({ + subject: "", + body: "", + }); + + // get default mail template + const { + data: mailTemplates, + refetch: refetchMailTemplates, + isLoading: loadingTemplates, + } = api.admin.getMailTemplates.useQuery({ + template: "inviteOrganizationTemplate", + }); + + const changeTemplateHandler = ( + e: React.ChangeEvent, + ) => { + const modifiedValue = e.target.value.replace(/\n/g, "
"); + setEmailTemplate({ + ...stateTemplate, + [e.target.name]: modifiedValue, + }); + }; + + const { mutate: sendTestMail, isLoading: sendingMailLoading } = + api.admin.sendTestMail.useMutation({ + onError: (err) => { + toast.error(err.message); + }, + onSuccess: () => { + toast.success(t("mail.templates.successToastMailSent")); + }, + }); + + const { mutate: setMailTemplates } = api.admin.setMailTemplates.useMutation(); + + const { mutate: getDefaultMailTemplate, data: defaultTemplates } = + api.admin.getDefaultMailTemplate.useMutation(); + + useEffect(() => { + if (!defaultTemplates) return; + setEmailTemplate(defaultTemplates); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [defaultTemplates]); + + useEffect(() => { + const notificationTemplate = mailTemplates as IMailTemplate; + setEmailTemplate(notificationTemplate); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [mailTemplates]); + + useEffect(() => { + const keysToCompare = ["subject", "body"]; + + const _mailTemplate = mailTemplates as IMailTemplate; + if (!_mailTemplate || !stateTemplate) return; + + const newChanges = keysToCompare.reduce( + (acc, key) => { + const val1 = _mailTemplate?.[key] as string; + const val2 = stateTemplate[key] as string; + + // Here we just compare strings directly + acc[key] = val1 !== val2; + + return acc; + }, + { subject: false, body: false }, + ); + + setChanges(newChanges); + }, [mailTemplates, stateTemplate]); + + const submitTemplateHandler = () => { + if (!stateTemplate.subject || !stateTemplate.body) { + return toast.error(t("mail.templates.errorFields")); + } + + setMailTemplates( + { + template: JSON.stringify(stateTemplate), + type: "notificationTemplate", + }, + { + onSuccess: () => { + toast.success(t("mail.templates.successToastTemplateSaved")); + void refetchMailTemplates(); + }, + }, + ); + }; + if (loadingTemplates) { + return ( +
+

+ +

+
+ ); + } + return ( +
+
+

+ {t("mail.templates.availableTags")} + fromAdmin fromOrganization toEmail +

+
+ + +
+
+ + +
+
+
+
+ + +
+
+ +
+
+
+ ); +}; + +export default OrganizationInviteTemplate; diff --git a/src/components/adminPage/organization/deleteOrganizationModal.tsx b/src/components/adminPage/organization/deleteOrganizationModal.tsx new file mode 100644 index 00000000..eda6ddc3 --- /dev/null +++ b/src/components/adminPage/organization/deleteOrganizationModal.tsx @@ -0,0 +1,64 @@ +import { useTranslations } from "next-intl"; +import React, { useState } from "react"; +import toast from "react-hot-toast"; +import { api } from "~/utils/api"; +import { useModalStore } from "~/utils/store"; + +const DeleteOrganizationModal = ({ org }) => { + const b = useTranslations("commonButtons"); + const m = useTranslations("commonToast"); + const [input, setInput] = useState({ orgNameDelete: "" }); + const { closeModal } = useModalStore((state) => state); + const { mutate: deleteOrg } = api.org.deleteOrg.useMutation(); + const { refetch: refetchOrg } = api.org.getAllOrg.useQuery(); + const inputHandler = (e: React.ChangeEvent) => { + setInput({ + ...input, + [e.target.name]: e.target.value, + }); + }; + + return ( +
+

Are you sure you want to delete this organization?

+

+ This action will permanently delete the organization along with all its networks, + members, and related data. This action cannot be undone. +

+

+ Please confirm that you want to proceed with deleting the organization. +

+ +
+ +
+
+ ); +}; + +export default DeleteOrganizationModal; diff --git a/src/components/adminPage/organization/organizationInviteModal.tsx b/src/components/adminPage/organization/organizationInviteModal.tsx new file mode 100644 index 00000000..cbe58c6f --- /dev/null +++ b/src/components/adminPage/organization/organizationInviteModal.tsx @@ -0,0 +1,235 @@ +import { Role } from "@prisma/client"; +import { useTranslations } from "next-intl"; +import React, { useState } from "react"; +import toast from "react-hot-toast"; +import ScrollableDropdown from "~/components/elements/dropdownlist"; +import { api } from "~/utils/api"; +import { useModalStore } from "~/utils/store"; + +interface Iprops { + organizationId: string; + // invite?: OrganizationInvitation & { tokenUrl: string }; +} + +const OrganizationInviteModal = ({ organizationId }: Iprops) => { + const b = useTranslations("commonButtons"); + const t = useTranslations("admin"); + const [state, setState] = useState({ + userId: null, + name: "", + role: Role.USER, + }); + + const { closeModal } = useModalStore((state) => state); + const { data: allUsers } = api.admin.getUsers.useQuery({ isAdmin: false }); + // const { refetch: refetchOrganization } = api.org.getAllOrg.useQuery(); + + const { mutate: addUser } = api.org.addUser.useMutation(); + + const dropDownHandler = (e) => { + setState({ + ...state, + role: e.target.value, + }); + }; + return ( +
+
+
+

+ {t("organization.listOrganization.invitationModal.description")} +

+ + { + setState({ ...state, userId: selectedItem.id, name: selectedItem.name }); + }} + /> +
+
+ +
+ +
+
+
+ +
+ {/*
+ + + {allUsers?.map((user) => ( + + +
*/} + + {/*
+ + +
*/} +
+ {/*
+
+ +
+ + +
+
+
*/} + {/* {inviteData?.invitationLink || invite?.email ? ( +
+
Generated Link (Click to Copy)
+
+ + toast.success( + "Link copied to clipboard. You can now send it to the user.", + ) + } + title={"copyToClipboard.title"} + > +
+ {inviteData?.invitationLink || invite?.tokenUrl} +
+
+
+
+ + +
+
+ ) : null} */} +
+ ); +}; + +export default OrganizationInviteModal; diff --git a/src/components/adminPage/users/table/accounts.tsx b/src/components/adminPage/users/table/accounts.tsx index 39a4ef8f..e9a9825b 100644 --- a/src/components/adminPage/users/table/accounts.tsx +++ b/src/components/adminPage/users/table/accounts.tsx @@ -38,7 +38,9 @@ export const Accounts = () => { { id: "id", desc: true }, ]); + const ct = useTranslations("commonTable"); const t = useTranslations("admin"); + const [globalFilter, setGlobalFilter] = useState(""); const { callModal } = useModalStore((state) => state); const [sorting, setSorting] = useState(initialSortingState); @@ -56,7 +58,7 @@ export const Accounts = () => { // minSize: 70, // }), columnHelper.accessor("name", { - header: () => {t("users.users.table.memberName")}, + header: () => {ct("header.name")}, id: "name", minSize: 350, cell: ({ getValue }) => { @@ -64,7 +66,7 @@ export const Accounts = () => { }, }), columnHelper.accessor("email", { - header: () => {t("users.users.table.email")}, + header: () => {ct("header.email")}, id: "email", }), // columnHelper.accessor("emailVerified", { @@ -80,7 +82,7 @@ export const Accounts = () => { // }, // }), columnHelper.accessor((row: ExtendedUser) => row._count?.network, { - header: () => {t("users.users.table.networks")}, + header: () => {ct("header.networks")}, id: "Networks", minSize: 20, cell: ({ getValue }) => { @@ -88,7 +90,7 @@ export const Accounts = () => { }, }), columnHelper.accessor("userGroupId", { - header: () => {t("users.users.table.group")}, + header: () => {ct("header.group")}, id: "group", minSize: 80, cell: ({ row: { original: { userGroup } } }) => { @@ -96,7 +98,7 @@ export const Accounts = () => { }, }), columnHelper.accessor("isActive", { - header: () => Account, + header: () => {ct("header.account")}, id: "isActive", minSize: 80, cell: ({ getValue }) => { @@ -104,7 +106,7 @@ export const Accounts = () => { }, }), columnHelper.accessor("role", { - header: () => {t("users.users.table.role")}, + header: () => {ct("header.role")}, id: "role", minSize: 80, cell: ({ getValue }) => { @@ -112,7 +114,7 @@ export const Accounts = () => { }, }), columnHelper.accessor("action", { - header: () => Actions, + header: () => {ct("header.actions")}, id: "action", cell: ({ row: { original } }) => { return ( diff --git a/src/components/adminPage/users/userInvitation.tsx b/src/components/adminPage/users/userInvitation.tsx index 4b634eec..a0d2bbfe 100644 --- a/src/components/adminPage/users/userInvitation.tsx +++ b/src/components/adminPage/users/userInvitation.tsx @@ -168,7 +168,7 @@ const UserInvitationLink = () => { rootFormClassName="flex flex-col space-y-2 w-6/6" size="sm" placeholder="" - buttonText={t("changeButton.generate")} + buttonText={t("commonButtons.generate")} fields={[ { name: "secret", diff --git a/src/components/auth/registerForm.tsx b/src/components/auth/registerForm.tsx index 277db991..b49a7402 100644 --- a/src/components/auth/registerForm.tsx +++ b/src/components/auth/registerForm.tsx @@ -9,8 +9,7 @@ interface FormData { email: string; password: string; name: string; - code?: string; - token?: string; + ztnetToken?: string; } const RegisterForm: React.FC = () => { @@ -22,8 +21,7 @@ const RegisterForm: React.FC = () => { email: "", password: "", name: "", - code: "", - token: invite?.toString(), + ztnetToken: "", }); const { mutate: register } = api.auth.register.useMutation(); @@ -74,10 +72,10 @@ const RegisterForm: React.FC = () => { diff --git a/src/components/elements/dropdownlist.tsx b/src/components/elements/dropdownlist.tsx new file mode 100644 index 00000000..8b2d9630 --- /dev/null +++ b/src/components/elements/dropdownlist.tsx @@ -0,0 +1,100 @@ +import React, { useState, useRef, useEffect } from "react"; +import cn from "classnames"; + +interface Iprops { + // biome-ignore lint/suspicious/noExplicitAny: + items: Record[]; + placeholder: string; + displayField: string; + idField: string; + className?: string; + // biome-ignore lint/suspicious/noExplicitAny: + onOptionSelect?: (value: any) => void; +} + +const ScrollableDropdown = ({ + items, + placeholder, + displayField, + idField, + className, + onOptionSelect, +}: Iprops) => { + const [inputValue, setInputValue] = useState(""); + const [isDropdownVisible, setIsDropdownVisible] = useState(false); + const dropdownRef = useRef(null); + const inputRef = useRef(null); + const containerRef = useRef(null); + + useEffect(() => { + const handleClickOutside = (event) => { + if ( + !dropdownRef.current?.contains(event.target) && + !inputRef.current?.contains(event.target) + ) { + setIsDropdownVisible(false); + } + }; + + document.addEventListener("mousedown", handleClickOutside); + return () => document.removeEventListener("mousedown", handleClickOutside); + }, []); + + const handleInputChange = (event) => { + setInputValue(event.target.value); + setIsDropdownVisible(true); + }; + + const handleOptionClick = (item) => { + setInputValue(item[displayField]); + setIsDropdownVisible(false); + if (onOptionSelect) { + onOptionSelect(item); + } + }; + + // Filter items based on inputValue + const filteredItems = items?.filter((item) => + item[displayField].toLowerCase().includes(inputValue.toLowerCase()), + ); + return ( +
e.preventDefault()} + > +
+ setIsDropdownVisible(true)} + /> + {isDropdownVisible && ( +
    + {filteredItems.map((item) => ( +
  • handleOptionClick(item)} + > + {item[displayField]} +
  • + ))} +
+ )} +
+
+ ); +}; + +export default ScrollableDropdown; diff --git a/src/components/elements/inputField.tsx b/src/components/elements/inputField.tsx index 45e23234..97c3a79a 100644 --- a/src/components/elements/inputField.tsx +++ b/src/components/elements/inputField.tsx @@ -67,7 +67,7 @@ const InputField = ({ showSubmitButtons = true, showCancelButton = true, }: FormProps) => { - const t = useTranslations("changeButton"); + const t = useTranslations("commonButtons"); const [showInputs, setShowInputs] = useState(openByDefault); const [formValues, setFormValues] = useState>({}); diff --git a/src/components/layouts/chatAside.tsx b/src/components/layouts/chatAside.tsx new file mode 100644 index 00000000..4285f80f --- /dev/null +++ b/src/components/layouts/chatAside.tsx @@ -0,0 +1,251 @@ +import { useRouter } from "next/router"; +import { useEffect, useRef, useState } from "react"; +import { api } from "~/utils/api"; +import { useAsideChatStore, useSocketStore } from "~/utils/store"; +import TimeAgo from "react-timeago"; +import { stringToColor } from "~/utils/randomColor"; +import { ErrorData } from "~/types/errorHandling"; +import toast from "react-hot-toast"; +import { useTranslations } from "next-intl"; + +const TimeAgoFormatter = (value: string, unit: string) => { + // Map full unit names to their abbreviations + const unitAbbreviations: { [key: string]: string } = { + second: "s ago", + minute: "m ago", + hour: "h ago", + day: "d ago", + week: "w ago", + month: "mo ago", + year: "ye ago", + }; + const abbreviation = unitAbbreviations[unit] || unit; + + return `${value} ${abbreviation}`; +}; + +const MessagesList = ({ messages }) => { + // Generate a color for the user + const userColor = stringToColor(messages.user.name); + + return ( +
+ {/* User icon */} +
+ {messages.user.name[0]} +
+ {/* Message content and timestamp */} +
+
+

{messages.user.name}

+

+ +

+
+

{messages.content}

+
+
+ ); +}; + +const ChatAside = () => { + const t = useTranslations("organization"); + + const { openChats, toggleChat } = useAsideChatStore(); + const [messages, setMessages] = useState([]); + const { messages: newMessages, hasNewMessages } = useSocketStore(); + + const [inputMsg, setInputMsg] = useState({ chatMessage: "" }); + const query = useRouter().query; + const orgId = query.orgid as string; + const messageEndRef = useRef(null); + + const { mutate: markMessagesAsRead } = api.org.markMessagesAsRead.useMutation(); + const { mutate: emitChatMsg } = api.org.sendMessage.useMutation(); + const { data: orgMessages } = api.org.getMessages.useQuery( + { organizationId: orgId }, + { + enabled: !!orgId, + }, + ); + + useEffect(() => { + if (!orgMessages) return; + setMessages(orgMessages); + }, [orgMessages]); + + useEffect(() => { + if (!newMessages[orgId] || newMessages[orgId].length === 0) { + return; + } + + setMessages((currentMessages) => { + const currentMessageIds = new Set(currentMessages.map((message) => message.id)); + const newUniqueMessages = newMessages[orgId].filter( + (message) => !currentMessageIds.has(message.id), + ); + + if (newUniqueMessages.length === 0) { + return currentMessages; // No new unique messages, no state update needed + } + + const mergedMessages = [...currentMessages, ...newUniqueMessages]; + return mergedMessages; + }); + }, [newMessages, orgId]); + + // Scroll to the bottom of the chat when new messages are added + // biome-ignore lint/correctness/useExhaustiveDependencies: + useEffect(() => { + messageEndRef.current?.scrollIntoView({ behavior: "instant" }); + }, [messages]); + + // Mark messages as read when the aside is opened + useEffect(() => { + if (openChats.includes(orgId)) { + markMessagesAsRead({ + organizationId: orgId, + }); + } + }, [openChats, orgId, markMessagesAsRead]); + + const eventHandler = (e) => { + setInputMsg({ + ...inputMsg, + [e.target.name]: e.target.value, + }); + }; + const sendMessage = (e) => { + e.preventDefault(); + + emitChatMsg( + { organizationId: orgId, message: inputMsg.chatMessage }, + { + onSuccess: () => { + setInputMsg({ chatMessage: "" }); + }, + onError: (error) => { + if ((error.data as ErrorData)?.zodError) { + const fieldErrors = (error.data as ErrorData)?.zodError.fieldErrors; + for (const field in fieldErrors) { + toast.error(`${fieldErrors[field].join(", ")}`); + } + } else if (error.message) { + toast.error(error.message); + } else { + toast.error("An unknown error occurred"); + } + }, + }, + ); + }; + return ( + <> + {/* Chat Toggle Button */} + + {/* Chat Aside Panel */} + + + ); +}; + +export default ChatAside; diff --git a/src/components/layouts/header.tsx b/src/components/layouts/header.tsx index 4c351d80..8c441590 100644 --- a/src/components/layouts/header.tsx +++ b/src/components/layouts/header.tsx @@ -47,7 +47,7 @@ const Header = () => { width="32" height="32" viewBox="0 0 512 512" - onClick={toggle} + onClick={() => toggle()} > @@ -59,7 +59,7 @@ const Header = () => { width="32" height="32" viewBox="0 0 512 512" - onClick={toggle} + onClick={() => toggle()} > diff --git a/src/components/layouts/layout.tsx b/src/components/layouts/layout.tsx index c84ef8c3..86b054c7 100644 --- a/src/components/layouts/layout.tsx +++ b/src/components/layouts/layout.tsx @@ -8,7 +8,10 @@ import Link from "next/link"; import { useRouter } from "next/router"; import { User } from "@prisma/client"; import { api } from "~/utils/api"; -import { useSidebarStore } from "~/utils/store"; +import { useSidebarStore, useAsideChatStore } from "~/utils/store"; +import ChatAside from "./chatAside"; +import { LogsFooter } from "./logFooter"; +import Modal from "../shared/modal"; type TUser = { user: User; @@ -54,6 +57,7 @@ export const LayoutAuthenticated = ({ children }: Props): JSX.Element => { const { open } = useSidebarStore(); return (
+
); }; +export const LayoutOrganizationAuthenticated = ({ children }: Props): JSX.Element => { + // if not session.user redirect to login + const { open: sidebarOpen } = useSidebarStore(); + const { openChats } = useAsideChatStore(); + + const router = useRouter(); + const orgId = router.query.orgid as string; + + return ( +
+ {/* Header */} + +
+ + {/* Main Content including Sidebar, Content, and Chat Aside */} +
+ {/* Sidebar */} + + + {/* Main Content */} +
+ {children} + {/* Logs Footer */} + +
+ + {/* Chat Aside */} + +
+
+ ); +}; export const LayoutAdminAuthenticated = ({ children, props }: Props): JSX.Element => { const { open } = useSidebarStore(); @@ -80,6 +122,7 @@ export const LayoutAdminAuthenticated = ({ children, props }: Props): JSX.Elemen } return (
+
diff --git a/src/components/networkByIdPage/networkMulticast.tsx b/src/components/networkByIdPage/networkMulticast.tsx index 3d883dab..985fc267 100644 --- a/src/components/networkByIdPage/networkMulticast.tsx +++ b/src/components/networkByIdPage/networkMulticast.tsx @@ -7,9 +7,10 @@ import { useTranslations } from "use-intl"; interface IProp { central?: boolean; + organizationId?: string; } -export const NetworkMulticast = ({ central = false }: IProp) => { +export const NetworkMulticast = ({ central = false, organizationId }: IProp) => { const t = useTranslations("networkById"); const [state, setState] = useState({ multicastLimit: "", @@ -72,6 +73,7 @@ export const NetworkMulticast = ({ central = false }: IProp) => { { nwid: network.nwid, central, + organizationId, updateParams: { multicastLimit: parseInt(state.multicastLimit), }, @@ -150,6 +152,7 @@ export const NetworkMulticast = ({ central = false }: IProp) => { { nwid: network.nwid, central, + organizationId, updateParams: { enableBroadcast: e.target.checked, }, diff --git a/src/components/networkByIdPage/networkName.tsx b/src/components/networkByIdPage/networkName.tsx index 2525953a..0a52b303 100644 --- a/src/components/networkByIdPage/networkName.tsx +++ b/src/components/networkByIdPage/networkName.tsx @@ -14,6 +14,7 @@ import { type NetworkEntity } from "~/types/local/network"; interface IProp { central?: boolean; + organizationId?: string; } const updateCache = ({ @@ -43,7 +44,7 @@ const updateCache = ({ ); }; -const NetworkName = ({ central = false }: IProp) => { +const NetworkName = ({ central = false, organizationId }: IProp) => { const t = useTranslations("networkById"); const client = useQueryClient(); const [state, setState] = useState({ @@ -88,6 +89,7 @@ const NetworkName = ({ central = false }: IProp) => { { nwid: networkById?.network?.id, central, + organizationId, updateParams: { name: state?.networkName }, }, { @@ -128,7 +130,7 @@ const NetworkName = ({ central = false }: IProp) => { return (
{t("networkName")} - + {state.editNetworkName ? (
{ +export const NetworkPrivatePublic = ({ central = false, organizationId }: IProp) => { const t = useTranslations(); const { query } = useRouter(); const client = useQueryClient(); @@ -62,6 +63,7 @@ export const NetworkPrivatePublic = ({ central = false }: IProp) => { privatePublicNetwork( { updateParams: { private: privateNetwork }, + organizationId, nwid: query.id as string, central, }, @@ -89,25 +91,23 @@ export const NetworkPrivatePublic = ({ central = false }: IProp) => { if (isLoading) return
Loading
; return ( -
-
- privateHandler(true)} - faded={!network.private} - title={t("networkById.privatePublicSwitch.privateCardTitle")} - rootClassName="min-w-full sm:min-w-min transition ease-in-out delay-150 hover:-translate-y-1 border border-success border-2 rounded-md solid cursor-pointer bg-transparent text-inherit flex-1 " - iconClassName="text-green-500" - content={t("networkById.privatePublicSwitch.privateCardContent")} - /> - privateHandler(false)} - faded={network.private} - title={t("networkById.privatePublicSwitch.publicCardTitle")} - rootClassName="transition ease-in-out delay-150 hover:-translate-y-1 border border-red-500 border-2 rounded-md solid cursor-pointer bg-transparent text-inherit flex-1" - iconClassName="text-warning" - content={t("networkById.privatePublicSwitch.publicCardContent")} - /> -
+
+ privateHandler(true)} + faded={!network.private} + title={t("networkById.privatePublicSwitch.privateCardTitle")} + rootClassName="sm:min-w-min transition ease-in-out delay-150 hover:-translate-y-1 border border-success border-2 rounded-md solid cursor-pointer bg-transparent text-inherit " + iconClassName="text-green-500" + content={t("networkById.privatePublicSwitch.privateCardContent")} + /> + privateHandler(false)} + faded={network.private} + title={t("networkById.privatePublicSwitch.publicCardTitle")} + rootClassName="transition ease-in-out delay-150 hover:-translate-y-1 border border-red-500 border-2 rounded-md solid cursor-pointer bg-transparent text-inherit" + iconClassName="text-warning" + content={t("networkById.privatePublicSwitch.publicCardContent")} + />
); }; diff --git a/src/components/networkByIdPage/networkRoutes.tsx b/src/components/networkByIdPage/networkRoutes.tsx index 14f68306..5723ee07 100644 --- a/src/components/networkByIdPage/networkRoutes.tsx +++ b/src/components/networkByIdPage/networkRoutes.tsx @@ -13,9 +13,11 @@ const initialRouteInput = { interface IProp { central?: boolean; + organizationId?: string; } -export const NettworkRoutes = ({ central = false }: IProp) => { +export const NettworkRoutes = ({ central = false, organizationId }: IProp) => { + const b = useTranslations("commonButtons"); const t = useTranslations("networkById"); const [showRouteInput, setShowRouteInput] = useState(false); const [routeInput, setRouteInput] = useState(initialRouteInput); @@ -51,6 +53,7 @@ export const NettworkRoutes = ({ central = false }: IProp) => { updateManageRoutes( { updateParams: { routes: [...newRouteArr] }, + organizationId, nwid: query.id as string, central, }, @@ -71,6 +74,7 @@ export const NettworkRoutes = ({ central = false }: IProp) => { updateParams: { routes: [...network.routes, { ...routeInput }], }, + organizationId, nwid: query.id as string, central, }, @@ -164,13 +168,13 @@ export const NettworkRoutes = ({ central = false }: IProp) => { className="input input-bordered input-primary input-xs w-3/6 rounded-md" /> ) : null} diff --git a/src/components/networkByIdPage/organization/addOrgForm.tsx b/src/components/networkByIdPage/organization/addOrgForm.tsx new file mode 100644 index 00000000..d16891fe --- /dev/null +++ b/src/components/networkByIdPage/organization/addOrgForm.tsx @@ -0,0 +1,87 @@ +import React from "react"; +import InputFields from "~/components/elements/inputField"; +import { ErrorData } from "~/types/errorHandling"; +import { api } from "~/utils/api"; +import toast from "react-hot-toast"; +import { useTranslations } from "next-intl"; + +const AddOrgForm = () => { + const b = useTranslations("commonButtons"); + const t = useTranslations("admin"); + const { refetch: refecthOrg } = api.org.getAllOrg.useQuery(); + const { refetch: refetchMe } = api.auth.me.useQuery(); + const { refetch: refetchUserOrg } = api.org.getOrgIdbyUserid.useQuery(); + + const { mutate: addOrg } = api.org.createOrg.useMutation({ + onError: (error) => { + if ((error.data as ErrorData)?.zodError) { + const fieldErrors = (error.data as ErrorData)?.zodError.fieldErrors; + for (const field in fieldErrors) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/restrict-template-expressions, @typescript-eslint/no-unsafe-call + toast.error(`${fieldErrors[field].join(", ")}`); + } + } else if (error.message) { + toast.error(error.message); + } else { + toast.error("An unknown error occurred"); + } + }, + onSuccess: () => { + toast.success("Organization added successfully"); + refetchMe(); + refecthOrg(); + // will load websocket in _app.tsx + refetchUserOrg(); + }, + }); + return ( +
+ + new Promise((resolve) => { + void addOrg( + { + ...params, + }, + { + onSuccess: () => { + resolve(true); + }, + }, + ); + }) + } + /> +
+ ); +}; + +export default AddOrgForm; diff --git a/src/components/networkByIdPage/organization/listOrganizations.tsx b/src/components/networkByIdPage/organization/listOrganizations.tsx new file mode 100644 index 00000000..16073683 --- /dev/null +++ b/src/components/networkByIdPage/organization/listOrganizations.tsx @@ -0,0 +1,137 @@ +import { useTranslations } from "next-intl"; +import React, { useState } from "react"; +import DeleteOrganizationModal from "~/components/adminPage/organization/deleteOrganizationModal"; +import OrganizationInviteModal from "~/components/adminPage/organization/organizationInviteModal"; +import EditOrganizationModal from "~/components/organization/editOrgModal"; +import { OrganizationUserTable } from "~/components/organization/userTable"; +import { api } from "~/utils/api"; +import { useModalStore } from "~/utils/store"; + +const ListOrganizations = () => { + const t = useTranslations("admin"); + const b = useTranslations("commonButtons"); + const [openOrgId, setOpenOrgId] = useState(null); + const { data: userOrgs } = api.org.getAllOrg.useQuery(); + const { callModal } = useModalStore((state) => state); + + const toggleUsersTable = (orgId) => { + if (openOrgId === orgId) { + // If the table for this org is already open, close it + setOpenOrgId(null); + } else { + // Open the table for the clicked org + setOpenOrgId(orgId); + } + }; + return ( +
+ {userOrgs?.map((org) => ( +
+

+ {t("organization.listOrganization.organizationName")}{" "} + {org.orgName} +

+

+ {t("organization.listOrganization.description")}{" "} + {org.description} +

+

+ {t("organization.listOrganization.numberOfMembers")}{" "} + {org?.users?.length} +

+

+ {org?.invitations?.length > 0 ? ( +

+ {t("organization.listOrganization.pendingInvitations")} +
+ {org?.invitations?.map((invite) => ( + + ))} +
+
+ ) : null} +

+
+
+ + + +
+ +
+ {openOrgId === org.id ? ( + + ) : null} +
+ ))} +
+ ); +}; + +export default ListOrganizations; diff --git a/src/components/networkByIdPage/table/memberEditCell.tsx b/src/components/networkByIdPage/table/memberEditCell.tsx index 9400a69c..bf1eb66b 100644 --- a/src/components/networkByIdPage/table/memberEditCell.tsx +++ b/src/components/networkByIdPage/table/memberEditCell.tsx @@ -9,13 +9,16 @@ import Input from "~/components/elements/input"; import { CopyToClipboard } from "react-copy-to-clipboard"; import { type MemberEntity } from "~/types/local/member"; import { toRfc4193Ip, sixPlane } from "~/utils/IPv6"; +import { ErrorData } from "~/types/errorHandling"; interface IProp { nwid: string; central: boolean; + organizationId?: string; } -const MemberEditCell = ({ nwid, central = false }: IProp) => { +const MemberEditCell = ({ nwid, central = false, organizationId }: IProp) => { + const c = useTranslations("commonTable"); const t = useTranslations("networkById"); const { data: networkById, refetch: refetchNetworkById } = @@ -29,10 +32,34 @@ const MemberEditCell = ({ nwid, central = false }: IProp) => { const { data: me } = api.auth.me.useQuery(); const { mutate: updateMemberDatabaseOnly } = - api.networkMember.UpdateDatabaseOnly.useMutation(); + api.networkMember.UpdateDatabaseOnly.useMutation({ + onError: (error) => { + if ((error.data as ErrorData)?.zodError) { + const fieldErrors = (error.data as ErrorData)?.zodError.fieldErrors; + for (const field in fieldErrors) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call, @typescript-eslint/restrict-template-expressions + toast.error(`${fieldErrors[field].join(", ")}`); + } + } else if (error.message) { + toast.error(error.message); + } else { + toast.error(t("addMemberById.error.unknown")); + } + }, + }); const { mutate: updateMember } = api.networkMember.Update.useMutation({ - onError: (e) => { - void toast.error(e?.message); + onError: (error) => { + if ((error.data as ErrorData)?.zodError) { + const fieldErrors = (error.data as ErrorData)?.zodError.fieldErrors; + for (const field in fieldErrors) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call, @typescript-eslint/restrict-template-expressions + toast.error(`${fieldErrors[field].join(", ")}`); + } + } else if (error.message) { + toast.error(error.message); + } else { + toast.error(t("addMemberById.error.unknown")); + } }, onSuccess: () => refetchNetworkById(), }); @@ -45,6 +72,7 @@ const MemberEditCell = ({ nwid, central = false }: IProp) => { { updateParams: { ipAssignments: [...newIpPool] }, memberId: id, + organizationId, nwid, central, }, @@ -79,6 +107,7 @@ const MemberEditCell = ({ nwid, central = false }: IProp) => { nwid, id: original.id, central, + organizationId, updateParams: { name: value as string, }, @@ -137,11 +166,7 @@ const MemberEditCell = ({ nwid, central = false }: IProp) => { const has6plane = networkById?.network?.v6AssignMode?.["6plane"]; if (!original.ipAssignments?.length && !hasRfc4193 && !has6plane) { - return ( -

- {t("networkMembersTable.column.ipAssignments.notAssigned")} -

- ); + return

{c("header.ipAssignments.notAssigned")}

; } const rfc4193Ip = hasRfc4193 ? toRfc4193Ip(nwid, original?.id) : undefined; @@ -162,8 +187,10 @@ const MemberEditCell = ({ nwid, central = false }: IProp) => { }; return (
- {generateClipboardElement(hasRfc4193, rfc4193Ip)} - {generateClipboardElement(has6plane, sixPlaneIp)} +
+ {generateClipboardElement(hasRfc4193, rfc4193Ip)} + {generateClipboardElement(has6plane, sixPlaneIp)} +
{original?.ipAssignments?.map((assignedIp) => { const subnetMatch = isIPInSubnet(assignedIp, networkById.network?.routes); diff --git a/src/components/networkByIdPage/table/memberHeaderColumns.tsx b/src/components/networkByIdPage/table/memberHeaderColumns.tsx index 6934fb8d..48b0699e 100644 --- a/src/components/networkByIdPage/table/memberHeaderColumns.tsx +++ b/src/components/networkByIdPage/table/memberHeaderColumns.tsx @@ -7,7 +7,6 @@ import { useTranslations } from "next-intl"; import TimeAgo from "react-timeago"; import { type ColumnDef, createColumnHelper, Row } from "@tanstack/react-table"; import { type NetworkMemberNotation, type MemberEntity } from "~/types/local/member"; -import { User, UserOptions } from "@prisma/client"; enum ConnectionStatus { Offline = 0, @@ -20,12 +19,7 @@ enum ConnectionStatus { interface IProp { nwid: string; central: boolean; -} - -interface UserExtended extends User { - options: UserOptions & { - deAuthorizeWarning: boolean; - }; + organizationId?: string; } const sortingMemberHex = ( @@ -115,10 +109,12 @@ const sortingIpAddress = ( return 0; }; -export const MemberHeaderColumns = ({ nwid, central = false }: IProp) => { +export const MemberHeaderColumns = ({ nwid, central = false, organizationId }: IProp) => { + const b = useTranslations("commonButtons"); + const c = useTranslations("commonTable"); const t = useTranslations(); const { callModal } = useModalStore((state) => state); - const { data: me } = api.auth.me.useQuery(); + const { data: me } = api.auth.me.useQuery(); const { data: networkById, refetch: refetchNetworkById } = api.network.getNetworkById.useQuery( { @@ -156,9 +152,7 @@ export const MemberHeaderColumns = ({ nwid, central = false }: IProp) => { }, ), columnHelper.accessor("authorized", { - header: () => ( - {t("networkById.networkMembersTable.column.authorized")} - ), + header: () => {c("header.authorized")}, id: "authorized", cell: ({ getValue, row: { original } }) => { return ( @@ -178,6 +172,7 @@ export const MemberHeaderColumns = ({ nwid, central = false }: IProp) => { nwid, memberId: original.id, central, + organizationId, updateParams: { authorized }, }, { onSuccess: () => void refetchNetworkById() }, @@ -190,13 +185,13 @@ export const MemberHeaderColumns = ({ nwid, central = false }: IProp) => { nwid, memberId: original.id, central, + organizationId, updateParams: { authorized: event.target.checked }, }, { onSuccess: () => void refetchNetworkById() }, ); } }} - // className="checkbox-error checkbox" className="checkbox-success checkbox checkbox-xs sm:checkbox-sm" /> @@ -204,24 +199,22 @@ export const MemberHeaderColumns = ({ nwid, central = false }: IProp) => { }, }), columnHelper.accessor("name", { - header: () => {t("networkById.networkMembersTable.column.name")}, + header: () => {c("header.name")}, id: "name", }), columnHelper.accessor("id", { - header: () => {t("networkById.networkMembersTable.column.id")}, + header: () => {c("header.id")}, id: "id", sortingFn: sortingMemberHex, cell: (info) => info.getValue(), }), columnHelper.accessor("ipAssignments", { - header: () => ( - {t("networkById.networkMembersTable.column.ipAssignments.header")} - ), + header: () => {c("header.ipAssignments.header")}, id: "ipAssignments", sortingFn: sortingIpAddress, }), columnHelper.accessor("creationTime", { - header: () => {t("networkById.networkMembersTable.column.created")}, + header: () => {c("header.created")}, id: "creationTime", cell: (info) => { const createdDate = new Date(info.getValue()); @@ -250,9 +243,7 @@ export const MemberHeaderColumns = ({ nwid, central = false }: IProp) => { return row?.peers?.physicalAddress; }, { - header: () => ( - {t("networkById.networkMembersTable.column.physicalIp.header")} - ), + header: () => {c("header.physicalIp.header")}, sortDescFirst: true, id: "physicalAddress", sortUndefined: -1, @@ -263,7 +254,7 @@ export const MemberHeaderColumns = ({ nwid, central = false }: IProp) => { if (!centralPhysicalAddress || typeof centralPhysicalAddress !== "string") return ( - {t("networkById.networkMembersTable.column.physicalIp.unknownValue")} + {c("header.physicalIp.unknownValue")} ); @@ -273,7 +264,7 @@ export const MemberHeaderColumns = ({ nwid, central = false }: IProp) => { if (!physicalAddress || typeof physicalAddress !== "string") return ( - {t("networkById.networkMembersTable.column.physicalIp.unknownValue")} + {c("header.physicalIp.unknownValue")} ); @@ -282,9 +273,7 @@ export const MemberHeaderColumns = ({ nwid, central = false }: IProp) => { }, ), columnHelper.accessor("conStatus", { - header: () => ( - {t("networkById.networkMembersTable.column.conStatus.header")} - ), + header: () => {c("header.conStatus.header")}, id: "conStatus", cell: ({ row: { original } }) => { const lastSeen = new Date(original?.lastSeen); @@ -325,7 +314,7 @@ export const MemberHeaderColumns = ({ nwid, central = false }: IProp) => { // The user is considered offline return ( - {t("networkById.networkMembersTable.column.conStatus.offline")} + {c("header.conStatus.offline")} ); @@ -346,9 +335,9 @@ export const MemberHeaderColumns = ({ nwid, central = false }: IProp) => { - {t("networkById.networkMembersTable.column.conStatus.relayed")} + {c("header.conStatus.relayed")} ); } @@ -359,8 +348,8 @@ export const MemberHeaderColumns = ({ nwid, central = false }: IProp) => { ) { const directTitle = original.conStatus === ConnectionStatus.DirectLAN - ? t("networkById.networkMembersTable.column.conStatus.directLan") - : t("networkById.networkMembersTable.column.conStatus.directWan"); + ? c("header.conStatus.directLan") + : c("header.conStatus.directWan"); const versionInfo = original.peers?.version && original.peers.version !== "-1.-1.-1" ? ` (v${original.peers.version})` @@ -368,7 +357,7 @@ export const MemberHeaderColumns = ({ nwid, central = false }: IProp) => { return (
- {t("networkById.networkMembersTable.column.conStatus.direct", { + {c("header.conStatus.direct", { version: versionInfo, })}{" "}
@@ -377,16 +366,14 @@ export const MemberHeaderColumns = ({ nwid, central = false }: IProp) => { return ( - {t("networkById.networkMembersTable.column.conStatus.offline")} + {c("header.conStatus.offline")} ); }, }), columnHelper.accessor("action", { - header: () => ( - {t("networkById.networkMembersTable.column.actions.header")} - ), + header: () => {c("header.actions")}, id: "action", cell: ({ row: { original } }) => { return ( @@ -408,13 +395,14 @@ export const MemberHeaderColumns = ({ nwid, central = false }: IProp) => { nwid={original.nwid} memberId={original.id} central={central} + organizationId={organizationId} /> ), }) } className="btn btn-outline btn-xs rounded-sm" > - {t("networkById.networkMembersTable.column.actions.optionBtn")} + {b("options")}
); @@ -422,7 +410,6 @@ export const MemberHeaderColumns = ({ nwid, central = false }: IProp) => { }), ], // this is needed so the ip in table is updated accordingly - // eslint-disable-next-line react-hooks/exhaustive-deps [networkById?.network], ); diff --git a/src/components/networkByIdPage/table/networkMembersTable.tsx b/src/components/networkByIdPage/table/networkMembersTable.tsx index 44271179..6d912f3d 100644 --- a/src/components/networkByIdPage/table/networkMembersTable.tsx +++ b/src/components/networkByIdPage/table/networkMembersTable.tsx @@ -30,11 +30,11 @@ declare module "@tanstack/react-table" { interface IProp { nwid: string; central: boolean; + organizationId?: string; } - const LOCAL_STORAGE_KEY = "membersTableSorting"; -export const NetworkMembersTable = ({ nwid, central = false }: IProp) => { +export const NetworkMembersTable = ({ nwid, central = false, organizationId }: IProp) => { // Load initial state from localStorage or set to default const initialSortingState = getLocalStorageItem(LOCAL_STORAGE_KEY, [ { id: "id", desc: true }, @@ -69,8 +69,8 @@ export const NetworkMembersTable = ({ nwid, central = false }: IProp) => { // const [data, setData] = useState(() => makeNetworkMemberData(11)); const [data, setData] = useState(networkById?.members ?? []); - const columnsHeader = MemberHeaderColumns({ nwid, central }); - const defaultColumn = MemberEditCell({ nwid, central }); + const columnsHeader = MemberHeaderColumns({ nwid, central, organizationId }); + const defaultColumn = MemberEditCell({ nwid, central, organizationId }); const [autoResetPageIndex, skipAutoResetPageIndex] = useSkipper(); const table = useReactTable({ data, diff --git a/src/components/networkPage/centralNetworkTable.tsx b/src/components/networkPage/centralNetworkTable.tsx index 153dacfe..89faa59c 100644 --- a/src/components/networkPage/centralNetworkTable.tsx +++ b/src/components/networkPage/centralNetworkTable.tsx @@ -43,7 +43,7 @@ export const CentralNetworkTable = ({ tableData = [] }) => { ]); const router = useRouter(); - const t = useTranslations("networksTable"); + const t = useTranslations("commonTable"); const [globalFilter, setGlobalFilter] = useState(""); const [sorting, setSorting] = useState(initialSortingState); @@ -53,20 +53,20 @@ export const CentralNetworkTable = ({ tableData = [] }) => { () => [ columnHelper.accessor("name", { cell: (info) => info.getValue(), - header: () => {t("name")}, + header: () => {t("header.name")}, }), columnHelper.accessor("description", { size: 300, cell: (info) => , - header: () => {t("description")}, + header: () => {t("header.description")}, }), columnHelper.accessor("nwid", { cell: (info) => info.getValue(), - header: () => {t("networkId")}, + header: () => {t("header.networkId")}, // footer: (info) => info.column.id, }), columnHelper.accessor("totalMemberCount", { - header: () => {t("members")}, + header: () => {t("header.members")}, cell: (info) => info.getValue(), }), ], @@ -130,7 +130,7 @@ export const CentralNetworkTable = ({ tableData = [] }) => { value={globalFilter ?? ""} onChange={(value) => setGlobalFilter(String(value))} className="font-lg border-block border p-2 shadow" - placeholder={t("networkSearchPlaceholder")} + placeholder={t("search.networkSearchPlaceholder")} />
diff --git a/src/components/networkPage/networkTable.tsx b/src/components/networkPage/networkTable.tsx index f3e190f8..51442bb1 100644 --- a/src/components/networkPage/networkTable.tsx +++ b/src/components/networkPage/networkTable.tsx @@ -38,7 +38,7 @@ const TruncateText = ({ text }: { text: string }) => { }; export const NetworkTable = ({ tableData = [] }) => { const router = useRouter(); - const t = useTranslations("networksTable"); + const t = useTranslations("commonTable"); // Load initial state from localStorage or set to default const initialSortingState = getLocalStorageItem(LOCAL_STORAGE_KEY, [ @@ -60,20 +60,20 @@ export const NetworkTable = ({ tableData = [] }) => { () => [ columnHelper.accessor("name", { cell: (info) => info.getValue(), - header: () => {t("name")}, + header: () => {t("header.name")}, }), columnHelper.accessor("description", { size: 300, cell: (info) => , - header: () => {t("description")}, + header: () => {t("header.description")}, }), columnHelper.accessor("nwid", { cell: (info) => info.getValue(), - header: () => {t("networkId")}, + header: () => {t("header.networkId")}, // footer: (info) => info.column.id, }), columnHelper.accessor("members", { - header: () => {t("members")}, + header: () => {t("header.members")}, cell: ({ row: { original } }) => { if (!Array.isArray(original.networkMembers)) return 0; return {original.networkMembers.length}; @@ -140,7 +140,7 @@ export const NetworkTable = ({ tableData = [] }) => { value={globalFilter ?? ""} onChange={(value) => setGlobalFilter(String(value))} className="font-lg border-block border p-2 shadow" - placeholder={t("networkSearchPlaceholder")} + placeholder={t("search.networkSearchPlaceholder")} />
diff --git a/src/components/organization/editOrgModal.tsx b/src/components/organization/editOrgModal.tsx new file mode 100644 index 00000000..cc34f667 --- /dev/null +++ b/src/components/organization/editOrgModal.tsx @@ -0,0 +1,95 @@ +import React, { useEffect, useState } from "react"; +import { api } from "~/utils/api"; +import toast from "react-hot-toast"; +import { useModalStore } from "~/utils/store"; +import { useTranslations } from "next-intl"; +import Input from "../elements/input"; + +interface Iprops { + organizationId: string; +} + +const EditOrganizationModal = ({ organizationId }: Iprops) => { + const b = useTranslations("commonButtons"); + const t = useTranslations("admin"); + const [input, setInput] = useState({ orgDescription: "", orgName: "" }); + const { closeModal } = useModalStore((state) => state); + const { refetch: refecthAllOrg } = api.org.getAllOrg.useQuery(); + const { data: orgData } = api.org.getOrgById.useQuery({ + organizationId, + }); + const { mutate: updateOrg } = api.org.updateMeta.useMutation(); + useEffect(() => { + if (orgData) { + setInput({ + orgDescription: orgData.description, + orgName: orgData.orgName, + }); + } + }, [orgData]); + + const inputHandler = (e: React.ChangeEvent) => { + setInput({ + ...input, + [e.target.name]: e.target.value, + }); + }; + return ( +
+ +