diff --git a/.env.example b/.env.example index e490a6ef4..0eca03648 100644 --- a/.env.example +++ b/.env.example @@ -1,4 +1,5 @@ VITE_APPWRITE_ENDPOINT=http://localhost/v1 VITE_APPWRITE_GROWTH_ENDPOINT= VITE_GA_PROJECT= -VITE_CONSOLE_MODE=self-hosted \ No newline at end of file +VITE_CONSOLE_MODE=self-hosted +VITE_STRIPE_PUBLIC_KEY= diff --git a/package-lock.json b/package-lock.json index 38c9bd42c..464a87ffa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,12 +6,13 @@ "": { "name": "@appwrite/console", "dependencies": { - "@appwrite.io/console": "^0.3.0", - "@appwrite.io/pink": "0.1.0-next.9", - "@appwrite.io/pink-icons": "^0.1.0-next.9", + "@appwrite.io/console": "^0.4.2", + "@appwrite.io/pink": "0.2.0", + "@appwrite.io/pink-icons": "0.2.0", "@popperjs/core": "^2.11.8", "@sentry/svelte": "^7.66.0", "@sentry/tracing": "^7.66.0", + "@stripe/stripe-js": "^2.2.0", "ai": "^2.2.11", "analytics": "^0.8.9", "dayjs": "^1.11.9", @@ -28,6 +29,8 @@ "web-vitals": "^3.4.0" }, "devDependencies": { + "@melt-ui/pp": "^0.1.4", + "@melt-ui/svelte": "^0.61.2", "@playwright/test": "^1.37.1", "@sveltejs/adapter-static": "^2.0.3", "@sveltejs/kit": "^1.24.0", @@ -53,6 +56,7 @@ "svelte-check": "^3.5.1", "svelte-jester": "^2.3.2", "svelte-preprocess": "^5.0.4", + "svelte-sequential-preprocessor": "^2.0.1", "tslib": "^2.6.2", "typescript": "^5.2.2", "vite": "^4.4.9", @@ -72,9 +76,9 @@ } }, "node_modules/@adobe/css-tools": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.3.1.tgz", - "integrity": "sha512-/62yikz7NLScCGAAST5SHdnjaDJQBDq0M2muyRTpf2VQhw6StBg2ALiu73zSJQ4fMVLA+0uBhBHAle7Wg+2kSg==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.3.2.tgz", + "integrity": "sha512-DA5a1C0gD/pLOvhv33YMrbf2FK3oUzwNl9oOJqE4XVjuEtt6XIakRcsd7eLiOSPkp1kTRQGICTA8cKra/vFbjw==", "dev": true }, "node_modules/@ampproject/remapping": { @@ -155,36 +159,36 @@ "integrity": "sha512-TD+xbmsBLyYy/IxFimW/YL/9L2IEnM7/EoV9Aeh56U64Ify8o27HJcKjo38XY9Tcn0uOq1AX3thkKgvtWvwFQg==" }, "node_modules/@appwrite.io/console": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@appwrite.io/console/-/console-0.3.0.tgz", - "integrity": "sha512-XHKQHirzQliXoDpMLakSdXwpq9aPoeTABNhW8Z7MK3p6oBfp2gMplDD43Fbd91JREXoJ+RG8okX0z0nIc6hDiQ==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@appwrite.io/console/-/console-0.4.2.tgz", + "integrity": "sha512-WUltkC5q7RIK7TDCb+qTXq2cPtBek9k98Ilqcn8Lv3rN5ZuK0x33AwcpTAEPD0DE9phWXmvoV1a8H5PGMcGKew==", "dependencies": { "cross-fetch": "3.1.5", "isomorphic-form-data": "2.0.0" } }, "node_modules/@appwrite.io/pink": { - "version": "0.1.0-next.9", - "resolved": "https://registry.npmjs.org/@appwrite.io/pink/-/pink-0.1.0-next.9.tgz", - "integrity": "sha512-W5xVm2ZXlEqbbKv0GkpnM5saunDKdSfuhWouLnORsonENGFsG529PxRjqeClz4zrlkt2x1DiwN175wpgV3GoEQ==", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@appwrite.io/pink/-/pink-0.2.0.tgz", + "integrity": "sha512-ni6O/yPiWkCYQ68PNcbmus6QrPpIEl7xmzKHU2dkV2L19RVio8thtBtT9ckJJ8uBMGsczASWs0fUqOxIvBmtNw==", "dependencies": { - "@appwrite.io/pink-icons": "0.1.0-next.9", + "@appwrite.io/pink-icons": "0.2.0", "normalize.css": "^8.0.1", - "the-new-css-reset": "^1.7.3" + "the-new-css-reset": "^1.11.2" } }, "node_modules/@appwrite.io/pink-icons": { - "version": "0.1.0-next.9", - "resolved": "https://registry.npmjs.org/@appwrite.io/pink-icons/-/pink-icons-0.1.0-next.9.tgz", - "integrity": "sha512-6t4Pqt/xugjpJQyaMx1u/7Gt9CkW5iItDAgUKcIMm84E4NbDJq8ZdAhhvctGQQppKUgHDPi+6x1XveUUd7tdbg==" + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@appwrite.io/pink-icons/-/pink-icons-0.2.0.tgz", + "integrity": "sha512-wThBUGdvpwT0q2fcUapiugfBiB4RFDvTlW6p+U7Dol61mmCpNteFSIoBPiPJzN5015n1v4UEWL/rdOia4CWdBQ==" }, "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.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", "dev": true, "dependencies": { - "@babel/highlight": "^7.22.13", + "@babel/highlight": "^7.23.4", "chalk": "^2.4.2" }, "engines": { @@ -263,9 +267,9 @@ } }, "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.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", + "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", "dev": true, "peer": true, "engines": { @@ -273,22 +277,22 @@ } }, "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.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.5.tgz", + "integrity": "sha512-Cwc2XjUrG4ilcfOw4wBAK+enbdgwAcAJCfGUItPBKR7Mjw4aEfAFYrLxeRp4jWgtNIKn3n2AlBOfwwafl+42/g==", "dev": true, "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.5", "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-module-transforms": "^7.23.0", - "@babel/helpers": "^7.23.2", - "@babel/parser": "^7.23.0", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helpers": "^7.23.5", + "@babel/parser": "^7.23.5", "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.2", - "@babel/types": "^7.23.0", + "@babel/traverse": "^7.23.5", + "@babel/types": "^7.23.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -314,13 +318,13 @@ } }, "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.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.5.tgz", + "integrity": "sha512-BPssCHrBD+0YrxviOa3QzpqwhNIXKEtOa2jQrm4FlmkC2apYgRnQcmPWiGZDlGxiNtltnUFolMe8497Esry+jA==", "dev": true, "peer": true, "dependencies": { - "@babel/types": "^7.23.0", + "@babel/types": "^7.23.5", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -407,9 +411,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, "peer": true, "dependencies": { @@ -463,9 +467,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==", "dev": true, "peer": true, "engines": { @@ -482,9 +486,9 @@ } }, "node_modules/@babel/helper-validator-option": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", - "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", "dev": true, "peer": true, "engines": { @@ -492,24 +496,24 @@ } }, "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.5", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.5.tgz", + "integrity": "sha512-oO7us8FzTEsG3U6ag9MfdF1iA/7Z6dz+MtFhifZk8C8o453rGJFFWUP1t+ULM9TUIAzC9uxXEiXjOiVMyd7QPg==", "dev": true, "peer": true, "dependencies": { "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.2", - "@babel/types": "^7.23.0" + "@babel/traverse": "^7.23.5", + "@babel/types": "^7.23.5" }, "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", @@ -592,9 +596,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.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.5.tgz", + "integrity": "sha512-hOOqoiNXrmGdFbhgCzu6GiURxUgM27Xwd/aPuu8RfHEZPBzL1Z54okAHAQjXfcQNwvrlkAmAp4SlRTZ45vlthQ==", "peer": true, "bin": { "parser": "bin/babel-parser.js" @@ -669,9 +673,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, "peer": true, "dependencies": { @@ -779,9 +783,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, "peer": true, "dependencies": { @@ -795,9 +799,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.5", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.5.tgz", + "integrity": "sha512-NdUTHcPe4C99WxPub+K9l9tK5/lV4UXIoaHSYgzco9BCyjKAAwzdBI+wWtYqHt7LJdbo74ZjRPJgzVweq1sz0w==", "dev": true, "dependencies": { "regenerator-runtime": "^0.14.0" @@ -822,20 +826,20 @@ } }, "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.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.5.tgz", + "integrity": "sha512-czx7Xy5a6sapWWRx61m1Ke1Ra4vczu1mCTtJam5zRTBOonfdJ+S/B6HYmGYu3fJtr8GGET3si6IhgWVBhJ/m8w==", "dev": true, "peer": true, "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.5", "@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.5", + "@babel/types": "^7.23.5", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -854,13 +858,13 @@ } }, "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.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.5.tgz", + "integrity": "sha512-ON5kSOJwVO6xXVRTvOI0eOnWe7VdUcIpsovGo9U/Br4Ie4UVFQTboO2cYnDhAGU6Fp+UxSiT+pMft0SMHfuq6w==", "dev": true, "peer": true, "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" }, @@ -1252,9 +1256,9 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.3.tgz", - "integrity": "sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, "dependencies": { "ajv": "^6.12.4", @@ -1275,23 +1279,48 @@ } }, "node_modules/@eslint/js": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.53.0.tgz", - "integrity": "sha512-Kn7K8dx/5U6+cT1yEhpX1w4PCSg0M+XyRILPgvwcEBjerFWCwQj5sbr3/VmxqV0JGHCBCzyd6LxypEuehypY1w==", + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.55.0.tgz", + "integrity": "sha512-qQfo2mxH5yVom1kacMtZZJFVdW+E70mqHMJvVg6WTLo+VBuQJ4TojZlfWBjK0ve5BdEeNAVxOsl/nvNMpJOaJA==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/@fastify/busboy": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.0.0.tgz", - "integrity": "sha512-JUFJad5lv7jxj926GPgymrWQxxjPYuJNiNjNMzqT+HiuP6Vl3dk5xzG+8sTX96np0ZAluvaMzPsjhHZ5rNuNQQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.0.tgz", + "integrity": "sha512-+KpH+QxZU7O4675t3mnkQKcZZg56u+K/Ct2K+N2AZYNVK8kyeo/bI18tI8aPm3tvNNRyTWfj6s5tnGNlcbQRsA==", "dev": true, "engines": { "node": ">=14" } }, + "node_modules/@floating-ui/core": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.5.2.tgz", + "integrity": "sha512-Ii3MrfY/GAIN3OhXNzpCKaLxHQfJF9qvwq/kEJYdqDxeIHa01K8sldugal6TmeeXl+WMvhv9cnVzUTaFFJF09A==", + "dev": true, + "dependencies": { + "@floating-ui/utils": "^0.1.3" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.5.3.tgz", + "integrity": "sha512-ClAbQnEqJAKCJOEbbLo5IUlZHkNszqhuxS4fHAVxRPXPya6Ysf2G8KypnYcOTpx6I8xcgF9bbHb6g/2KpbV8qA==", + "dev": true, + "dependencies": { + "@floating-ui/core": "^1.4.2", + "@floating-ui/utils": "^0.1.3" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.1.6.tgz", + "integrity": "sha512-OfX7E2oUDYxtBvsuS4e/jSn4Q9Qb6DzgeYtsAdkPZ47znpoNsMgZw0+tVijiv3uGNR6dgNlty6r9rzIzHjtd/A==", + "dev": true + }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.13", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", @@ -1325,6 +1354,15 @@ "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", "dev": true }, + "node_modules/@internationalized/date": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/@internationalized/date/-/date-3.5.0.tgz", + "integrity": "sha512-nw0Q+oRkizBWMioseI8+2TeUPEyopJVz5YxoYVzR0W1v+2YytiYah7s/ot35F149q/xAg4F1gT/6eTd+tsUpFQ==", + "dev": true, + "dependencies": { + "@swc/helpers": "^0.5.0" + } + }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -1809,6 +1847,39 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@melt-ui/pp": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@melt-ui/pp/-/pp-0.1.4.tgz", + "integrity": "sha512-zR+Kl3CZJPJBHW8V7YcdQCMI/dVcnW9Ct3yGbVaIywYVStVRS7F9uEDOea3xLLT2WTGodQePzPlUn53yKFu87g==", + "dev": true, + "dependencies": { + "estree-walker": "^3.0.3" + }, + "engines": { + "pnpm": ">=8.6.3" + }, + "peerDependencies": { + "@melt-ui/svelte": ">= 0.29.0", + "svelte": "^3.55.0 || ^4.0.0 || ^5.0.0-next.1" + } + }, + "node_modules/@melt-ui/svelte": { + "version": "0.61.3", + "resolved": "https://registry.npmjs.org/@melt-ui/svelte/-/svelte-0.61.3.tgz", + "integrity": "sha512-6btfQJs1zfXpZ++vftqXCYCqAq3DDdAj3TbSn/myZbFPYLib/HoFKQryg1Ctts3tIxCATaYtVQZVfSWHm8ZdWQ==", + "dev": true, + "dependencies": { + "@floating-ui/core": "^1.3.1", + "@floating-ui/dom": "^1.4.5", + "@internationalized/date": "^3.5.0", + "dequal": "^2.0.3", + "focus-trap": "^7.5.2", + "nanoid": "^4.0.2" + }, + "peerDependencies": { + "svelte": ">=3 <5" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -1845,12 +1916,12 @@ } }, "node_modules/@playwright/test": { - "version": "1.39.0", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.39.0.tgz", - "integrity": "sha512-3u1iFqgzl7zr004bGPYiN/5EZpRUSFddQBra8Rqll5N0/vfpqlP9I9EXqAoGacuAbX6c9Ulg/Cjqglp5VkK6UQ==", + "version": "1.40.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.40.1.tgz", + "integrity": "sha512-EaaawMTOeEItCRvfmkI9v6rBkF1svM8wjl/YPRrg2N2Wmp+4qJYkWtJsbew1szfKKDm6fPLy4YAanBhIlf9dWw==", "dev": true, "dependencies": { - "playwright": "1.39.0" + "playwright": "1.40.1" }, "bin": { "playwright": "cli.js" @@ -1860,9 +1931,9 @@ } }, "node_modules/@polka/url": { - "version": "1.0.0-next.23", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.23.tgz", - "integrity": "sha512-C16M+IYz0rgRhWZdCmK+h58JMv8vijAA61gmz2rspCSwKwzBebpdcsiUmwrtJRdphuY30i6BSLEOP8ppbNLyLg==", + "version": "1.0.0-next.24", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.24.tgz", + "integrity": "sha512-2LuNTFBIO0m7kKIQvvPHN6UE63VjpmL9rnEEaOOaiSPbZK+zUOYIzBAWcED+3XYzhYsd/0mD57VdxAEqqV52CQ==", "dev": true }, "node_modules/@popperjs/core": { @@ -1874,68 +1945,82 @@ "url": "https://opencollective.com/popperjs" } }, - "node_modules/@sentry-internal/tracing": { - "version": "7.77.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.77.0.tgz", - "integrity": "sha512-8HRF1rdqWwtINqGEdx8Iqs9UOP/n8E0vXUu3Nmbqj4p5sQPA7vvCfq+4Y4rTqZFc7sNdFpDsRION5iQEh8zfZw==", + "node_modules/@sentry-internal/feedback": { + "version": "7.86.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-7.86.0.tgz", + "integrity": "sha512-6rl0JYjmAKnhm4/fuFaROh4Ht8oi9f6ZeIcViCuGJcrGICZJJY0s+R77XJI78rNa82PYFrSCcnWXcGji4T8E7g==", "dependencies": { - "@sentry/core": "7.77.0", - "@sentry/types": "7.77.0", - "@sentry/utils": "7.77.0" + "@sentry/core": "7.86.0", + "@sentry/types": "7.86.0", + "@sentry/utils": "7.86.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@sentry-internal/tracing": { + "version": "7.86.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.86.0.tgz", + "integrity": "sha512-b4dUsNWlPWRwakGwR7bhOkqiFlqQszH1hhVFwrm/8s3kqEBZ+E4CeIfCvuHBHQ1cM/fx55xpXX/BU163cy+3iQ==", + "dependencies": { + "@sentry/core": "7.86.0", + "@sentry/types": "7.86.0", + "@sentry/utils": "7.86.0" }, "engines": { "node": ">=8" } }, "node_modules/@sentry/browser": { - "version": "7.77.0", - "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.77.0.tgz", - "integrity": "sha512-nJ2KDZD90H8jcPx9BysQLiQW+w7k7kISCWeRjrEMJzjtge32dmHA8G4stlUTRIQugy5F+73cOayWShceFP7QJQ==", + "version": "7.86.0", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.86.0.tgz", + "integrity": "sha512-nfYWpVOmug+W7KJO7/xhA1JScMZcYHcoOVHLsUFm4znx51U4qZEk+zZDM11Q2Nw6MuDyEYg6bsH1QCwaoC6nLw==", "dependencies": { - "@sentry-internal/tracing": "7.77.0", - "@sentry/core": "7.77.0", - "@sentry/replay": "7.77.0", - "@sentry/types": "7.77.0", - "@sentry/utils": "7.77.0" + "@sentry-internal/feedback": "7.86.0", + "@sentry-internal/tracing": "7.86.0", + "@sentry/core": "7.86.0", + "@sentry/replay": "7.86.0", + "@sentry/types": "7.86.0", + "@sentry/utils": "7.86.0" }, "engines": { "node": ">=8" } }, "node_modules/@sentry/core": { - "version": "7.77.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.77.0.tgz", - "integrity": "sha512-Tj8oTYFZ/ZD+xW8IGIsU6gcFXD/gfE+FUxUaeSosd9KHwBQNOLhZSsYo/tTVf/rnQI/dQnsd4onPZLiL+27aTg==", + "version": "7.86.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.86.0.tgz", + "integrity": "sha512-SbLvqd1bRYzhDS42u7GMnmbDMfth/zRiLElQWbLK/shmuZzTcfQSwNNdF4Yj+VfjOkqPFgGmICHSHVUc9dh01g==", "dependencies": { - "@sentry/types": "7.77.0", - "@sentry/utils": "7.77.0" + "@sentry/types": "7.86.0", + "@sentry/utils": "7.86.0" }, "engines": { "node": ">=8" } }, "node_modules/@sentry/replay": { - "version": "7.77.0", - "resolved": "https://registry.npmjs.org/@sentry/replay/-/replay-7.77.0.tgz", - "integrity": "sha512-M9Ik2J5ekl+C1Och3wzLRZVaRGK33BlnBwfwf3qKjgLDwfKW+1YkwDfTHbc2b74RowkJbOVNcp4m8ptlehlSaQ==", + "version": "7.86.0", + "resolved": "https://registry.npmjs.org/@sentry/replay/-/replay-7.86.0.tgz", + "integrity": "sha512-YYZO8bfQSx1H87Te/zzyHPLHvExWiYwUfMWW68yGX+PPZIIzxaM81/iCQHkoucxlvuPCOtxCgf7RSMbsnqEa8g==", "dependencies": { - "@sentry-internal/tracing": "7.77.0", - "@sentry/core": "7.77.0", - "@sentry/types": "7.77.0", - "@sentry/utils": "7.77.0" + "@sentry-internal/tracing": "7.86.0", + "@sentry/core": "7.86.0", + "@sentry/types": "7.86.0", + "@sentry/utils": "7.86.0" }, "engines": { "node": ">=12" } }, "node_modules/@sentry/svelte": { - "version": "7.77.0", - "resolved": "https://registry.npmjs.org/@sentry/svelte/-/svelte-7.77.0.tgz", - "integrity": "sha512-5UgHp+i2IPxoqU/uCEVRryjChjne85Jp/JUqaW5GBWwI0+86snhJsDYm76X7N+mwQfQyOz0/lJs72nAdXh874w==", + "version": "7.86.0", + "resolved": "https://registry.npmjs.org/@sentry/svelte/-/svelte-7.86.0.tgz", + "integrity": "sha512-Qf81DORscJrr/8nXdfRRIPThjfGD+db6VvuoNCwQ+/t3WyqSVz96huURkImTBsnQUY0Bw1y4R72ySHRzg0ynNA==", "dependencies": { - "@sentry/browser": "7.77.0", - "@sentry/types": "7.77.0", - "@sentry/utils": "7.77.0", + "@sentry/browser": "7.86.0", + "@sentry/types": "7.86.0", + "@sentry/utils": "7.86.0", "magic-string": "^0.30.0" }, "engines": { @@ -1946,30 +2031,30 @@ } }, "node_modules/@sentry/tracing": { - "version": "7.77.0", - "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-7.77.0.tgz", - "integrity": "sha512-zr6eSCW3NJ124uj4Fy/6hh77cziy43dpYE1WpgvO/yhl1+kdrY2XVJ0bXGqwHU0KBm/eSgHD7yecUxmZUXiabA==", + "version": "7.86.0", + "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-7.86.0.tgz", + "integrity": "sha512-WPqgmbLm6ntpIoTZd1L/RHIVEDMmvVjIDxKeXGiJeXHZG2VMtgwoxuZAFluVFaD0Sr20Nhj+ZS7HvKOWTxrjjA==", "dependencies": { - "@sentry-internal/tracing": "7.77.0" + "@sentry-internal/tracing": "7.86.0" }, "engines": { "node": ">=8" } }, "node_modules/@sentry/types": { - "version": "7.77.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.77.0.tgz", - "integrity": "sha512-nfb00XRJVi0QpDHg+JkqrmEBHsqBnxJu191Ded+Cs1OJ5oPXEW6F59LVcBScGvMqe+WEk1a73eH8XezwfgrTsA==", + "version": "7.86.0", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.86.0.tgz", + "integrity": "sha512-pGAt0+bMfWgo0KG2epthfNV4Wae03tURpoxNjGo5Fr4cXxvLTSijSAQ6rmmO4bXBJ7+rErEjX30g30o/eEdP9g==", "engines": { "node": ">=8" } }, "node_modules/@sentry/utils": { - "version": "7.77.0", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.77.0.tgz", - "integrity": "sha512-NmM2kDOqVchrey3N5WSzdQoCsyDkQkiRxExPaNI2oKQ/jMWHs9yt0tSy7otPBcXs0AP59ihl75Bvm1tDRcsp5g==", + "version": "7.86.0", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.86.0.tgz", + "integrity": "sha512-6PejFtw9VTFFy5vu0ks+U7Ozkqz+eMt+HN8AZKBKErYzX5/xs0kpkOcSRpu3ETdTYcZf8VAmLVgFgE2BE+3WuQ==", "dependencies": { - "@sentry/types": "7.77.0" + "@sentry/types": "7.86.0" }, "engines": { "node": ">=8" @@ -2001,6 +2086,11 @@ "@sinonjs/commons": "^3.0.0" } }, + "node_modules/@stripe/stripe-js": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-2.2.0.tgz", + "integrity": "sha512-YyXQbsXvnNRJ6MofFhCLIQ4W7UpfkfSOQhjIaHEiCMBv3IBxhzugXiYNNzceGTK/7DL31v7HtTnkJ+FI+6AIow==" + }, "node_modules/@sveltejs/adapter-static": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@sveltejs/adapter-static/-/adapter-static-2.0.3.tgz", @@ -2011,13 +2101,13 @@ } }, "node_modules/@sveltejs/kit": { - "version": "1.27.3", - "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-1.27.3.tgz", - "integrity": "sha512-pd7qwX6ww5noA0/FLk45B0aKUeOXWR+pfZsGTrv3dRmj3lTmnki9UTmTdWzHJGrje+BBkGUZHfgGrsSOQQBQpQ==", + "version": "1.27.7", + "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-1.27.7.tgz", + "integrity": "sha512-AzXYDoYt42clCBwLF9GTHsXyg2DFR31Ncyt8yxu8Aw4tgB433V+w+hcr1RTfAN9zKW2J2PY9FMQ8FoX/4Vw8CA==", "dev": true, "hasInstallScript": true, "dependencies": { - "@sveltejs/vite-plugin-svelte": "^2.4.1", + "@sveltejs/vite-plugin-svelte": "^2.5.0", "@types/cookie": "^0.5.1", "cookie": "^0.5.0", "devalue": "^4.3.1", @@ -2038,14 +2128,14 @@ "node": "^16.14 || >=18" }, "peerDependencies": { - "svelte": "^3.54.0 || ^4.0.0-next.0", + "svelte": "^3.54.0 || ^4.0.0-next.0 || ^5.0.0-next.0", "vite": "^4.0.0" } }, "node_modules/@sveltejs/vite-plugin-svelte": { - "version": "2.4.6", - "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-2.4.6.tgz", - "integrity": "sha512-zO79p0+DZnXPnF0ltIigWDx/ux7Ni+HRaFOw720Qeivc1azFUrJxTl0OryXVibYNx1hCboGia1NRV3x8RNv4cA==", + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-2.5.3.tgz", + "integrity": "sha512-erhNtXxE5/6xGZz/M9eXsmI7Pxa6MS7jyTy06zN3Ck++ldrppOnOlJwHHTsMC7DHDQdgUp4NAc4cDNQ9eGdB/w==", "dev": true, "dependencies": { "@sveltejs/vite-plugin-svelte-inspector": "^1.0.4", @@ -2060,7 +2150,7 @@ "node": "^14.18.0 || >= 16" }, "peerDependencies": { - "svelte": "^3.54.0 || ^4.0.0", + "svelte": "^3.54.0 || ^4.0.0 || ^5.0.0-next.0", "vite": "^4.0.0" } }, @@ -2081,6 +2171,15 @@ "vite": "^4.0.0" } }, + "node_modules/@swc/helpers": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.3.tgz", + "integrity": "sha512-FaruWX6KdudYloq1AHD/4nU+UsMTdNE8CKyrseXWEcgjDAbvkwJg2QGPAnfIJLIWsjZOSPLOAykK6fuYp4vp4A==", + "dev": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@testing-library/dom": { "version": "9.3.3", "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.3.3.tgz", @@ -2173,15 +2272,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, "peer": true, "dependencies": { @@ -2193,9 +2292,9 @@ } }, "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, "peer": true, "dependencies": { @@ -2203,9 +2302,9 @@ } }, "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, "peer": true, "dependencies": { @@ -2214,9 +2313,9 @@ } }, "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, "peer": true, "dependencies": { @@ -2224,47 +2323,47 @@ } }, "node_modules/@types/chai": { - "version": "4.3.9", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.9.tgz", - "integrity": "sha512-69TtiDzu0bcmKQv3yg1Zx409/Kd7r0b5F1PfpYJfSHzLGtB53547V4u+9iqKYsTu/O2ai6KTb0TInNpvuQ3qmg==", + "version": "4.3.11", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.11.tgz", + "integrity": "sha512-qQR1dr2rGIHYlJulmr8Ioq3De0Le9E4MJ5AiaeAETJJpndT1uUNHsGFK3L/UIu+rbkQSdj8J/w2bCsBZc/Y5fQ==", "dev": true }, "node_modules/@types/chai-subset": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/@types/chai-subset/-/chai-subset-1.3.4.tgz", - "integrity": "sha512-CCWNXrJYSUIojZ1149ksLl3AN9cmZ5djf+yUoVVV+NuYrtydItQVlL2ZDqyC6M6O9LWRnVf8yYDxbXHO2TfQZg==", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/chai-subset/-/chai-subset-1.3.5.tgz", + "integrity": "sha512-c2mPnw+xHtXDoHmdtcCXGwyLMiauiAyxWMzhGpqHC4nqI/Y5G2XhTampslK2rb59kpcuHon03UH8W6iYUzw88A==", "dev": true, "dependencies": { "@types/chai": "*" } }, "node_modules/@types/cookie": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.5.3.tgz", - "integrity": "sha512-SLg07AS9z1Ab2LU+QxzU8RCmzsja80ywjf/t5oqw+4NSH20gIGlhLOrBDm1L3PBWzPa4+wkgFQVZAjE6Ioj2ug==", + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.5.4.tgz", + "integrity": "sha512-7z/eR6O859gyWIAjuvBWFzNURmf2oPBmJlfVWkwehU5nzIyjwBsTh7WMmEEV4JFnHuQ3ex4oyTvfKzcyJVDBNA==", "dev": true }, "node_modules/@types/deep-equal": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@types/deep-equal/-/deep-equal-1.0.3.tgz", - "integrity": "sha512-xP1pB67eLrRdMLKpXUXhYN/3uiJN1gNalcVOSY5kdJbxhGuZTTE8awSWOD9LCJDzQZVsuZZcnMMLRrbf+nOUSQ==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@types/deep-equal/-/deep-equal-1.0.4.tgz", + "integrity": "sha512-tqdiS4otQP4KmY0PR3u6KbZ5EWvhNdUoS/jc93UuK23C220lOZ/9TvjfxdPcKvqwwDVtmtSCrnr0p/2dirAxkA==", "dev": true }, "node_modules/@types/dlv": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@types/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-u6JdAm9wje4n7vqkK9F6nQI18xSO+MVfXz6RMgN4acJmSZMlV7ZRrEQg4d1wmiQ2txg2xArpc68RS6p4JecVNg==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@types/dlv/-/dlv-1.1.4.tgz", + "integrity": "sha512-m8KmImw4Jt+4rIgupwfivrWEOnj1LzkmKkqbh075uG13eTQ1ZxHWT6T0vIdSQhLIjQCiR0n0lZdtyDOPO1x2Mw==", "peer": true }, "node_modules/@types/estree": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.4.tgz", - "integrity": "sha512-2JwWnHK9H+wUZNorf2Zr6ves96WHoWDJIftkcxPKsS7Djta6Zu519LarhRNljPXkpsZR2ZMwNCPeW7omW07BJw==" + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" }, "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, "peer": true, "dependencies": { @@ -2272,33 +2371,33 @@ } }, "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.7", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.7.tgz", - "integrity": "sha512-HLyetab6KVPSiF+7pFcUyMeLsx25LDNDemw9mGsJBkai/oouwrjTycocSDYopMEwFhN2Y4s9oPyOCZNofgSt2g==", + "version": "29.5.11", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.11.tgz", + "integrity": "sha512-S2mHmYIVe13vrm6q4kN6fLYYAka15ALQki/vgDC3mIukEOx8WJlv0kQPM+d4w8Gp6u0uSdKND04IlTXBv0rwnQ==", "dev": true, "dependencies": { "expect": "^29.0.0", @@ -2338,42 +2437,42 @@ "dev": true }, "node_modules/@types/json-schema": { - "version": "7.0.14", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.14.tgz", - "integrity": "sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw==", + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, "node_modules/@types/node": { - "version": "20.8.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.10.tgz", - "integrity": "sha512-TlgT8JntpcbmKUFzjhsyhGfP2fsiz1Mv56im6enJ905xG1DAYesxJaeSbGqQmAw8OWPdhyJGhGSQGKRNJ45u9w==", + "version": "20.10.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.4.tgz", + "integrity": "sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==", "dev": true, "dependencies": { "undici-types": "~5.26.4" } }, "node_modules/@types/prismjs": { - "version": "1.26.2", - "resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.2.tgz", - "integrity": "sha512-/r7Cp7iUIk7gts26mHXD66geUC+2Fo26TZYjQK6Nr4LDfi6lmdRmMqM0oPwfiMhUwoBAOFe8GstKi2pf6hZvwA==", + "version": "1.26.3", + "resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.3.tgz", + "integrity": "sha512-A0D0aTXvjlqJ5ZILMz3rNfDBOx9hHxLZYv2by47Sm/pqW35zzjusrZTryatjN/Rf8Us2gZrJD+KeHbUSTux1Cw==", "dev": true }, "node_modules/@types/pug": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/@types/pug/-/pug-2.0.8.tgz", - "integrity": "sha512-QzhsZ1dMGyJbn/D9V80zp4GIA4J4rfAjCCxc3MP+new0E8dyVdSkR735Lx+n3LIaHNFcjHL5+TbziccuT+fdoQ==", + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/@types/pug/-/pug-2.0.10.tgz", + "integrity": "sha512-Sk/uYFOBAB7mb74XcpizmH0KOR2Pv3D2Hmrh1Dmy5BmK3MpdSa5kqZcg6EKBdklU0bFXX9gCfzvpnyUehrPIuA==", "dev": true }, "node_modules/@types/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ==", + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", + "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", "dev": true }, "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": { @@ -2386,31 +2485,31 @@ } }, "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/@typescript-eslint/eslint-plugin": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.9.1.tgz", - "integrity": "sha512-w0tiiRc9I4S5XSXXrMHOWgHgxbrBn1Ro+PmiYhSg2ZVdxrAJtQgzU5o2m1BfP6UOn7Vxcc6152vFjQfmZR4xEg==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.13.2.tgz", + "integrity": "sha512-3+9OGAWHhk4O1LlcwLBONbdXsAhLjyCFogJY/cWy2lxdVJ2JrcTF2pTGMaLl2AE7U1l31n8Py4a8bx5DLf/0dQ==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.9.1", - "@typescript-eslint/type-utils": "6.9.1", - "@typescript-eslint/utils": "6.9.1", - "@typescript-eslint/visitor-keys": "6.9.1", + "@typescript-eslint/scope-manager": "6.13.2", + "@typescript-eslint/type-utils": "6.13.2", + "@typescript-eslint/utils": "6.13.2", + "@typescript-eslint/visitor-keys": "6.13.2", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -2436,15 +2535,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.9.1.tgz", - "integrity": "sha512-C7AK2wn43GSaCUZ9do6Ksgi2g3mwFkMO3Cis96kzmgudoVaKyt62yNzJOktP0HDLb/iO2O0n2lBOzJgr6Q/cyg==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.13.2.tgz", + "integrity": "sha512-MUkcC+7Wt/QOGeVlM8aGGJZy1XV5YKjTpq9jK6r6/iLsGXhBVaGP5N0UYvFsu9BFlSpwY9kMretzdBH01rkRXg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.9.1", - "@typescript-eslint/types": "6.9.1", - "@typescript-eslint/typescript-estree": "6.9.1", - "@typescript-eslint/visitor-keys": "6.9.1", + "@typescript-eslint/scope-manager": "6.13.2", + "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/typescript-estree": "6.13.2", + "@typescript-eslint/visitor-keys": "6.13.2", "debug": "^4.3.4" }, "engines": { @@ -2464,13 +2563,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.9.1.tgz", - "integrity": "sha512-38IxvKB6NAne3g/+MyXMs2Cda/Sz+CEpmm+KLGEM8hx/CvnSRuw51i8ukfwB/B/sESdeTGet1NH1Wj7I0YXswg==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.13.2.tgz", + "integrity": "sha512-CXQA0xo7z6x13FeDYCgBkjWzNqzBn8RXaE3QVQVIUm74fWJLkJkaHmHdKStrxQllGh6Q4eUGyNpMe0b1hMkXFA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.9.1", - "@typescript-eslint/visitor-keys": "6.9.1" + "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/visitor-keys": "6.13.2" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -2481,13 +2580,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.9.1.tgz", - "integrity": "sha512-eh2oHaUKCK58qIeYp19F5V5TbpM52680sB4zNSz29VBQPTWIlE/hCj5P5B1AChxECe/fmZlspAWFuRniep1Skg==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.13.2.tgz", + "integrity": "sha512-Qr6ssS1GFongzH2qfnWKkAQmMUyZSyOr0W54nZNU1MDfo+U4Mv3XveeLZzadc/yq8iYhQZHYT+eoXJqnACM1tw==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.9.1", - "@typescript-eslint/utils": "6.9.1", + "@typescript-eslint/typescript-estree": "6.13.2", + "@typescript-eslint/utils": "6.13.2", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -2508,9 +2607,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.9.1.tgz", - "integrity": "sha512-BUGslGOb14zUHOUmDB2FfT6SI1CcZEJYfF3qFwBeUrU6srJfzANonwRYHDpLBuzbq3HaoF2XL2hcr01c8f8OaQ==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.13.2.tgz", + "integrity": "sha512-7sxbQ+EMRubQc3wTfTsycgYpSujyVbI1xw+3UMRUcrhSy+pN09y/lWzeKDbvhoqcRbHdc+APLs/PWYi/cisLPg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -2521,13 +2620,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.9.1.tgz", - "integrity": "sha512-U+mUylTHfcqeO7mLWVQ5W/tMLXqVpRv61wm9ZtfE5egz7gtnmqVIw9ryh0mgIlkKk9rZLY3UHygsBSdB9/ftyw==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.13.2.tgz", + "integrity": "sha512-SuD8YLQv6WHnOEtKv8D6HZUzOub855cfPnPMKvdM/Bh1plv1f7Q/0iFUDLKKlxHcEstQnaUU4QZskgQq74t+3w==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.9.1", - "@typescript-eslint/visitor-keys": "6.9.1", + "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/visitor-keys": "6.13.2", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2548,17 +2647,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.9.1.tgz", - "integrity": "sha512-L1T0A5nFdQrMVunpZgzqPL6y2wVreSyHhKGZryS6jrEN7bD9NplVAyMryUhXsQ4TWLnZmxc2ekar/lSGIlprCA==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.13.2.tgz", + "integrity": "sha512-b9Ptq4eAZUym4idijCRzl61oPCwwREcfDI8xGk751Vhzig5fFZR9CyzDz4Sp/nxSLBYxUPyh4QdIDqWykFhNmQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.9.1", - "@typescript-eslint/types": "6.9.1", - "@typescript-eslint/typescript-estree": "6.9.1", + "@typescript-eslint/scope-manager": "6.13.2", + "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/typescript-estree": "6.13.2", "semver": "^7.5.4" }, "engines": { @@ -2573,12 +2672,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.9.1.tgz", - "integrity": "sha512-MUaPUe/QRLEffARsmNfmpghuQkW436DvESW+h+M52w0coICHRfD6Np9/K6PdACwnrq1HmuLl+cSPZaJmeVPkSw==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.13.2.tgz", + "integrity": "sha512-OGznFs0eAQXJsp+xSd6k/O1UbFi/K/L7WjqeRoFE7vadjAF9y0uppXhYNQNEqygjou782maGClOoZwPqF0Drlw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.9.1", + "@typescript-eslint/types": "6.13.2", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -2679,13 +2778,13 @@ } }, "node_modules/@vue/compiler-core": { - "version": "3.3.8", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.3.8.tgz", - "integrity": "sha512-hN/NNBUECw8SusQvDSqqcVv6gWq8L6iAktUR0UF3vGu2OhzRqcOiAno0FmBJWwxhYEXRlQJT5XnoKsVq1WZx4g==", + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.3.11.tgz", + "integrity": "sha512-h97/TGWBilnLuRaj58sxNrsUU66fwdRKLOLQ9N/5iNDfp+DZhYH9Obhe0bXxhedl8fjAgpRANpiZfbgWyruQ0w==", "peer": true, "dependencies": { - "@babel/parser": "^7.23.0", - "@vue/shared": "3.3.8", + "@babel/parser": "^7.23.5", + "@vue/shared": "3.3.11", "estree-walker": "^2.0.2", "source-map-js": "^1.0.2" } @@ -2697,30 +2796,30 @@ "peer": true }, "node_modules/@vue/compiler-dom": { - "version": "3.3.8", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.3.8.tgz", - "integrity": "sha512-+PPtv+p/nWDd0AvJu3w8HS0RIm/C6VGBIRe24b9hSyNWOAPEUosFZ5diwawwP8ip5sJ8n0Pe87TNNNHnvjs0FQ==", + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.3.11.tgz", + "integrity": "sha512-zoAiUIqSKqAJ81WhfPXYmFGwDRuO+loqLxvXmfUdR5fOitPoUiIeFI9cTTyv9MU5O1+ZZglJVTusWzy+wfk5hw==", "peer": true, "dependencies": { - "@vue/compiler-core": "3.3.8", - "@vue/shared": "3.3.8" + "@vue/compiler-core": "3.3.11", + "@vue/shared": "3.3.11" } }, "node_modules/@vue/compiler-sfc": { - "version": "3.3.8", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.3.8.tgz", - "integrity": "sha512-WMzbUrlTjfYF8joyT84HfwwXo+8WPALuPxhy+BZ6R4Aafls+jDBnSz8PDz60uFhuqFbl3HxRfxvDzrUf3THwpA==", + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.3.11.tgz", + "integrity": "sha512-U4iqPlHO0KQeK1mrsxCN0vZzw43/lL8POxgpzcJweopmqtoYy9nljJzWDIQS3EfjiYhfdtdk9Gtgz7MRXnz3GA==", "peer": true, "dependencies": { - "@babel/parser": "^7.23.0", - "@vue/compiler-core": "3.3.8", - "@vue/compiler-dom": "3.3.8", - "@vue/compiler-ssr": "3.3.8", - "@vue/reactivity-transform": "3.3.8", - "@vue/shared": "3.3.8", + "@babel/parser": "^7.23.5", + "@vue/compiler-core": "3.3.11", + "@vue/compiler-dom": "3.3.11", + "@vue/compiler-ssr": "3.3.11", + "@vue/reactivity-transform": "3.3.11", + "@vue/shared": "3.3.11", "estree-walker": "^2.0.2", "magic-string": "^0.30.5", - "postcss": "^8.4.31", + "postcss": "^8.4.32", "source-map-js": "^1.0.2" } }, @@ -2731,33 +2830,33 @@ "peer": true }, "node_modules/@vue/compiler-ssr": { - "version": "3.3.8", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.3.8.tgz", - "integrity": "sha512-hXCqQL/15kMVDBuoBYpUnSYT8doDNwsjvm3jTefnXr+ytn294ySnT8NlsFHmTgKNjwpuFy7XVV8yTeLtNl/P6w==", + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.3.11.tgz", + "integrity": "sha512-Zd66ZwMvndxRTgVPdo+muV4Rv9n9DwQ4SSgWWKWkPFebHQfVYRrVjeygmmDmPewsHyznCNvJ2P2d6iOOhdv8Qg==", "peer": true, "dependencies": { - "@vue/compiler-dom": "3.3.8", - "@vue/shared": "3.3.8" + "@vue/compiler-dom": "3.3.11", + "@vue/shared": "3.3.11" } }, "node_modules/@vue/reactivity": { - "version": "3.3.8", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.3.8.tgz", - "integrity": "sha512-ctLWitmFBu6mtddPyOKpHg8+5ahouoTCRtmAHZAXmolDtuZXfjL2T3OJ6DL6ezBPQB1SmMnpzjiWjCiMYmpIuw==", + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.3.11.tgz", + "integrity": "sha512-D5tcw091f0nuu+hXq5XANofD0OXnBmaRqMYl5B3fCR+mX+cXJIGNw/VNawBqkjLNWETrFW0i+xH9NvDbTPVh7g==", "peer": true, "dependencies": { - "@vue/shared": "3.3.8" + "@vue/shared": "3.3.11" } }, "node_modules/@vue/reactivity-transform": { - "version": "3.3.8", - "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.3.8.tgz", - "integrity": "sha512-49CvBzmZNtcHua0XJ7GdGifM8GOXoUMOX4dD40Y5DxI3R8OUhMlvf2nvgUAcPxaXiV5MQQ1Nwy09ADpnLQUqRw==", + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.3.11.tgz", + "integrity": "sha512-fPGjH0wqJo68A0wQ1k158utDq/cRyZNlFoxGwNScE28aUFOKFEnCBsvyD8jHn+0kd0UKVpuGuaZEQ6r9FJRqCg==", "peer": true, "dependencies": { - "@babel/parser": "^7.23.0", - "@vue/compiler-core": "3.3.8", - "@vue/shared": "3.3.8", + "@babel/parser": "^7.23.5", + "@vue/compiler-core": "3.3.11", + "@vue/shared": "3.3.11", "estree-walker": "^2.0.2", "magic-string": "^0.30.5" } @@ -2769,49 +2868,50 @@ "peer": true }, "node_modules/@vue/runtime-core": { - "version": "3.3.8", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.3.8.tgz", - "integrity": "sha512-qurzOlb6q26KWQ/8IShHkMDOuJkQnQcTIp1sdP4I9MbCf9FJeGVRXJFr2mF+6bXh/3Zjr9TDgURXrsCr9bfjUw==", + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.3.11.tgz", + "integrity": "sha512-g9ztHGwEbS5RyWaOpXuyIVFTschclnwhqEbdy5AwGhYOgc7m/q3NFwr50MirZwTTzX55JY8pSkeib9BX04NIpw==", "peer": true, "dependencies": { - "@vue/reactivity": "3.3.8", - "@vue/shared": "3.3.8" + "@vue/reactivity": "3.3.11", + "@vue/shared": "3.3.11" } }, "node_modules/@vue/runtime-dom": { - "version": "3.3.8", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.3.8.tgz", - "integrity": "sha512-Noy5yM5UIf9UeFoowBVgghyGGPIDPy1Qlqt0yVsUdAVbqI8eeMSsTqBtauaEoT2UFXUk5S64aWVNJN4MJ2vRdA==", + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.3.11.tgz", + "integrity": "sha512-OlhtV1PVpbgk+I2zl+Y5rQtDNcCDs12rsRg71XwaA2/Rbllw6mBLMi57VOn8G0AjOJ4Mdb4k56V37+g8ukShpQ==", "peer": true, "dependencies": { - "@vue/runtime-core": "3.3.8", - "@vue/shared": "3.3.8", + "@vue/runtime-core": "3.3.11", + "@vue/shared": "3.3.11", "csstype": "^3.1.2" } }, "node_modules/@vue/server-renderer": { - "version": "3.3.8", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.3.8.tgz", - "integrity": "sha512-zVCUw7RFskvPuNlPn/8xISbrf0zTWsTSdYTsUTN1ERGGZGVnRxM2QZ3x1OR32+vwkkCm0IW6HmJ49IsPm7ilLg==", + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.3.11.tgz", + "integrity": "sha512-AIWk0VwwxCAm4wqtJyxBylRTXSy1wCLOKbWxHaHiu14wjsNYtiRCSgVuqEPVuDpErOlRdNnuRgipQfXRLjLN5A==", "peer": true, "dependencies": { - "@vue/compiler-ssr": "3.3.8", - "@vue/shared": "3.3.8" + "@vue/compiler-ssr": "3.3.11", + "@vue/shared": "3.3.11" }, "peerDependencies": { - "vue": "3.3.8" + "vue": "3.3.11" } }, "node_modules/@vue/shared": { - "version": "3.3.8", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.3.8.tgz", - "integrity": "sha512-8PGwybFwM4x8pcfgqEQFy70NaQxASvOC5DJwLQfpArw1UDfUXrJkdxD3BhVTMS+0Lef/TU7YO0Jvr0jJY8T+mw==", + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.3.11.tgz", + "integrity": "sha512-u2G8ZQ9IhMWTMXaWqZycnK4UthG1fA238CD+DP4Dm4WJi5hdUKKLg0RMRaRpDPNMdkTwIDkp7WtD0Rd9BH9fLw==", "peer": true }, "node_modules/abab": { "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/acorn": { @@ -2835,9 +2935,9 @@ } }, "node_modules/acorn-walk": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.0.tgz", - "integrity": "sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA==", + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.1.tgz", + "integrity": "sha512-TgUZgYvqZprrl7YldZNoa9OciCAyZR+Ejm9eXzKCmjsF5IKp/wgQ7Z/ZpjpGTIUPwrHQIcYeI8qDh4PsEwxMbw==", "dev": true, "engines": { "node": ">=0.4.0" @@ -2856,9 +2956,9 @@ } }, "node_modules/ai": { - "version": "2.2.20", - "resolved": "https://registry.npmjs.org/ai/-/ai-2.2.20.tgz", - "integrity": "sha512-BTZ8VEsIdapZM46Tt72FzYPY4Kt55ANpYubUSYJCrrdUfMDCPfT/XwqPsXZam1i7Go6YrUPha9VBdrvzQxBtXw==", + "version": "2.2.28", + "resolved": "https://registry.npmjs.org/ai/-/ai-2.2.28.tgz", + "integrity": "sha512-NUPwtXjIghlkhrR8x9nEnzpaKnWVhABe4XsSYIRbwWS1f9M8DxV413W+bpQ52iKkzputuraipHSyjnAtgU88cA==", "dependencies": { "eventsource-parser": "1.0.0", "nanoid": "3.3.6", @@ -3248,9 +3348,9 @@ } }, "node_modules/browserslist": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", - "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", + "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", "dev": true, "funding": [ { @@ -3268,9 +3368,9 @@ ], "peer": true, "dependencies": { - "caniuse-lite": "^1.0.30001541", - "electron-to-chromium": "^1.4.535", - "node-releases": "^2.0.13", + "caniuse-lite": "^1.0.30001565", + "electron-to-chromium": "^1.4.601", + "node-releases": "^2.0.14", "update-browserslist-db": "^1.0.13" }, "bin": { @@ -3348,9 +3448,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001561", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001561.tgz", - "integrity": "sha512-NTt0DNoKe958Q0BE0j0c1V9jbUzhBxHIEJy7asmGrpE0yG63KTV7PLHPnK2E1O9RsQrQ081I3NLuXGS6zht3cw==", + "version": "1.0.30001566", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001566.tgz", + "integrity": "sha512-ggIhCsTxmITBAMmK8yZjEhCO5/47jKXPu6Dha/wuCS4JePVL+3uiDEBuhu2aIoT+bqTOR8L76Ip1ARL9xYsEJA==", "dev": true, "funding": [ { @@ -3716,9 +3816,9 @@ } }, "node_modules/csstype": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", - "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", "peer": true }, "node_modules/data-urls": { @@ -3791,14 +3891,14 @@ } }, "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==", "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", @@ -3808,11 +3908,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" @@ -3960,6 +4063,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" @@ -4000,9 +4104,9 @@ "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==" }, "node_modules/electron-to-chromium": { - "version": "1.4.576", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.576.tgz", - "integrity": "sha512-yXsZyXJfAqzWk1WKryr0Wl0MN2D47xodPvEEwlVePBnhU5E7raevLQR+E6b9JAD3GfL/7MbAL9ZtWQQPcLx7wA==", + "version": "1.4.608", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.608.tgz", + "integrity": "sha512-J2f/3iIIm3Mo0npneITZ2UPe4B1bg8fTNrFjD8715F/k1BvbviRuqYGkET1PgprrczXYTHFvotbBOmUp6KE0uA==", "dev": true, "peer": true }, @@ -4132,15 +4236,15 @@ } }, "node_modules/eslint": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.53.0.tgz", - "integrity": "sha512-N4VuiPjXDUa4xVeV/GC/RV3hQW9Nw+Y463lkWaKKXKYMvmRiRDAtfpuPFLN+E1/6ZhyR8J2ig+eVREnYgUsiag==", + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.55.0.tgz", + "integrity": "sha512-iyUUAM0PCKj5QpwGfmCAG9XXbZCWsqP/eWAWrG/W0umvjuLRBECwSFdt+rCntju0xEH7teIABPwXpahftIaTdA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.3", - "@eslint/js": "8.53.0", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.55.0", "@humanwhocodes/config-array": "^0.11.13", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -4186,10 +4290,22 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint-compat-utils": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.1.2.tgz", + "integrity": "sha512-Jia4JDldWnFNIru1Ehx1H5s9/yxiRHY/TimCuUc0jNexew3cF1gI6CYZil1ociakfWO3rRqFjl1mskBblB3RYg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "eslint": ">=6.0.0" + } + }, "node_modules/eslint-config-prettier": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.0.0.tgz", - "integrity": "sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", "dev": true, "bin": { "eslint-config-prettier": "bin/cli.js" @@ -4199,14 +4315,15 @@ } }, "node_modules/eslint-plugin-svelte": { - "version": "2.34.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-svelte/-/eslint-plugin-svelte-2.34.1.tgz", - "integrity": "sha512-HnLzYevh9bLL0Rj2d4dmZY9EutN0BL5JsJRHqtJFIyaEmdxxd3ZuY5zNoSjIFhctFMSntsClbd6TwYjgaOY0Xw==", + "version": "2.35.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-svelte/-/eslint-plugin-svelte-2.35.1.tgz", + "integrity": "sha512-IF8TpLnROSGy98Z3NrsKXWDSCbNY2ReHDcrYTuXZMbfX7VmESISR78TWgO9zdg4Dht1X8coub5jKwHzP0ExRug==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@jridgewell/sourcemap-codec": "^1.4.14", "debug": "^4.3.1", + "eslint-compat-utils": "^0.1.2", "esutils": "^2.0.3", "known-css-properties": "^0.29.0", "postcss": "^8.4.5", @@ -4412,9 +4529,9 @@ "dev": true }, "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", @@ -4511,9 +4628,9 @@ } }, "node_modules/flat-cache": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.1.tgz", - "integrity": "sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "dev": true, "dependencies": { "flatted": "^3.2.9", @@ -4521,7 +4638,7 @@ "rimraf": "^3.0.2" }, "engines": { - "node": ">=12.0.0" + "node": "^10.12.0 || >=12.0.0" } }, "node_modules/flatted": { @@ -4530,6 +4647,15 @@ "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", "dev": true }, + "node_modules/focus-trap": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.5.4.tgz", + "integrity": "sha512-N7kHdlgsO/v+iD/dMoJKtsSqs5Dz/dXZVebRgJw23LDk+jMi/974zyiOYDziY2JPp8xivq9BmUGwIJMiuSBi7w==", + "dev": true, + "dependencies": { + "tabbable": "^6.2.0" + } + }, "node_modules/for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -4899,9 +5025,9 @@ } }, "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", + "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", "dev": true, "engines": { "node": ">= 4" @@ -5333,9 +5459,9 @@ } }, "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, "peer": true, "engines": { @@ -6816,9 +6942,9 @@ "peer": true }, "node_modules/node-releases": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", - "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", "dev": true, "peer": true }, @@ -6887,12 +7013,12 @@ } }, "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", "has-symbols": "^1.0.3", "object-keys": "^1.1.1" }, @@ -7212,12 +7338,12 @@ } }, "node_modules/playwright": { - "version": "1.39.0", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.39.0.tgz", - "integrity": "sha512-naE5QT11uC/Oiq0BwZ50gDmy8c8WLPRTEWuSSFVG2egBka/1qMoSqYQcROMT9zLwJ86oPofcTH2jBY/5wWOgIw==", + "version": "1.40.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.40.1.tgz", + "integrity": "sha512-2eHI7IioIpQ0bS1Ovg/HszsN/XKNwEG1kbzSDDmADpclKc7CyqkHw7Mg2JCz/bbCxg25QUPcjksoMW7JcIFQmw==", "dev": true, "dependencies": { - "playwright-core": "1.39.0" + "playwright-core": "1.40.1" }, "bin": { "playwright": "cli.js" @@ -7230,9 +7356,9 @@ } }, "node_modules/playwright-core": { - "version": "1.39.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.39.0.tgz", - "integrity": "sha512-+k4pdZgs1qiM+OUkSjx96YiKsXsmb59evFoqv8SKO067qBA+Z2s/dCzJij/ZhdQcs2zlTAgRKfeiiLm8PQ2qvw==", + "version": "1.40.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.40.1.tgz", + "integrity": "sha512-+hkOycxPiV534c4HhpfX6yrlawqVUzITRKwHAmYfmsVreltEl6fAZJ3DPfLMOODw0H3s1Itd6MDCWmP1fl/QvQ==", "dev": true, "bin": { "playwright-core": "cli.js" @@ -7256,9 +7382,9 @@ } }, "node_modules/postcss": { - "version": "8.4.31", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", - "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "version": "8.4.32", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.32.tgz", + "integrity": "sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw==", "funding": [ { "type": "opencollective", @@ -7274,7 +7400,7 @@ } ], "dependencies": { - "nanoid": "^3.3.6", + "nanoid": "^3.3.7", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" }, @@ -7393,9 +7519,9 @@ } }, "node_modules/prettier": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz", - "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.0.tgz", + "integrity": "sha512-TQLvXjq5IAibjh8EpBIkNKxO749UEWABoiIZehEPiY4GNpVdhaFKqSTu+QrlU6D2dPAfubRmtJTi4K4YkQ5eXw==", "dev": true, "bin": { "prettier": "bin/prettier.cjs" @@ -7408,13 +7534,13 @@ } }, "node_modules/prettier-plugin-svelte": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/prettier-plugin-svelte/-/prettier-plugin-svelte-3.0.3.tgz", - "integrity": "sha512-dLhieh4obJEK1hnZ6koxF+tMUrZbV5YGvRpf2+OADyanjya5j0z1Llo8iGwiHmFWZVG/hLEw/AJD5chXd9r3XA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/prettier-plugin-svelte/-/prettier-plugin-svelte-3.1.2.tgz", + "integrity": "sha512-7xfMZtwgAWHMT0iZc8jN4o65zgbAQ3+O32V6W7pXrqNvKnHnkoyQCGCbKeUyXKZLbYE0YhFRnamfxfkEGxm8qA==", "dev": true, "peerDependencies": { "prettier": "^3.0.0", - "svelte": "^3.2.0 || ^4.0.0-next.0" + "svelte": "^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0" } }, "node_modules/pretty-bytes": { @@ -7860,9 +7986,9 @@ "dev": true }, "node_modules/seroval": { - "version": "0.12.3", - "resolved": "https://registry.npmjs.org/seroval/-/seroval-0.12.3.tgz", - "integrity": "sha512-5WDeMpv7rmEylsypRj1iwRVHE/QLsMLiZ+9savlNNQEVdgGia1iRMb7qyaAagY0wu/7+QTe6d2wldk/lgaLb6g==", + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/seroval/-/seroval-0.15.1.tgz", + "integrity": "sha512-OPVtf0qmeC7RW+ScVX+7aOS+xoIM7pWcZ0jOWg2aTZigCydgRB04adfteBRbecZnnrO1WuGQ+C3tLeBBzX2zSQ==", "peer": true, "engines": { "node": ">=10" @@ -8007,13 +8133,13 @@ } }, "node_modules/solid-js": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.8.5.tgz", - "integrity": "sha512-xvtJvzJzWbsn35oKFhW9kNwaxG1Z/YLMsDp4tLVcYZTMPzvzQ8vEZuyDQ6nt7xDArVgZJ7TUFrJUwrui/oq53A==", + "version": "1.8.7", + "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.8.7.tgz", + "integrity": "sha512-9dzrSVieh2zj3SnJ02II6xZkonR6c+j/91b7XZUNcC6xSaldlqjjGh98F1fk5cRJ8ZTkzqF5fPIWDxEOs6QZXA==", "peer": true, "dependencies": { "csstype": "^3.1.0", - "seroval": "^0.12.0" + "seroval": "^0.15.1" } }, "node_modules/solid-swr-store": { @@ -8117,9 +8243,9 @@ "dev": true }, "node_modules/std-env": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.4.3.tgz", - "integrity": "sha512-f9aPhy8fYBuMN+sNfakZV18U39PbalgjXG3lLB9WkaYTxijru61wb57V9wxxNthXM5Sd88ETBWi29qLAsHO52Q==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.6.0.tgz", + "integrity": "sha512-aFZ19IgVmhdB2uX599ve2kE6BIE3YMnQ6Gp6BURhW/oIzpXGKr878TQfAQZn1+i0Flcc/UKUy1gOlcfaUBCryg==", "dev": true }, "node_modules/stop-iteration-iterator": { @@ -8285,9 +8411,9 @@ } }, "node_modules/svelte": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-4.2.2.tgz", - "integrity": "sha512-My2tytF2e2NnHSpn2M7/3VdXT4JdTglYVUuSuK/mXL2XtulPYbeBfl8Dm1QiaKRn0zoULRnL+EtfZHHP0k4H3A==", + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-4.2.8.tgz", + "integrity": "sha512-hU6dh1MPl8gh6klQZwK/n73GiAHiR95IkFsesLPbMeEZi36ydaXL/ZAb4g9sayT0MXzpxyZjR28yderJHxcmYA==", "dependencies": { "@ampproject/remapping": "^2.2.1", "@jridgewell/sourcemap-codec": "^1.4.15", @@ -8308,9 +8434,9 @@ } }, "node_modules/svelte-check": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-3.5.2.tgz", - "integrity": "sha512-5a/YWbiH4c+AqAUP+0VneiV5bP8YOk9JL3jwvN+k2PEPLgpu85bjQc5eE67+eIZBBwUEJzmO3I92OqKcqbp3fw==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-3.6.2.tgz", + "integrity": "sha512-E6iFh4aUCGJLRz6QZXH3gcN/VFfkzwtruWSRmlKrLWQTiO6VzLsivR6q02WYLGNAGecV3EocqZuCDrC2uttZ0g==", "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.17", @@ -8319,14 +8445,14 @@ "import-fresh": "^3.2.1", "picocolors": "^1.0.0", "sade": "^1.7.4", - "svelte-preprocess": "^5.0.4", + "svelte-preprocess": "^5.1.0", "typescript": "^5.0.3" }, "bin": { "svelte-check": "bin/svelte-check" }, "peerDependencies": { - "svelte": "^3.55.0 || ^4.0.0-next.0 || ^4.0.0" + "svelte": "^3.55.0 || ^4.0.0-next.0 || ^4.0.0 || ^5.0.0-next.0" } }, "node_modules/svelte-confetti": { @@ -8390,9 +8516,9 @@ } }, "node_modules/svelte-preprocess": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/svelte-preprocess/-/svelte-preprocess-5.0.4.tgz", - "integrity": "sha512-ABia2QegosxOGsVlsSBJvoWeXy1wUKSfF7SWJdTjLAbx/Y3SrVevvvbFNQqrSJw89+lNSsM58SipmZJ5SRi5iw==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/svelte-preprocess/-/svelte-preprocess-5.1.1.tgz", + "integrity": "sha512-p/Dp4hmrBW5mrCCq29lEMFpIJT2FZsRlouxEc5qpbOmXRbaFs7clLs8oKPwD3xCFyZfv1bIhvOzpQkhMEVQdMw==", "dev": true, "hasInstallScript": true, "dependencies": { @@ -8415,7 +8541,7 @@ "sass": "^1.26.8", "stylus": "^0.55.0", "sugarss": "^2.0.0 || ^3.0.0 || ^4.0.0", - "svelte": "^3.23.0 || ^4.0.0-next.0 || ^4.0.0", + "svelte": "^3.23.0 || ^4.0.0-next.0 || ^4.0.0 || ^5.0.0-next.0", "typescript": ">=3.9.5 || ^4.0.0 || ^5.0.0" }, "peerDependenciesMeta": { @@ -8463,6 +8589,19 @@ "node": ">=12" } }, + "node_modules/svelte-sequential-preprocessor": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/svelte-sequential-preprocessor/-/svelte-sequential-preprocessor-2.0.1.tgz", + "integrity": "sha512-N5JqlBni6BzElxmuFrOPxOJnjsxh1cFDACLEVKs8OHBcx8ZNRO1p5SxuQex1m3qbLzAC8G99EHeWcxGkjyKjLQ==", + "dev": true, + "dependencies": { + "svelte": "^4.0.1", + "tslib": "~2.6.0" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/svelte/node_modules/aria-query": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", @@ -8512,6 +8651,12 @@ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", "dev": true }, + "node_modules/tabbable": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", + "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==", + "dev": true + }, "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -8534,9 +8679,9 @@ "dev": true }, "node_modules/the-new-css-reset": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/the-new-css-reset/-/the-new-css-reset-1.11.1.tgz", - "integrity": "sha512-AsNpvcX9YkVja3ZwVYjwULYOyelhse4Atnnple2wPwrKdf3tEBXECBPAoTN+tMSFiFbi00jyprt7F9vhHornMw==" + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/the-new-css-reset/-/the-new-css-reset-1.11.2.tgz", + "integrity": "sha512-m/JQ/srn+e5SAI7MVCZOJ1hoxoE1w1uA96birT52Y9769GN9e0M4K1PBxlz05Vq4HprX11ASBjM2TcQs4WXnXg==" }, "node_modules/tiny-glob": { "version": "0.2.9", @@ -8697,9 +8842,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.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", "devOptional": true, "bin": { "tsc": "bin/tsc", @@ -8710,9 +8855,9 @@ } }, "node_modules/ufo": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.3.1.tgz", - "integrity": "sha512-uY/99gMLIOlJPwATcMVYfqDSxUR9//AUcgZMzwfSTJPDKzA1S8mX4VLqa+fiAtveraQUBCz4FFcwVZBGbwBXIw==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.3.2.tgz", + "integrity": "sha512-o+ORpgGwaYQXgqGDwd+hkS4PuZ3QnmqMMxRuajK/a38L6fTpcE5GPIfrf+L/KemFzfUpeUQc1rRS1iDBozvnFA==", "dev": true }, "node_modules/undici": { @@ -8807,9 +8952,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, "peer": true, "dependencies": { @@ -8822,9 +8967,9 @@ } }, "node_modules/vite": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.0.tgz", - "integrity": "sha512-ulr8rNLA6rkyFAlVWw2q5YJ91v098AFQ2R0PRFwPzREXOUJQPtFUG0t+/ZikhaOCDqFoDhN6/v8Sq0o4araFAw==", + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.1.tgz", + "integrity": "sha512-AXXFaAJ8yebyqzoNB9fu2pHoo/nWX+xZlaRwoeYUxEqBO+Zj4msE5G+BhGBll9lYEKv9Hfks52PAF2X7qDYXQA==", "dev": true, "dependencies": { "esbuild": "^0.18.10", @@ -8991,16 +9136,16 @@ } }, "node_modules/vue": { - "version": "3.3.8", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.3.8.tgz", - "integrity": "sha512-5VSX/3DabBikOXMsxzlW8JyfeLKlG9mzqnWgLQLty88vdZL7ZJgrdgBOmrArwxiLtmS+lNNpPcBYqrhE6TQW5w==", + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.3.11.tgz", + "integrity": "sha512-d4oBctG92CRO1cQfVBZp6WJAs0n8AK4Xf5fNjQCBeKCvMI1efGQ5E3Alt1slFJS9fZuPcFoiAiqFvQlv1X7t/w==", "peer": true, "dependencies": { - "@vue/compiler-dom": "3.3.8", - "@vue/compiler-sfc": "3.3.8", - "@vue/runtime-dom": "3.3.8", - "@vue/server-renderer": "3.3.8", - "@vue/shared": "3.3.8" + "@vue/compiler-dom": "3.3.11", + "@vue/compiler-sfc": "3.3.11", + "@vue/runtime-dom": "3.3.11", + "@vue/server-renderer": "3.3.11", + "@vue/shared": "3.3.11" }, "peerDependencies": { "typescript": "*" diff --git a/package.json b/package.json index f99cbbc8b..410b4d658 100644 --- a/package.json +++ b/package.json @@ -18,12 +18,13 @@ "e2e": "playwright test tests/e2e" }, "dependencies": { - "@appwrite.io/console": "^0.3.0", - "@appwrite.io/pink": "0.1.0-next.9", - "@appwrite.io/pink-icons": "^0.1.0-next.9", + "@appwrite.io/console": "^0.4.2", + "@appwrite.io/pink": "0.2.0", + "@appwrite.io/pink-icons": "0.2.0", "@popperjs/core": "^2.11.8", "@sentry/svelte": "^7.66.0", "@sentry/tracing": "^7.66.0", + "@stripe/stripe-js": "^2.2.0", "ai": "^2.2.11", "analytics": "^0.8.9", "dayjs": "^1.11.9", @@ -40,6 +41,8 @@ "web-vitals": "^3.4.0" }, "devDependencies": { + "@melt-ui/pp": "^0.1.4", + "@melt-ui/svelte": "^0.61.2", "@playwright/test": "^1.37.1", "@sveltejs/adapter-static": "^2.0.3", "@sveltejs/kit": "^1.24.0", @@ -65,6 +68,7 @@ "svelte-check": "^3.5.1", "svelte-jester": "^2.3.2", "svelte-preprocess": "^5.0.4", + "svelte-sequential-preprocessor": "^2.0.1", "tslib": "^2.6.2", "typescript": "^5.2.2", "vite": "^4.4.9", diff --git a/src/lib/actions/analytics.ts b/src/lib/actions/analytics.ts index 8755353fd..8a15993fc 100644 --- a/src/lib/actions/analytics.ts +++ b/src/lib/actions/analytics.ts @@ -256,6 +256,25 @@ export enum Submit { FileCreate = 'submit_file_create', FileDelete = 'submit_file_delete', FileUpdatePermissions = 'submit_file_update_permissions', + BudgetCapUpdate = 'submit_budget_cap_update', + BudgetAlertsUpdate = 'submit_budget_alert_conditions_update', + CreditRedeem = 'submit_credit_redeem', + PaymentMethodCreate = 'submit_payment_method_create', + PaymentMethodUpdate = 'submit_payment_method_update', + PaymentMethodDelete = 'submit_payment_method_delete', + BillingAddressCreate = 'submit_billing_address_create', + BillingAddressUpdate = 'submit_billing_address_update', + BillingAddressDelete = 'submit_billing_address_delete', + OrganizationPaymentUpdate = 'submit_organization_payment_update', + OrganizationPaymentDelete = 'submit_organization_payment_delete', + OrganizationBackupPaymentUpdate = 'submit_organization_backup_payment_update', + OrganizationBackupPaymentDelete = 'submit_organization_backup_payment_delete', + OrganizationBillingAddressUpdate = 'submit_organization_billing_address_update', + OrganizationBillingAddressDelete = 'submit_organization_billing_address_delete', + OrganizationUpgrade = 'submit_organization_upgrade', + OrganizationDowngrade = 'submit_organization_downgrade', + OrganizationBillingTaxIdUpdate = 'submit_organization_billing_tax_id_update', + SupportTicket = 'submit_support_ticket', InstallationCreate = 'submit_installation_create', InstallationDelete = 'submit_installation_delete', EmailChangeLocale = 'submit_email_change_locale', diff --git a/src/lib/commandCenter/panels/ai.svelte b/src/lib/commandCenter/panels/ai.svelte index 1c589e138..20425fe9a 100644 --- a/src/lib/commandCenter/panels/ai.svelte +++ b/src/lib/commandCenter/panels/ai.svelte @@ -15,7 +15,6 @@ const { input, handleSubmit, completion, isLoading, complete, error } = useCompletion({ api: endpoint + '/console/assistant', headers: { - 'content-type': 'application/json', 'x-appwrite-project': 'console' }, credentials: 'include' diff --git a/src/lib/commandCenter/panels/template.svelte b/src/lib/commandCenter/panels/template.svelte index 3b5ce24e7..31a14a33e 100644 --- a/src/lib/commandCenter/panels/template.svelte +++ b/src/lib/commandCenter/panels/template.svelte @@ -369,37 +369,39 @@ --cmd-center-border: hsl(var(--color-neutral-10)); --cmd-center-shadow: 0px 16px 32px 0px rgba(55, 59, 77, 0.04); - --kbd-bg: hsl(var(--color-neutral-30)); + --kbd-bg: hsl(var(--color-neutral-15)); + --kbd-color: hsl(var(--color-neutral-60)); --crumb-bg: hsl(var(--color-neutral-10)); --crumb-color: hsl(var(--color-neutral-100)); --result-bg: hsl(var(--color-neutral-10)); - --footer-bg: linear-gradient(180deg, #fff 49.38%, #e8e9f0 100%); + --footer-bg: linear-gradient(180deg, #fff 0%, #e8e9f0 100%); --icon-color: hsl(var(--color-neutral-50)); - --label-color: hsl(var(--color-neutral-100)); + --label-color: hsl(var(--color-neutral-60)); } :global(.theme-dark) .card { - --cmd-center-bg: hsl(var(--color-neutral-100-new)); - --cmd-center-border: hsl(var(--color-neutral-150)); - --cmd-center-shadow: 0px 16px 32px 0px hsl(var(--color-neutral-110-new)); + --cmd-center-bg: hsl(var(--color-neutral-90)); + --cmd-center-border: hsl(var(--color-neutral-80)); + --cmd-center-shadow: 0px 16px 32px 0px #14141f; - --kbd-bg: hsl(var(--color-neutral-150)); + --kbd-bg: hsl(var(--color-neutral-80)); + --kbd-color: hsl(var(--color-neutral-15)); --crumb-bg: hsl(var(--color-neutral-150)); --crumb-color: hsl(var(--color-neutral-30)); - --result-bg: hsl(var(--color-neutral-200)); + --result-bg: hsl(var(--color-neutral-85)); --footer-bg: linear-gradient( 180deg, - hsl(var(--color-neutral-100-new)) 0%, - hsl(var(--color-neutral-85-new)) 100% + hsl(var(--color-neutral-100)) 0%, + hsl(var(--color-neutral-85)) 100% ); --icon-color: hsl(var(--color-neutral-70)); - --label-color: hsl(var(--color-neutral-30)); + --label-color: hsl(var(--color-neutral-15)); } // Elements @@ -430,6 +432,7 @@ } :global(.kbd) { + color: var(--kbd-color); background-color: var(--kbd-bg); padding-inline: 0.25rem; } diff --git a/src/lib/components/alert.svelte b/src/lib/components/alert.svelte index 4dc90b3ff..c553d6042 100644 --- a/src/lib/components/alert.svelte +++ b/src/lib/components/alert.svelte @@ -1,6 +1,7 @@ + +{#if $organization?.markedForDeletion && !$page.url.pathname.includes('/console/account')} + + + All existing projects in the {$organization.name} organization have been paused. This organization + will be deleted once your upcoming invoice is processed successfully. + + +{/if} diff --git a/src/lib/components/billing/alerts/paymentAuthRequired.svelte b/src/lib/components/billing/alerts/paymentAuthRequired.svelte new file mode 100644 index 000000000..d8819b492 --- /dev/null +++ b/src/lib/components/billing/alerts/paymentAuthRequired.svelte @@ -0,0 +1,29 @@ + + +{#if $actionRequiredInvoices && $actionRequiredInvoices?.invoices?.length && !$page.url.pathname.includes('/console/account')} + + Please authorize your upcoming payment for {$organization.name}. Your bank requires this + security measure to proceed with payment. + + + + + +{/if} diff --git a/src/lib/components/billing/alerts/projectsAtRisk.svelte b/src/lib/components/billing/alerts/projectsAtRisk.svelte new file mode 100644 index 000000000..348fe3ebd --- /dev/null +++ b/src/lib/components/billing/alerts/projectsAtRisk.svelte @@ -0,0 +1,32 @@ + + +{#if $failedInvoice && !$page.url.pathname.includes('/console/account')} + {@const daysPassed = diffDays(new Date($failedInvoice.dueAt), new Date())} + + + {#if daysPassed > 30} + Your scheduled payment on {toLocaleDate($failedInvoice?.dueAt)} failed. To resume + write access of your organization, please update your billing details. + {:else} + Your scheduled payment on {toLocaleDate($failedInvoice?.dueAt)} failed. Access + to paid projects within this organization will be disabled if no action is taken within + 30 days. + {/if} + + + + + +{/if} diff --git a/src/lib/components/billing/alerts/tooManyFreeOrgs.svelte b/src/lib/components/billing/alerts/tooManyFreeOrgs.svelte new file mode 100644 index 000000000..cf37e4d45 --- /dev/null +++ b/src/lib/components/billing/alerts/tooManyFreeOrgs.svelte @@ -0,0 +1,13 @@ + + + + All but one organization will be automatically upgraded to a Pro plan on 31 January 2024. + You can add a payment method or transfer projects from your settings. + + + + + diff --git a/src/lib/components/billing/couponInput.svelte b/src/lib/components/billing/couponInput.svelte new file mode 100644 index 000000000..1f81a3a74 --- /dev/null +++ b/src/lib/components/billing/couponInput.svelte @@ -0,0 +1,74 @@ + + + + + + + {#if couponData?.status === 'error'} +
+ + + {couponData.code} is not a valid promo code + +
+ {:else if couponData?.status === 'active'} +
+
+ + + + {couponData.code} applied (-${couponData.credits}) + + +
+ +
+ {/if} +
diff --git a/src/lib/components/billing/index.ts b/src/lib/components/billing/index.ts new file mode 100644 index 000000000..0d7a98daa --- /dev/null +++ b/src/lib/components/billing/index.ts @@ -0,0 +1,2 @@ +export { default as PaymentBoxes } from './paymentBoxes.svelte'; +export { default as CouponInput } from './couponInput.svelte'; diff --git a/src/lib/components/billing/paymentBoxes.svelte b/src/lib/components/billing/paymentBoxes.svelte new file mode 100644 index 000000000..240ad1c0c --- /dev/null +++ b/src/lib/components/billing/paymentBoxes.svelte @@ -0,0 +1,91 @@ + + + + + + + + {element.brand} ending in {element.last4} + + + + + + Add new payment method + + + + + +
+
+
+
+
+ +
+
+
+
+ + diff --git a/src/lib/components/box.svelte b/src/lib/components/box.svelte index d77ca8eb4..9d164cd57 100644 --- a/src/lib/components/box.svelte +++ b/src/lib/components/box.svelte @@ -5,7 +5,7 @@ export { classes as class }; enum radiuses { - xsmall = '--border-radius-extra-large', + xsmall = '--border-radius-xsmall', small = '--border-radius-small', medium = '--border-radius-medium', large = '--border-radius-large' diff --git a/src/lib/components/card.svelte b/src/lib/components/card.svelte index 24c81e6e1..d5a3cbdb7 100644 --- a/src/lib/components/card.svelte +++ b/src/lib/components/card.svelte @@ -24,6 +24,8 @@ export let isButton = false; export let danger = false; export let href: string = null; + let classes = ''; + export { classes as class }; function getElement() { switch (true) { @@ -39,7 +41,7 @@ @@ -18,8 +25,12 @@ {#if total > 3 ? total < limit + offset : total % 2 !== 0} - - - + {#if isCloud && serviceId && total >= planLimit} + + {:else} + + + + {/if} {/if} diff --git a/src/lib/components/cardGrid.svelte b/src/lib/components/cardGrid.svelte index 20622e636..67e0d2ad4 100644 --- a/src/lib/components/cardGrid.svelte +++ b/src/lib/components/cardGrid.svelte @@ -10,7 +10,7 @@
-
+
diff --git a/src/lib/components/cardPlanLimit.svelte b/src/lib/components/cardPlanLimit.svelte new file mode 100644 index 000000000..966337d2f --- /dev/null +++ b/src/lib/components/cardPlanLimit.svelte @@ -0,0 +1,16 @@ + + +
+
+

Upgrade your plan to add more {service}

+ +
+
diff --git a/src/lib/components/collapsibleItem.svelte b/src/lib/components/collapsibleItem.svelte index cd44bc824..8397454dc 100644 --- a/src/lib/components/collapsibleItem.svelte +++ b/src/lib/components/collapsibleItem.svelte @@ -9,7 +9,7 @@
+ import { sdk } from '$lib/stores/sdk'; + + export let brand: string; + export let width = 23; + export let height = 16; + + function getCreditCardImage(brand: string, width = 46, height = 32) { + if (!brand) return ''; + return sdk.forConsole.avatars.getCreditCard(brand, width, height).toString(); + } + + +{brand} diff --git a/src/lib/components/creditCardInfo.svelte b/src/lib/components/creditCardInfo.svelte new file mode 100644 index 000000000..b3b89d0d7 --- /dev/null +++ b/src/lib/components/creditCardInfo.svelte @@ -0,0 +1,36 @@ + + +
+
+
+ +

+ {paymentMethod?.brand} ending in {paymentMethod?.last4} +

+ +
+

+ Expires {paymentMethod?.expiryMonth}/{paymentMethod?.expiryYear} +

+ {#if paymentMethod?.name} +

+ {paymentMethod.name} +

+ {/if} +
+ + +
+ {#if paymentMethod?.expired} + + This payment method has expired + + {/if} +
diff --git a/src/lib/components/drop.svelte b/src/lib/components/drop.svelte index 31077c10d..d6c899df2 100644 --- a/src/lib/components/drop.svelte +++ b/src/lib/components/drop.svelte @@ -143,7 +143,7 @@ .drop-arrow::before { content: ''; transform: rotate(45deg); - background: hsl(var(--color-neutral-200)); + background: hsl(var(--color-neutral-85)); body.theme-light & { background: hsl(var(--color-neutral-10)); diff --git a/src/lib/components/dropListItem.svelte b/src/lib/components/dropListItem.svelte index 98d7c2676..acf02686b 100644 --- a/src/lib/components/dropListItem.svelte +++ b/src/lib/components/dropListItem.svelte @@ -4,6 +4,7 @@ export let disabled = false; export let icon: string = null; export let event: string = null; + export let loading = false; function track() { if (!event) { @@ -17,10 +18,17 @@
  • -
  • diff --git a/src/lib/components/dropListLink.svelte b/src/lib/components/dropListLink.svelte index f0b0ca024..0267a21d0 100644 --- a/src/lib/components/dropListLink.svelte +++ b/src/lib/components/dropListLink.svelte @@ -1,13 +1,27 @@
  • - + {#if !noMedia} + + {/if}
    @@ -63,7 +67,8 @@ on:click={track} aria-label="create" type="button" - class="card u-grid u-cross-center u-width-full-line dashed"> + class="card u-grid u-cross-center u-width-full-line dashed" + class:common-section={marginTop}>
    diff --git a/src/lib/components/fakeModal.svelte b/src/lib/components/fakeModal.svelte new file mode 100644 index 000000000..4daec9409 --- /dev/null +++ b/src/lib/components/fakeModal.svelte @@ -0,0 +1,154 @@ + + + + +{#if show} + +
    + +
    +{/if} + + diff --git a/src/lib/components/filters/content.svelte b/src/lib/components/filters/content.svelte index 6da14dcc6..098376a90 100644 --- a/src/lib/components/filters/content.svelte +++ b/src/lib/components/filters/content.svelte @@ -115,7 +115,7 @@
    -
    +
      ({ @@ -130,7 +130,7 @@ options={operatorsForColumn} placeholder="Select operator" bind:value={operatorKey} /> -
    + {#if column && operator && !operator?.hideInput}
    {#if column.type === 'integer' || column.type === 'double'} diff --git a/src/lib/components/floatingActionBar.svelte b/src/lib/components/floatingActionBar.svelte index 066852314..28b7a8e3b 100644 --- a/src/lib/components/floatingActionBar.svelte +++ b/src/lib/components/floatingActionBar.svelte @@ -26,13 +26,13 @@ } :global(.theme-dark) .floating-action-bar { - border: 1px solid hsl(var(--color-neutral-200)); - background: hsl(var(--color-neutral-300)); + border: 1px solid hsl(var(--color-neutral-85)); + background: hsl(var(--color-neutral-90)); box-shadow: 0px 6px 16px 8px #14141f; } :global(.theme-light) .floating-action-bar { - border: 1px solid hsl(var(--color-neutral-30)); + border: 1px solid hsl(var(--color-neutral-15)); background: hsl(var(--color-neutral-0)); box-shadow: 0px 6px 16px 0px rgba(55, 59, 77, 0.14); } diff --git a/src/lib/components/gridItem1.svelte b/src/lib/components/gridItem1.svelte index e5041f9da..ac1bb8ea0 100644 --- a/src/lib/components/gridItem1.svelte +++ b/src/lib/components/gridItem1.svelte @@ -7,7 +7,7 @@
    - +
    diff --git a/src/lib/components/heading.svelte b/src/lib/components/heading.svelte index f6c4d4740..440693da1 100644 --- a/src/lib/components/heading.svelte +++ b/src/lib/components/heading.svelte @@ -6,8 +6,10 @@ export let size: Size; export let trimmed = true; export let id: string = null; + let classes = ''; + export { classes as class }; - + diff --git a/src/lib/components/index.ts b/src/lib/components/index.ts index 4b12577c8..781ce567c 100644 --- a/src/lib/components/index.ts +++ b/src/lib/components/index.ts @@ -46,13 +46,20 @@ export { default as EventModal } from './eventModal.svelte'; export { default as Status } from './status.svelte'; export { default as Heading } from './heading.svelte'; export { default as Output } from './output.svelte'; +export { default as Support } from './support.svelte'; export { default as ViewSelector } from './viewSelector.svelte'; export { default as LabelCard } from './labelCard.svelte'; +export { default as RegionCard } from './regionCard.svelte'; export { default as Limit } from './limit.svelte'; export { default as PaginationWithLimit } from './paginationWithLimit.svelte'; export { default as ClickableList } from './clickableList.svelte'; export { default as ClickableListItem } from './clickableListItem.svelte'; export { default as Id } from './id.svelte'; +export { default as ProgressBar } from './progressBar.svelte'; +export { default as ProgressBarBig } from './progressBarBig.svelte'; +export { default as CreditCardInfo } from './creditCardInfo.svelte'; +export { default as CreditCardBrandImage } from './creditCardBrandImage.svelte'; +export { default as CardPlanLimit } from './cardPlanLimit.svelte'; export { default as NumericList } from './numericList.svelte'; export { default as NumericListItem } from './numericListItem.svelte'; export { default as EyebrowHeading } from './eyebrowHeading.svelte'; @@ -60,3 +67,7 @@ export { default as SvgIcon } from './svgIcon.svelte'; export { default as MigrationBox } from './migrationBox.svelte'; export { default as FloatingActionBar } from './floatingActionBar.svelte'; export { default as LoadingDots } from './loadingDots.svelte'; +export { default as FakeModal } from './fakeModal.svelte'; +export { default as RadioBoxes } from './radioBoxes.svelte'; +export { default as ModalWrapper } from './modalWrapper.svelte'; +export { default as ModalSideCol } from './modalSideCol.svelte'; diff --git a/src/lib/components/labelCard.svelte b/src/lib/components/labelCard.svelte index 5565b392e..9d30f9b0c 100644 --- a/src/lib/components/labelCard.svelte +++ b/src/lib/components/labelCard.svelte @@ -1,4 +1,6 @@ diff --git a/src/lib/components/list.svelte b/src/lib/components/list.svelte index 2b3b007b5..518497ae7 100644 --- a/src/lib/components/list.svelte +++ b/src/lib/components/list.svelte @@ -1,3 +1,4 @@ -
      + +
      diff --git a/src/lib/components/listItem.svelte b/src/lib/components/listItem.svelte index 68b959ff2..26805f943 100644 --- a/src/lib/components/listItem.svelte +++ b/src/lib/components/listItem.svelte @@ -1,16 +1,8 @@ -
    • -
      - -
      - -
      -

      - -

      - -
      +
    • +
    • diff --git a/src/lib/components/modal.svelte b/src/lib/components/modal.svelte index 636e713ca..816ce2046 100644 --- a/src/lib/components/modal.svelte +++ b/src/lib/components/modal.svelte @@ -1,6 +1,5 @@ - - - - {#if show} - - + + +
    + + {#if $$slots.footer} + + {/if} + + diff --git a/src/lib/components/modalSideCol.svelte b/src/lib/components/modalSideCol.svelte new file mode 100644 index 000000000..81dbe2464 --- /dev/null +++ b/src/lib/components/modalSideCol.svelte @@ -0,0 +1,77 @@ + + + +
    +
    + +
    +
    + + +
    +
    +
    + + diff --git a/src/lib/components/modalWrapper.svelte b/src/lib/components/modalWrapper.svelte new file mode 100644 index 000000000..0e28bdf61 --- /dev/null +++ b/src/lib/components/modalWrapper.svelte @@ -0,0 +1,82 @@ + + + + + + {#if show} + + {/if} + diff --git a/src/lib/components/permissions/custom.svelte b/src/lib/components/permissions/custom.svelte index 3d2d36693..35abd34db 100644 --- a/src/lib/components/permissions/custom.svelte +++ b/src/lib/components/permissions/custom.svelte @@ -1,5 +1,5 @@ - -

    - Custom permissions allow you to grant access to specific users or teams using their ID and - role. -

    + - - - A permission should be formatted as: user:[USER_ID] or team:[TEAM_ID]/[ROLE]¸ - + + + + A permission should be formatted as: user:[USER_ID] or team:[TEAM_ID]/[ROLE]¸ + + diff --git a/src/lib/components/permissions/label.svelte b/src/lib/components/permissions/label.svelte index 531c25284..b927b544f 100644 --- a/src/lib/components/permissions/label.svelte +++ b/src/lib/components/permissions/label.svelte @@ -1,5 +1,5 @@ - -

    Labels allow you to grant access to users with the specfied label.

    + - - Only alphanumeric characters are allowed. + + + Only alphanumeric characters are allowed. + diff --git a/src/lib/components/progressBar.svelte b/src/lib/components/progressBar.svelte new file mode 100644 index 000000000..406f69c02 --- /dev/null +++ b/src/lib/components/progressBar.svelte @@ -0,0 +1,38 @@ + + +
    +
    +

    + {#if icon} +

    +

    + {progress}% +

    +
    +
    +
    + {used}{unit} + {max}{unit} +
    +
    diff --git a/src/lib/components/progressBarBig.svelte b/src/lib/components/progressBarBig.svelte new file mode 100644 index 000000000..3a177f6a3 --- /dev/null +++ b/src/lib/components/progressBarBig.svelte @@ -0,0 +1,36 @@ + + +
    +
    +
    +

    + {currentValue} + {currentUnit} +

    +

    {progress}%

    +
    +

    + {maxValue} + {maxUnit} +

    +
    + {#if showBar} +
    = 75 && progress < 100} + class:is-danger={progress >= 100} + style:--graph-size={Math.max(Math.min(progress, maximum), minimum) + '%'} /> + {/if} +
    diff --git a/src/lib/components/radioBoxes.svelte b/src/lib/components/radioBoxes.svelte new file mode 100644 index 000000000..74e84a85a --- /dev/null +++ b/src/lib/components/radioBoxes.svelte @@ -0,0 +1,41 @@ + + +
    + {#if total} + {#each elements as element} + {@const value = element[variableName]?.toString()} +
    + + + +
    + {/each} + {/if} + +
    + {#if total} + + + Add new {name} + + + {/if} + {#if group === null} + + {/if} +
    +
    diff --git a/src/lib/components/regionCard.svelte b/src/lib/components/regionCard.svelte new file mode 100644 index 000000000..3e1964802 --- /dev/null +++ b/src/lib/components/regionCard.svelte @@ -0,0 +1,34 @@ + + + diff --git a/src/lib/components/step.svelte b/src/lib/components/step.svelte index 17597f4c1..a229f65ba 100644 --- a/src/lib/components/step.svelte +++ b/src/lib/components/step.svelte @@ -3,12 +3,14 @@ export let current = false; export let currentSub = 0; export let isSub = false; - export let step: { text: string; substeps?: { text: string }[] }; + export let step: { text: string; disabled?: boolean; substeps?: { text: string }[] };
  • + {:else} + + {/if} + +{/if} +
    +
    +

    Troubleshooting

    + +
    + {#key $app.themeInUse} + + {/key} +
    +
    + +
    +
    +
    +
    +

    Community support

    +

    Get help from our community

    +
    +
      +
    • + +
    • +
    • + +
    • +
    +
    diff --git a/src/lib/constants.ts b/src/lib/constants.ts index a2107d03c..393623360 100644 --- a/src/lib/constants.ts +++ b/src/lib/constants.ts @@ -3,7 +3,12 @@ export const CARD_LIMIT = 6; // default card limit export const INTERVAL = 5 * 60000; // default interval to check for feedback export enum Dependencies { + CREDIT = 'dependency:credit', + INVOICES = 'dependency:invoices', + ADDRESS = 'dependency:address', + PAYMENT_METHODS = 'dependency:paymentMethods', ORGANIZATION = 'dependency:organization', + MEMBERS = 'dependency:members', PROJECT = 'dependency:project', PROJECT_VARIABLES = 'dependency:project_variables', PROJECT_INSTALLATIONS = 'dependency:project_installations', @@ -273,3 +278,348 @@ export const eventServices: Array = [ ] } ]; + +export const usageRates = { + 'tier-0': [ + { + id: 'members', + resource: 'Organization members', + amount: 1, + unit: '', + rate: '$20/member' + }, + { id: 'bandwith', resource: 'Bandwidth', amount: 10, unit: 'GB', rate: '$0.04/GB' }, + { id: 'storage', resource: 'Storage', amount: 2, unit: 'GB', rate: '$0.025/GB' }, + { + id: 'executions', + resource: 'Function executions', + amount: 750000, + unit: 'executions', + rate: '$2/1M executions' + }, + { + id: 'users', + resource: 'Active users', + amount: 200000, + unit: 'AU', + rate: '$0.0012/user' + }, + { + id: 'connections', + resource: 'Concurrent connections', + amount: 750, + unit: 'connections', + rate: '$5/1K connections' + } + ], + 'tier-1': [ + { + id: 'members', + resource: 'Organization members', + amount: 'Unlimited', + unit: '', + rate: '$20/member' + }, + { id: 'bandwith', resource: 'Bandwidth', amount: 1, unit: 'TB', rate: '$0.04/GB' }, + { id: 'storage', resource: 'Storage', amount: 150, unit: 'GB', rate: '$0.025/GB' }, + { + id: 'executions', + resource: 'Function executions', + amount: 3500000, + unit: 'executions', + rate: '$2/1M executions' + }, + { + id: 'users', + resource: 'Active users', + amount: 200000, + unit: 'AU', + rate: '$0.0012/user' + }, + { + id: 'connections', + resource: 'Concurrent connections', + amount: 750, + unit: 'connections', + rate: '$5/1K connections' + } + ], + 'tier-2': [ + { + id: 'members', + resource: 'Organization members', + amount: 'Unlimited', + unit: '', + rate: '$20/member' + }, + { id: 'bandwith', resource: 'Bandwidth', amount: 1, unit: 'TB', rate: '$0.04/GB' }, + { id: 'storage', resource: 'Storage', amount: 150, unit: 'GB', rate: '$0.025/GB' }, + { + id: 'executions', + resource: 'Function executions', + amount: 3500000, + unit: 'executions', + rate: '$2/1M executions' + }, + { + id: 'users', + resource: 'Active users', + amount: 200000, + unit: 'AU', + rate: '$0.0012/user' + }, + { + id: 'connections', + resource: 'Concurrent connections', + amount: 750, + unit: 'connections', + rate: '$5/1K connections' + } + ] +}; + +//resources: bandwidth, buckets, file size limit, functions, executions, users,teams,logs, members, platforms, webhooks, databases, connections, messages +export const limitRates = { + 'tier-0': [ + { + id: 'bandwith', + amount: 10, + unit: 'GB' + }, + { + id: 'buckets', + amount: 3, + unit: '' + }, + { + id: 'file-size-limit', + amount: 1, + unit: 'MB' + }, + { + id: 'storage', + amount: 5, + unit: 'GB' + }, + { + id: 'functions', + amount: 1, + unit: '' + }, + { + id: 'executions', + amount: 750000, + unit: 'executions' + }, + { + id: 'users', + amount: 200000, + unit: 'AU' + }, + + { + id: 'teams', + amount: 1, + unit: '' + }, + + { + id: 'logs', + amount: 1, + unit: '' + }, + + { + id: 'members', + amount: 1, + unit: '' + }, + { + id: 'platforms', + amount: 1, + unit: '' + }, + { + id: 'webhooks', + amount: 1, + unit: '' + }, + { + id: 'databases', + amount: 1, + unit: '' + }, + { + id: 'connections', + amount: 1, + unit: '' + }, + { + id: 'messages', + amount: 1, + unit: '' + } + ], + 'tier-1': [ + { + id: 'bandwith', + amount: 10, + unit: 'GB' + }, + { + id: 'buckets', + amount: 1, + unit: '' + }, + { + id: 'file-size-limit', + amount: 5, + unit: 'MB' + }, + { + id: 'storage', + amount: 5, + unit: 'GB' + }, + { + id: 'functions', + amount: 1, + unit: '' + }, + { + id: 'executions', + amount: 750000, + unit: 'executions' + }, + { + id: 'users', + amount: 200000, + unit: 'AU' + }, + + { + id: 'teams', + amount: 1, + unit: '' + }, + { + id: 'logs', + amount: 1, + unit: '' + }, + { + id: 'members', + amount: 1, + unit: '' + }, + { + id: 'platforms', + amount: 1, + unit: '' + }, + { + id: 'webhooks', + amount: 1, + unit: '' + }, + { + id: 'databases', + amount: 1, + unit: '' + }, + { + id: 'connections', + amount: 1, + unit: '' + }, + { + id: 'messages', + amount: 1, + unit: '' + } + ], + 'tier-2': [ + { + id: 'bandwith', + amount: 10, + unit: 'GB' + }, + { + id: 'buckets', + amount: 1, + unit: '' + }, + { + id: 'file-size-limit', + amount: 5, + unit: 'MB' + }, + { + id: 'storage', + amount: 5, + unit: 'GB' + }, + { + id: 'functions', + amount: 1, + unit: '' + }, + { + id: 'executions', + amount: 750000, + unit: 'executions' + }, + { + id: 'users', + amount: 200000, + unit: 'AU' + }, + + { + id: 'teams', + amount: 1, + unit: '' + }, + { + id: 'logs', + amount: 1, + unit: '' + }, + { + id: 'members', + amount: 1, + unit: '' + }, + { + id: 'platforms', + amount: 1, + unit: '' + }, + { + id: 'webhooks', + amount: 1, + unit: '' + }, + { + id: 'databases', + amount: 1, + unit: '' + }, + { + id: 'connections', + amount: 1, + unit: '' + }, + { + id: 'messages', + amount: 1, + unit: '' + } + ] +}; + +export enum BillingPlan { + STARTER = 'tier-0', + PRO = 'tier-1', + SCALE = 'tier-2' +} diff --git a/src/lib/elements/flag.svelte b/src/lib/elements/flag.svelte new file mode 100644 index 000000000..d1088bddb --- /dev/null +++ b/src/lib/elements/flag.svelte @@ -0,0 +1,28 @@ + + +{name} diff --git a/src/lib/elements/forms/button.svelte b/src/lib/elements/forms/button.svelte index af466aa46..30bcfb871 100644 --- a/src/lib/elements/forms/button.svelte +++ b/src/lib/elements/forms/button.svelte @@ -10,17 +10,20 @@ export let github = false; export let text = false; export let danger = false; - export let disabled = false; export let round = false; + export let link = false; + export let disabled = false; export let external = false; export let href: string = null; export let fullWidth = false; + export let fullWidthMobile = false; export let ariaLabel: string = null; export let noMargin = false; export let event: string = null; let classes: string = undefined; export { classes as class }; export let actions: MultiActionArray = []; + export let submissionLoader = false; const isSubmitting = hasContext('form') ? getContext('form').isSubmitting @@ -39,7 +42,7 @@ } $: resolvedClasses = [ - 'button', + link ? 'link' : 'button', disabled && 'is-disabled', round && 'is-only-icon', secondary && 'is-secondary', @@ -47,6 +50,7 @@ text && 'is-text', danger && 'is-danger', fullWidth && 'is-full-width', + fullWidthMobile && 'is-full-width-mobile', noMargin && 'u-padding-inline-0', classes ] @@ -74,6 +78,12 @@ aria-label={ariaLabel} type={submit ? 'submit' : 'button'} use:multiAction={actions}> - + {#if $isSubmitting && submissionLoader} +
  • + {/each} + +

    Create a new project

    +
    + + {:else} + + {/if} - - + + - - + + +{/if} diff --git a/src/routes/console/organization-[organization]/+page.ts b/src/routes/console/organization-[organization]/+page.ts index fab93a7b4..e0e748f0e 100644 --- a/src/routes/console/organization-[organization]/+page.ts +++ b/src/routes/console/organization-[organization]/+page.ts @@ -1,10 +1,12 @@ import { Query } from '@appwrite.io/console'; import { sdk } from '$lib/stores/sdk'; import { getLimit, getPage, pageToOffset } from '$lib/helpers/load'; -import { CARD_LIMIT } from '$lib/constants'; +import { CARD_LIMIT, Dependencies } from '$lib/constants'; import type { PageLoad } from './$types'; -export const load: PageLoad = async ({ params, url, route }) => { +export const load: PageLoad = async ({ params, url, route, depends, parent }) => { + await parent(); + depends(Dependencies.ORGANIZATION); const page = getPage(url); const limit = getLimit(url, route, CARD_LIMIT); const offset = pageToOffset(page, limit); diff --git a/src/routes/console/organization-[organization]/billing/+page.svelte b/src/routes/console/organization-[organization]/billing/+page.svelte new file mode 100644 index 000000000..a6055bedb --- /dev/null +++ b/src/routes/console/organization-[organization]/billing/+page.svelte @@ -0,0 +1,103 @@ + + + + {#if $failedInvoice} + + + The scheduled payment for {$organization.name} failed + + To avoid service disruptions in organization's your projects, please verify your payment + details and update them if necessary. + + {/if} + {#if defaultPaymentMethod?.failed && !backupPaymentMethod} + + + The default payment method for {$organization.name} has expired + + To avoid service disruptions in your organization's projects, please update your payment + details. + + {/if} + {#if $organization?.billingPlanDowngrade} + + Your organization will change to a Starter plan once your current billing cycle ends on {toLocaleDate( + $organization.billingNextInvoiceDate + )}. + + {/if} +
    + Billing +
    + + + + + + + {#if $organization?.billingPlan !== BillingPlan.STARTER && !!$organization?.billingBudget} + + {/if} + +
    diff --git a/src/routes/console/organization-[organization]/billing/+page.ts b/src/routes/console/organization-[organization]/billing/+page.ts new file mode 100644 index 000000000..a1eb3b685 --- /dev/null +++ b/src/routes/console/organization-[organization]/billing/+page.ts @@ -0,0 +1,18 @@ +import { Dependencies } from '$lib/constants'; +import { sdk } from '$lib/stores/sdk'; +import type { PageLoad } from './$types'; + +export const load: PageLoad = async ({ parent, depends }) => { + const { organization } = await parent(); + depends(Dependencies.PAYMENT_METHODS); + depends(Dependencies.ORGANIZATION); + depends(Dependencies.CREDIT); + depends(Dependencies.INVOICES); + depends(Dependencies.ADDRESS); + + return { + paymentMethods: await sdk.forConsole.billing.listPaymentMethods(), + addressList: await sdk.forConsole.billing.listAddresses(), + aggregationList: await sdk.forConsole.billing.listAggregation(organization.$id) + }; +}; diff --git a/src/routes/console/organization-[organization]/billing/addCreditModal.svelte b/src/routes/console/organization-[organization]/billing/addCreditModal.svelte new file mode 100644 index 000000000..f0bb10ba9 --- /dev/null +++ b/src/routes/console/organization-[organization]/billing/addCreditModal.svelte @@ -0,0 +1,50 @@ + + + + Apply Appwrite credits to your organization. + + + + + + + + + + diff --git a/src/routes/console/organization-[organization]/billing/addCreditWizard.svelte b/src/routes/console/organization-[organization]/billing/addCreditWizard.svelte new file mode 100644 index 000000000..5b4029d34 --- /dev/null +++ b/src/routes/console/organization-[organization]/billing/addCreditWizard.svelte @@ -0,0 +1,68 @@ + + + diff --git a/src/routes/console/organization-[organization]/billing/availableCredit.svelte b/src/routes/console/organization-[organization]/billing/availableCredit.svelte new file mode 100644 index 000000000..753e389d7 --- /dev/null +++ b/src/routes/console/organization-[organization]/billing/availableCredit.svelte @@ -0,0 +1,117 @@ + + + + Available credit + +

    Appwrite credit will automatically be applied to your next invoice.

    + +
    +

    + Credit balance ${balance} +

    + {#if creditList?.total} + + {/if} +
    + {#if creditList?.total} + + + Date Added + Expiry Date + Amount + + + {#each creditList.credits as credit} + + + {toLocaleDate(credit.$createdAt)} + + + {toLocaleDate(credit.expiration)} + + + ${credit.credits} + + + {/each} + +
    +
    +

    Total results: {creditList?.total}

    + +
    + {:else} + Add credits + {/if} +
    +
    + + diff --git a/src/routes/console/organization-[organization]/billing/billingAddress.svelte b/src/routes/console/organization-[organization]/billing/billingAddress.svelte new file mode 100644 index 000000000..aa432851b --- /dev/null +++ b/src/routes/console/organization-[organization]/billing/billingAddress.svelte @@ -0,0 +1,166 @@ + + + + Billing address + +

    + View or update your billing address. This address will be included in your invoices from + Appwrite. +

    + + {#if $organization?.billingAddressId && billingAddress} +
    +
    +
    +

    {billingAddress.streetAddress}

    + {#if billingAddress?.addressLine2} +

    {billingAddress.addressLine2}

    + {/if} +

    {billingAddress.city}

    +

    {billingAddress.state}

    +

    {billingAddress.postalCode}

    +

    {billingAddress.country}

    +
    + + + + + { + showEdit = true; + showBillingAddressDropdown = false; + }}> + Edit + + { + showReplace = true; + showBillingAddressDropdown = false; + }}> + Replace + + + +
    +
    + {:else} +
    +
    +
    + + + + {#if $addressList?.total} + {#each $addressList.billingAddresses as address} + addAddress(address?.$id)}> +

    + {address.streetAddress}, + {#if address?.addressLine2} + {address.addressLine2}, + {/if} + {address.city}, + {address.state}, + {address.postalCode}, + {address.country} +

    +
    + {/each} + {/if} + { + showCreate = true; + showDropdown = false; + }}> + Add new billing address + +
    +
    +
    +
    + Add a billing address +
    +
    +
    + {/if} +
    +
    + +{#if showCreate} + +{/if} +{#if showEdit} + +{/if} +{#if showReplace} + +{/if} diff --git a/src/routes/console/organization-[organization]/billing/budgetAlert.svelte b/src/routes/console/organization-[organization]/billing/budgetAlert.svelte new file mode 100644 index 000000000..b89e7cdc7 --- /dev/null +++ b/src/routes/console/organization-[organization]/billing/budgetAlert.svelte @@ -0,0 +1,143 @@ + + +
    + + Budget alerts + +

    + Get notified by email when your organization reaches or exceeds a percent of your + specified budget cap. You can set a maximum of 3 alerts. +

    + + +
    + (search = selectedAlert.toString())} /> +
    + +
    +
    +
    + + {#if alerts.length} + + + Alert at budget cap % + + + + {#each alerts.sort() as alert} + + + {alert}% + + + + + + {/each} + +
    + {/if} +
    + + + + +
    +
    diff --git a/src/routes/console/organization-[organization]/billing/budgetCap.svelte b/src/routes/console/organization-[organization]/billing/budgetCap.svelte new file mode 100644 index 000000000..137c70ba4 --- /dev/null +++ b/src/routes/console/organization-[organization]/billing/budgetCap.svelte @@ -0,0 +1,98 @@ + + +
    + + Budget cap + +

    + Restrict your resource usage by setting a budget cap. +

    + + {#if $organization?.billingPlan === BillingPlan.STARTER} + + + Budget caps are a Pro plan feature + + Upgrade to a Pro plan to set a budget cap for your organization. For more information + on what you can do with a Pro plan, + view our pricing guide. + + {:else} + + + + Budget cap limits do not include the base amount of your plan. Cap usage + is reset at the beginning of each billing cycle. + + + {#if capActive} + + {/if} + + {/if} + + + + + +
    +
    diff --git a/src/routes/console/organization-[organization]/billing/deleteOrgPayment.svelte b/src/routes/console/organization-[organization]/billing/deleteOrgPayment.svelte new file mode 100644 index 000000000..747b538ec --- /dev/null +++ b/src/routes/console/organization-[organization]/billing/deleteOrgPayment.svelte @@ -0,0 +1,88 @@ + + +{#if disabled} + +

    + The {isBackup ? 'backup' : 'default'} payment method cannot be deleted as + {$organization?.name} + has an upcoming invoice. To proceed with deletion, set a {isBackup + ? 'default' + : 'backup'} or add a new {isBackup ? 'backup' : 'default'} payment method. +

    + + + +
    +{:else} + +

    + Are you sure you want to delete the payment method from {$organization?.name}? +

    + + + + +
    +{/if} diff --git a/src/routes/console/organization-[organization]/billing/paymentHistory.svelte b/src/routes/console/organization-[organization]/billing/paymentHistory.svelte new file mode 100644 index 000000000..d0b628c72 --- /dev/null +++ b/src/routes/console/organization-[organization]/billing/paymentHistory.svelte @@ -0,0 +1,146 @@ + + + + Payment history + +

    + Transaction history for this organization. Download invoices for more details about your + payments. +

    + + {#if invoiceList.total - 1 > 0} + + + Due Date + Status + Amount Due + + + + {#each invoiceList?.invoices as invoice, i} + {@const status = invoice.status} + {#if i !== 0} + + + {toLocaleDate(invoice.dueAt)} + + + + + {status === 'requires_authentication' ? 'failed' : status} + + + ${invoice.amount} + + + + + + (showDropdown[i] = !showDropdown[i])} + event="view_invoice"> + View invoice + + { + showDropdown[i] = !showDropdown[i]; + }} + event="download_invoice"> + Download PDF + + + + + + {/if} + {/each} + + +
    +

    Total results: {invoiceList?.total - 1 ?? 0}

    + +
    + {:else} + +

    + You have no payment history. After you receive your first invoice, you'll see it + here. +

    +
    + {/if} +
    +
    diff --git a/src/routes/console/organization-[organization]/billing/paymentMethods.svelte b/src/routes/console/organization-[organization]/billing/paymentMethods.svelte new file mode 100644 index 000000000..ae44de05e --- /dev/null +++ b/src/routes/console/organization-[organization]/billing/paymentMethods.svelte @@ -0,0 +1,329 @@ + + + + Payment methods + +

    View or update your organization payment methods here.

    + +
    +

    Default

    + {#if $organization?.paymentMethodId} + + + + + { + isSelectedBackup = false; + showEdit = true; + showDropdown = false; + }}> + Edit + + { + isSelectedBackup = false; + showReplace = true; + showDropdown = false; + }}> + Replace + + { + isSelectedBackup = false; + showDelete = true; + showDropdown = false; + }}> + Delete + + + + + {:else} + {@const filteredPaymentMethods = $paymentMethods.paymentMethods.filter( + (o) => !!o.last4 && o.$id !== $organization?.backupPaymentMethodId + )} +
    +
    +
    + + + + {#if $paymentMethods.total} + {#each filteredPaymentMethods as paymentMethod} + { + showDropdown = false; + addPaymentMethod(paymentMethod?.$id); + }}> + +

    + Card ending in {paymentMethod.last4} +

    + +
    +
    + {/each} + {/if} + (showPayment = true)}> + Add new payment method + +
    +
    +
    +
    + Add a payment method +
    +
    +
    + {/if} +
    +
    +

    Backup

    + {#if $organization?.backupPaymentMethodId} + + + + + { + showEdit = true; + isSelectedBackup = true; + showDropdownBackup = false; + }}> + Edit + + { + showReplace = true; + isSelectedBackup = true; + showDropdownBackup = false; + }}> + Replace + + { + showDelete = true; + isSelectedBackup = true; + showDropdownBackup = false; + }}> + Delete + + + + + {:else} + {@const filteredPaymentMethods = $paymentMethods.paymentMethods.filter( + (o) => !!o.last4 && o.$id !== $organization?.paymentMethodId + )} +
    +
    +
    + + + + {#if $paymentMethods.total} + {#each filteredPaymentMethods as paymentMethod} + { + showDropdownBackup = true; + addBackupPaymentMethod(paymentMethod?.$id); + }}> + +

    + Card ending in {paymentMethod.last4} +

    + +
    +
    + {/each} + {/if} + (showPayment = true)}> + Add new payment method + +
    +
    +
    +
    + Add a backup payment method + +
    +
    +
    + {/if} +
    +
    +
    + +{#if showPayment && isCloud && hasStripePublicKey} + { + if (isSelectedBackup) { + addBackupPaymentMethod(e.detail.$id); + } else { + addPaymentMethod(e.detail.$id); + } + }} /> +{/if} +{#if showEdit && isCloud && hasStripePublicKey} + +{/if} +{#if isCloud && hasStripePublicKey} + +{/if} +{#if showDelete && isCloud && hasStripePublicKey} + +{/if} diff --git a/src/routes/console/organization-[organization]/billing/planSummary.svelte b/src/routes/console/organization-[organization]/billing/planSummary.svelte new file mode 100644 index 000000000..746ae32c1 --- /dev/null +++ b/src/routes/console/organization-[organization]/billing/planSummary.svelte @@ -0,0 +1,160 @@ + + +{#if $organization} + + Overview + +

    + A summary of the current plan. For more information on Appwrite plans, + view our pricing page. + +

    + + +
    +
    +
    + {tierToPlan($organization?.billingPlan)?.name} plan +
    + {#if $organization?.billingPlan !== BillingPlan.STARTER && isTrial} + TRIAL + {/if} +
    + +

    + {#if !extraUsage} + Total to-date: + {/if} + + ${isTrial ? 0 : currentPlan?.price} + +

    +
    + {#if currentInvoice?.usage?.length && $organization?.billingPlan !== BillingPlan.STARTER && !isTrial} + {@const extraMembers = currentInvoice.usage.find((u) => u.name === 'members')} + {#if extraMembers} +
    + Additional members +
      +
    • +

      + {extraMembers.value} + {extraMembers.name} +

      +

      ${extraMembers.amount}

      +
    • +
    +
    + {/if} +
    + Addons +
      + {#each currentInvoice.usage as excess} + {#if ['storage', 'bandwidth'].includes(excess.name)} + {@const excessValue = humanFileSize(excess.value)} +
    • +

      + + {excessValue.value}{excessValue.unit} + + {excess.name} +

      +

      ${excess.amount}

      +
    • + {/if} + {#if ['users', 'executions'].includes(excess.name)} +
    • +

      + {abbreviateNumber(excess.value)} + {excess.name} +

      +

      ${excess.amount}

      +
    • + {/if} + {/each} +
    • +

      Total to-date:

      +

      ${currentInvoice?.amount}

      +
    • +
    +
    + {/if} +
    +
    +

    Billing period:

    +

    + {toLocaleDate($organization?.billingCurrentInvoiceDate)} - {toLocaleDate( + $organization?.billingNextInvoiceDate + )} +

    +
    +
    + + {#if $organization?.billingPlan === BillingPlan.STARTER} +
    + + +
    + {:else} +
    + + +
    + {/if} +
    +
    +{/if} diff --git a/src/routes/console/organization-[organization]/billing/replaceAddress.svelte b/src/routes/console/organization-[organization]/billing/replaceAddress.svelte new file mode 100644 index 000000000..0eb06bbef --- /dev/null +++ b/src/routes/console/organization-[organization]/billing/replaceAddress.svelte @@ -0,0 +1,195 @@ + + + +

    Replace the existing billing address for your organization.

    + {#if addresses?.total} + + + +
    +
    +

    {element.streetAddress}

    + {#if element?.addressLine2} +

    {element.addressLine2}

    + {/if} +

    {element.city}

    +

    {element.state}

    +

    {element.postalCode}

    +

    {element.country}

    +
    + {#if $organization.billingAddressId === element.$id} + Current + {/if} +
    +
    + + Add a new billing address + + + + + + + + + + + +
    +
    + {/if} + + + + +
    diff --git a/src/routes/console/organization-[organization]/billing/replaceCard.svelte b/src/routes/console/organization-[organization]/billing/replaceCard.svelte new file mode 100644 index 000000000..8dfc4fe50 --- /dev/null +++ b/src/routes/console/organization-[organization]/billing/replaceCard.svelte @@ -0,0 +1,222 @@ + + + +

    Replace the existing payment method for your organization.

    + +
    + {#if methods?.total} + {#each filteredMethods as method} +
    + + + + + {method.brand} ending in {method.last4} + + + {#if method.$id === $organization.backupPaymentMethodId} + Backup + {:else if method.$id === $organization.paymentMethodId} + Default + {/if} + + +
    + {/each} + {/if} + +
    + {#if methods?.total} + + Add new payment method + + {/if} + {#if selectedPaymentMethodId === null} + + +
    +
    +
    +
    +
    + +
    +
    +
    + {/if} +
    +
    +
    + + + + +
    + + diff --git a/src/routes/console/organization-[organization]/billing/store.ts b/src/routes/console/organization-[organization]/billing/store.ts new file mode 100644 index 000000000..e75622d62 --- /dev/null +++ b/src/routes/console/organization-[organization]/billing/store.ts @@ -0,0 +1,15 @@ +import { page } from '$app/stores'; +import type { WizardStepsType } from '$lib/layout/wizard.svelte'; +import type { AggregationList } from '$lib/sdk/billing'; +import { derived, writable } from 'svelte/store'; + +export const aggregationList = derived( + page, + ($page) => $page.data.aggregationList as AggregationList +); + +export const addCreditWizardSteps = writable(new Map()); +export const addCreditWizardStore = writable<{ coupon: string; paymentMethodId: string }>({ + coupon: null, + paymentMethodId: null +}); diff --git a/src/routes/console/organization-[organization]/billing/taxId.svelte b/src/routes/console/organization-[organization]/billing/taxId.svelte new file mode 100644 index 000000000..003012cbb --- /dev/null +++ b/src/routes/console/organization-[organization]/billing/taxId.svelte @@ -0,0 +1,55 @@ + + +
    + + Tax ID + Add a tax identification number to your organization. + + + + + + + + + + +
    diff --git a/src/routes/console/organization-[organization]/billing/wizard/addCredit.svelte b/src/routes/console/organization-[organization]/billing/wizard/addCredit.svelte new file mode 100644 index 000000000..3e4a3707b --- /dev/null +++ b/src/routes/console/organization-[organization]/billing/wizard/addCredit.svelte @@ -0,0 +1,46 @@ + + + + Add credits + + Add Appwrite credits to your organization. A payment method is required before credits can + be applied. + + { + $addCreditWizardStore.coupon = e.detail.code; + }} + let:data> + {data.code} has been successfully added + + diff --git a/src/routes/console/organization-[organization]/billing/wizard/paymentDetails.svelte b/src/routes/console/organization-[organization]/billing/wizard/paymentDetails.svelte new file mode 100644 index 000000000..b4f54264d --- /dev/null +++ b/src/routes/console/organization-[organization]/billing/wizard/paymentDetails.svelte @@ -0,0 +1,57 @@ + + + + Payment details + + Add a payment method to your organization. You will not be charged until you upgrade to a + Pro or Scale plan. + + +

    Payment method

    + + + +
    diff --git a/src/routes/console/organization-[organization]/breadcrumbs.svelte b/src/routes/console/organization-[organization]/breadcrumbs.svelte index 62b3a6f20..e2a847beb 100644 --- a/src/routes/console/organization-[organization]/breadcrumbs.svelte +++ b/src/routes/console/organization-[organization]/breadcrumbs.svelte @@ -4,8 +4,8 @@ $: breadcrumbs = [ { - href: `/console/organization-${$organization.$id}`, - title: $organization.name + href: `/console/organization-${$organization?.$id}`, + title: $organization?.name } ]; diff --git a/src/routes/console/organization-[organization]/createMember.svelte b/src/routes/console/organization-[organization]/createMember.svelte index 669d7fafa..5bd7742ba 100644 --- a/src/routes/console/organization-[organization]/createMember.svelte +++ b/src/routes/console/organization-[organization]/createMember.svelte @@ -1,34 +1,41 @@ + {#if isCloud} + + {#if $organization?.billingPlan === BillingPlan.SCALE} + You can add unlimited organization members on the {plan.name} plan at no cost. + {:else if $organization?.billingPlan === BillingPlan.PRO} + You can add unlimited organization members on the {plan.name} plan for + ${plan.addons.member.price} each per billing period. + {/if} + + {/if} + import { Wizard } from '$lib/layout'; + import { sdk } from '$lib/stores/sdk'; + import { onDestroy } from 'svelte'; + import { addNotification } from '$lib/stores/notifications'; + import Step1 from './wizard/step1.svelte'; + import Step2 from './wizard/step2.svelte'; + import type { WizardStepsType } from '$lib/layout/wizard.svelte'; + import { goto, invalidate } from '$app/navigation'; + import { Dependencies } from '$lib/constants'; + import { page } from '$app/stores'; + import { Submit, trackEvent, trackError } from '$lib/actions/analytics'; + import { ID } from '@appwrite.io/console'; + import { createProject } from './wizard/store'; + import { wizard } from '$lib/stores/wizard'; + + const teamId = $page.params.organization; + + async function onFinish() { + await invalidate(Dependencies.FUNCTIONS); + } + + async function create() { + try { + const project = await sdk.forConsole.projects.create( + $createProject?.id ?? ID.unique(), + $createProject.name, + teamId, + $createProject.region + ); + trackEvent(Submit.ProjectCreate, { + customId: !!$createProject?.id, + teamId, + region: $createProject.region + }); + addNotification({ + type: 'success', + message: `${$createProject.name} has been created` + }); + await goto(`/console/project-${project.$id}`); + wizard.hide(); + } catch (e) { + addNotification({ + type: 'error', + message: e.message + }); + trackError(e, Submit.ProjectCreate); + } + } + + onDestroy(() => { + $createProject = { + id: null, + name: null, + region: 'fra' + }; + }); + + const stepsComponents: WizardStepsType = new Map(); + stepsComponents.set(1, { + label: 'Project details', + component: Step1 + }); + stepsComponents.set(2, { + label: 'Select region', + component: Step2 + }); + + + diff --git a/src/routes/console/organization-[organization]/deleteMember.svelte b/src/routes/console/organization-[organization]/deleteMember.svelte index 7c12dd1d1..5a6cd2687 100644 --- a/src/routes/console/organization-[organization]/deleteMember.svelte +++ b/src/routes/console/organization-[organization]/deleteMember.svelte @@ -1,6 +1,6 @@ - - -

    - Are you sure you want to delete {$organization.name}? All projects ({$organization.total}) - and data associated with this organization will be deleted. This action is irreversible. -

    - - - - -
    diff --git a/src/routes/console/organization-[organization]/excesLimitModal.svelte b/src/routes/console/organization-[organization]/excesLimitModal.svelte new file mode 100644 index 000000000..b3a58ac1c --- /dev/null +++ b/src/routes/console/organization-[organization]/excesLimitModal.svelte @@ -0,0 +1,102 @@ + + + + + Your usage exceeds the {tierToPlan($organization.billingPlan).name} plan limits + + + Appwrite Pro is now available. To facilitate a smooth transition for your projects, Starter plan + will maintain its current state of unlimited resource usage. This extension will be in effect + until January 31st, 2024. + + {#if $organization.billingPlan === BillingPlan.STARTER} +

    + Usage for {$organization.name} organization has reached the limits of the {tierToPlan( + $organization.billingPlan + ).name} plan. Consider upgrading to increase your resource usage. +

    + {:else} +

    + Usage for {$organization.name} organization has reached the limits of the {tierToPlan( + $organization.billingPlan + ).name} plan. Excess usage fees will apply. +

    + {/if} + + + +
    + +
    + + + +
    +
    +
    +
    diff --git a/src/routes/console/organization-[organization]/header.svelte b/src/routes/console/organization-[organization]/header.svelte index a206639f2..23c2d23d8 100644 --- a/src/routes/console/organization-[organization]/header.svelte +++ b/src/routes/console/organization-[organization]/header.svelte @@ -1,10 +1,15 @@ - - - - - - {#each $organizationList.teams as org} - (showDropdown = false)}> - {org.name} - - {/each} - - -
    -
      - newOrgModal.set(true)}> - New organization - -
    -
    -
    -
    -
    - - - - -
    -
    -
    - - {#each tabs as tab} - - {tab.title} - - {/each} - -
    +{#if $organization?.$id} + + + + + + {#each $organizationList.teams as org} + (showDropdown = false)}> + {org.name} + + {/each} + + +
    +
      + + New Organization + +
    +
    +
    +
    +
    + + + +
    + +
    +
    +
    + + {#each tabs as tab} + + {tab.title} + + {/each} + +
    +{/if} diff --git a/src/routes/console/organization-[organization]/members/+page.svelte b/src/routes/console/organization-[organization]/members/+page.svelte index 140a59510..8497dac36 100644 --- a/src/routes/console/organization-[organization]/members/+page.svelte +++ b/src/routes/console/organization-[organization]/members/+page.svelte @@ -1,9 +1,7 @@ + + + {#if upcomingInvoice} +

    + The organization {$organization.name} will be flagged for deletion. +

    + +

    + All existing projects will be paused and the organization will be deleted once your + upcoming invoice is processed on {toLocaleDate($organization.billingNextInvoiceDate)}. +

    + {:else} +

    + Are you sure you want to delete {$organization.name}? All projects ({$projects.total}) + and data associated with this organization will be deleted. This action is irreversible. +

    + {/if} + + + + +
    diff --git a/src/routes/console/organization-[organization]/store.ts b/src/routes/console/organization-[organization]/store.ts new file mode 100644 index 000000000..07b0ca110 --- /dev/null +++ b/src/routes/console/organization-[organization]/store.ts @@ -0,0 +1,6 @@ +import { page } from '$app/stores'; +import type { Models } from '@appwrite.io/console'; +import { derived, writable } from 'svelte/store'; + +export const showExcess = writable(false); +export const projects = derived(page, ($page) => $page.data?.projects as Models.ProjectList); diff --git a/src/routes/console/organization-[organization]/usage/[[invoice]]/+page.svelte b/src/routes/console/organization-[organization]/usage/[[invoice]]/+page.svelte new file mode 100644 index 000000000..475e23ed5 --- /dev/null +++ b/src/routes/console/organization-[organization]/usage/[[invoice]]/+page.svelte @@ -0,0 +1,296 @@ + + + +
    + Usage + + {#if $organization?.billingPlan === BillingPlan.STARTER} + + {/if} +
    +
    + {#if $organization.billingPlan === BillingPlan.SCALE} +

    + On the Scale plan, you'll be charged only for any usage that exceeds the thresholds + per resource listed below. +

    + {:else if $organization.billingPlan === BillingPlan.PRO} +

    + On the Pro plan, you'll be charged only for any usage that exceeds the thresholds + per resource listed below. +

    + {:else if $organization.billingPlan === BillingPlan.STARTER} +

    + If you exceed the limits of the {plan} plan, services for your organization's projects + may be disrupted. + . +

    + {/if} + + +
    + + + Bandwidth + +

    + Calculated for all bandwidth used across all projects in your organization. +

    + + + {#if data.organizationUsage.bandwidth} + {@const current = total(data.organizationUsage.bandwidth)} + {@const currentHumanized = humanFileSize(current)} + {@const max = getServiceLimit('bandwidth', tier)} + + + value + ? `${humanFileSize(+value).value} ${ + humanFileSize(+value).unit + }` + : '0' + } + } + }} + series={[ + { + name: 'Bandwidth', + data: [ + ...data.organizationUsage.bandwidth.map((e) => [e.date, e.value]) + ], + tooltip: { + valueFormatter: (value) => + `${humanFileSize(+value).value} ${humanFileSize(+value).unit}` + } + } + ]} /> + + {:else} + +
    +
    +
    + {/if} +
    +
    + + + Users + +

    The total number of users across all projects in your organization.

    + + + {#if data.organizationUsage.users} + {@const current = data.organizationUsage.usersTotal} + {@const max = getServiceLimit('users', tier)} + + + + {:else} + +
    +
    +
    + {/if} +
    +
    + + + Executions + +

    + Calculated for all functions that are executed in all projects in your organization. +

    + + + {#if data.organizationUsage.executionsTotal} + {@const current = data.organizationUsage.executionsTotal} + {@const max = getServiceLimit('executions', tier)} + + [e.date, e.value]) + ] + } + ]} /> + + {:else} + +
    +
    +
    + {/if} +
    +
    + + + Storage + +

    + Calculated for all your files, deployments, builds and databases. While in beta, only + file storage is counted against your plan limits. +

    + + + {#if data.organizationUsage.storageTotal} + {@const current = data.organizationUsage.storageTotal} + {@const currentHumanized = humanFileSize(current)} + {@const max = getServiceLimit('storage', tier)} + + + {:else} + +
    +
    +
    + {/if} +
    +
    + +

    + Metrics are estimates updated every 24 hours and may not accurately reflect your invoice. +

    +
    diff --git a/src/routes/console/organization-[organization]/usage/[[invoice]]/+page.ts b/src/routes/console/organization-[organization]/usage/[[invoice]]/+page.ts new file mode 100644 index 000000000..b1ef9a272 --- /dev/null +++ b/src/routes/console/organization-[organization]/usage/[[invoice]]/+page.ts @@ -0,0 +1,63 @@ +import { sdk } from '$lib/stores/sdk'; +import { Query } from '@appwrite.io/console'; +import type { PageLoad } from './$types'; +import type { Organization } from '$lib/stores/organization'; +import type { Invoice } from '$lib/sdk/billing'; + +export const load: PageLoad = async ({ params, parent }) => { + const { invoice } = params; + const parentData = await parent(); + const org = parentData.organization as Organization; + + /** + * Temporary fix during migration to billing system + */ + if (org.billingCurrentInvoiceDate === null || org.billingNextInvoiceDate === null) { + return { + organizationUsage: { + bandwidth: null, + users: null, + usersTotal: null, + storageTotal: null, + executions: null, + executionsTotal: null, + projects: null + } + }; + } + + let startDate: string = org.billingCurrentInvoiceDate; + let endDate: string = org.billingNextInvoiceDate; + let currentInvoice: Invoice = undefined; + + if (invoice) { + currentInvoice = await sdk.forConsole.billing.getInvoice(org.$id, invoice); + startDate = currentInvoice.from; + endDate = currentInvoice.to; + } + + const [invoices, usage] = await Promise.all([ + sdk.forConsole.billing.listInvoices(org.$id, [Query.orderDesc('from')]), + sdk.forConsole.billing.listUsage(params.organization, startDate, endDate) + ]); + + const queries: string[] = []; + + if (usage?.projects?.length > 0) { + queries.push( + Query.equal( + '$id', + usage.projects.map((p) => p.projectId) + ) + ); + } + + const projectNames = await sdk.forConsole.projects.list(queries); + + return { + organizationUsage: usage, + projectNames: projectNames.projects, + invoices, + currentInvoice + }; +}; diff --git a/src/routes/console/organization-[organization]/usage/[[invoice]]/ProjectBreakdown.svelte b/src/routes/console/organization-[organization]/usage/[[invoice]]/ProjectBreakdown.svelte new file mode 100644 index 000000000..456559272 --- /dev/null +++ b/src/routes/console/organization-[organization]/usage/[[invoice]]/ProjectBreakdown.svelte @@ -0,0 +1,81 @@ + + + + + Project breakdown + + + Project + Usage + + + + {#each groupByProject(metric).sort((a, b) => b.usage - a.usage) as project} + + + {getProjectName(project.projectId)} + + {format(project.usage)} + + View project usage + + + {/each} + + + + diff --git a/src/routes/console/organization-[organization]/wizard/step1.svelte b/src/routes/console/organization-[organization]/wizard/step1.svelte new file mode 100644 index 000000000..70bbc0050 --- /dev/null +++ b/src/routes/console/organization-[organization]/wizard/step1.svelte @@ -0,0 +1,37 @@ + + + + Project Details + + + + {#if !showCustomId} +
    + (showCustomId = !showCustomId)}> + +
    + {:else} + + {/if} +
    +
    diff --git a/src/routes/console/organization-[organization]/wizard/step2.svelte b/src/routes/console/organization-[organization]/wizard/step2.svelte new file mode 100644 index 000000000..daffe98a4 --- /dev/null +++ b/src/routes/console/organization-[organization]/wizard/step2.svelte @@ -0,0 +1,127 @@ + + + + Select region + + Choose a deployment region for your project. This region cannot be changed. + + {#if regions?.total} +
      + {#each regions.regions.filter((r) => r.$id !== 'default') as region} +
    • + +
      + {#if region.disabled} + +

      {region.name}

      + {#if !notifications.includes(region.$id)} + { + notifyRegion(region); + }}> + + {:else} + { + unNotifyRegion(region); + }}> + + {/if} + {:else} + + + {region.name} + {/if} +
      +
      +
    • + {/each} +
    + {/if} +
    diff --git a/src/routes/console/organization-[organization]/wizard/store.ts b/src/routes/console/organization-[organization]/wizard/store.ts new file mode 100644 index 000000000..d79bd1ded --- /dev/null +++ b/src/routes/console/organization-[organization]/wizard/store.ts @@ -0,0 +1,11 @@ +import { writable } from 'svelte/store'; + +export const createProject = writable<{ + id?: string; + name: string; + region: string; +}>({ + id: null, + name: null, + region: 'fra' +}); diff --git a/src/routes/console/project-[project]/+layout.ts b/src/routes/console/project-[project]/+layout.ts index ab513b583..98096bd90 100644 --- a/src/routes/console/project-[project]/+layout.ts +++ b/src/routes/console/project-[project]/+layout.ts @@ -3,16 +3,23 @@ import { sdk } from '$lib/stores/sdk'; import { error } from '@sveltejs/kit'; import type { LayoutLoad } from './$types'; import { preferences } from '$lib/stores/preferences'; +import { failedInvoice } from '$lib/stores/billing'; +import { isCloud } from '$lib/system'; export const load: LayoutLoad = async ({ params, depends }) => { depends(Dependencies.PROJECT); try { const project = await sdk.forConsole.projects.get(params.project); - localStorage.setItem('project', project.$id); - localStorage.setItem('organization', project.teamId); + const prefs = await sdk.forConsole.account.getPrefs(); + const newPrefs = { ...prefs, organization: project.teamId }; + sdk.forConsole.account.updatePrefs(newPrefs); preferences.loadTeamPrefs(project.teamId); + if (isCloud) { + await failedInvoice.load(project.teamId); + } + return { project, organization: await sdk.forConsole.teams.get(project.teamId) diff --git a/src/routes/console/project-[project]/auth/+layout.svelte b/src/routes/console/project-[project]/auth/+layout.svelte index 69c53375a..cfb6a198b 100644 --- a/src/routes/console/project-[project]/auth/+layout.svelte +++ b/src/routes/console/project-[project]/auth/+layout.svelte @@ -2,6 +2,8 @@ import { goto } from '$app/navigation'; import { page } from '$app/stores'; import { registerCommands, updateCommandGroupRanks } from '$lib/commandCenter'; + import { readOnly } from '$lib/stores/billing'; + import { GRACE_PERIOD_OVERRIDE } from '$lib/system'; import { project } from '../store'; import { showCreateUser } from './+page.svelte'; import { showCreateTeam } from './teams/+page.svelte'; @@ -16,10 +18,10 @@ showCreateUser.set(true); }, keys: $page.url.pathname.endsWith('auth') ? ['c'] : ['c', 'u'], - group: 'users', icon: 'plus', - rank: $page.url.pathname.endsWith('auth') ? 10 : 0 + rank: $page.url.pathname.endsWith('auth') ? 10 : 0, + disabled: $readOnly && !GRACE_PERIOD_OVERRIDE }, { label: 'Create team', @@ -33,7 +35,8 @@ group: 'teams', icon: 'plus', - rank: $page.url.pathname.endsWith('teams') ? 10 : 0 + rank: $page.url.pathname.endsWith('teams') ? 10 : 0, + disabled: $readOnly && !GRACE_PERIOD_OVERRIDE }, { label: 'Go to teams', diff --git a/src/routes/console/project-[project]/auth/+page.svelte b/src/routes/console/project-[project]/auth/+page.svelte index cf868562e..209c3d37d 100644 --- a/src/routes/console/project-[project]/auth/+page.svelte +++ b/src/routes/console/project-[project]/auth/+page.svelte @@ -26,11 +26,12 @@ TableRowLink } from '$lib/elements/table'; import { toLocaleDate, toLocaleDateTime } from '$lib/helpers/date'; - import { Container } from '$lib/layout'; + import { Container, ContainerHeader } from '$lib/layout'; import type { Models } from '@appwrite.io/console'; import { writable } from 'svelte/store'; import type { PageData } from './$types'; import Create from './createUser.svelte'; + import { tooltip } from '$lib/actions/tooltip'; export let data: PageData; @@ -41,11 +42,22 @@ - - - + + +
    + +
    +
    {#if data.users.total} @@ -91,10 +103,10 @@ {user.emailVerification && user.phoneVerification ? 'verified' : user.emailVerification - ? 'verified email' - : user.phoneVerification - ? 'verified phone' - : 'unverified'} + ? 'verified email' + : user.phoneVerification + ? 'verified phone' + : 'unverified'} {:else} blocked diff --git a/src/routes/console/project-[project]/auth/settings/+page.svelte b/src/routes/console/project-[project]/auth/settings/+page.svelte index afacc54eb..fea2bad07 100644 --- a/src/routes/console/project-[project]/auth/settings/+page.svelte +++ b/src/routes/console/project-[project]/auth/settings/+page.svelte @@ -47,7 +47,7 @@ {#if $authMethods && $OAuthProviders} - Auth Methods + Auth methods

    Enable the authentication methods you wish to use.

    diff --git a/src/routes/console/project-[project]/auth/store.ts b/src/routes/console/project-[project]/auth/store.ts new file mode 100644 index 000000000..ae7e544db --- /dev/null +++ b/src/routes/console/project-[project]/auth/store.ts @@ -0,0 +1,8 @@ +import { page } from '$app/stores'; +import type { Models } from '@appwrite.io/console'; +import { derived } from 'svelte/store'; + +export const userList = derived( + page, + ($page) => $page.data.users as unknown as Models.UserList> +); diff --git a/src/routes/console/project-[project]/auth/teams/+page.svelte b/src/routes/console/project-[project]/auth/teams/+page.svelte index ba925b078..5aa93c321 100644 --- a/src/routes/console/project-[project]/auth/teams/+page.svelte +++ b/src/routes/console/project-[project]/auth/teams/+page.svelte @@ -24,11 +24,14 @@ import Create from '../createTeam.svelte'; import { goto } from '$app/navigation'; import { toLocaleDateTime } from '$lib/helpers/date'; - import { Container } from '$lib/layout'; + import { Container, ContainerHeader } from '$lib/layout'; import { base } from '$app/paths'; import type { Models } from '@appwrite.io/console'; import type { PageData } from './$types'; + import { tooltip } from '$lib/actions/tooltip'; import { writable } from 'svelte/store'; + import { readOnly } from '$lib/stores/billing'; + import { isCloud } from '$lib/system'; export let data: PageData; @@ -39,11 +42,29 @@ - - - + + +
    + +
    +
    +
    + {#if data.teams.total}
    @@ -51,7 +72,7 @@ Members Created - + {#each data.teams.teams as team} diff --git a/src/routes/console/project-[project]/auth/teams/team-[team]/createMembership.svelte b/src/routes/console/project-[project]/auth/teams/team-[team]/createMembership.svelte index 295910ba3..4d4fab614 100644 --- a/src/routes/console/project-[project]/auth/teams/team-[team]/createMembership.svelte +++ b/src/routes/console/project-[project]/auth/teams/team-[team]/createMembership.svelte @@ -22,10 +22,10 @@ const user = await sdk.forProject.teams.createMembership( teamId, roles, - url, email || undefined, undefined, undefined, + url, name || undefined ); addNotification({ diff --git a/src/routes/console/project-[project]/auth/teams/team-[team]/updatePrefs.svelte b/src/routes/console/project-[project]/auth/teams/team-[team]/updatePrefs.svelte index 1d9291ed2..d5691d488 100644 --- a/src/routes/console/project-[project]/auth/teams/team-[team]/updatePrefs.svelte +++ b/src/routes/console/project-[project]/auth/teams/team-[team]/updatePrefs.svelte @@ -56,7 +56,7 @@ - Team Preferences + Team preferences

    You can update your team's preferences by storing shared information on the teams's objects so they can easily be shared across members. diff --git a/src/routes/console/project-[project]/auth/templates/+page.svelte b/src/routes/console/project-[project]/auth/templates/+page.svelte index d72167797..6d686d883 100644 --- a/src/routes/console/project-[project]/auth/templates/+page.svelte +++ b/src/routes/console/project-[project]/auth/templates/+page.svelte @@ -40,6 +40,10 @@ // import { baseEmailTemplate, baseSmsTemplate, emailTemplate, smsTemplate } from './store'; import { baseEmailTemplate, emailTemplate } from './store'; import { Button } from '$lib/elements/forms'; + import { organization } from '$lib/stores/organization'; + import ChangeOrganizationTierCloud from '$routes/console/changeOrganizationTierCloud.svelte'; + import { wizard } from '$lib/stores/wizard'; + import { BillingPlan } from '$lib/constants'; const projectId = $page.params.project; @@ -114,6 +118,18 @@

    + {#if $organization.billingPlan === BillingPlan.STARTER} + wizard.start(ChangeOrganizationTierCloud) + } + ]}> + All emails sent using the Starter plan will include attribution to Appwrite in + the signature. To send attribution-free emails, upgrade your plan. + + {/if} - +
    Template language diff --git a/src/routes/console/project-[project]/auth/usage/[[period]]/+page.svelte b/src/routes/console/project-[project]/auth/usage/[[period]]/+page.svelte index 879419d72..c8ffc9c54 100644 --- a/src/routes/console/project-[project]/auth/usage/[[period]]/+page.svelte +++ b/src/routes/console/project-[project]/auth/usage/[[period]]/+page.svelte @@ -4,39 +4,16 @@ import type { PageData } from './$types'; export let data: PageData; - - $: count = data.count; - $: created = data.created; - $: read = data.read; - $: updated = data.updated; - $: deleted = data.deleted; + $: total = data.usersTotal; + $: count = data.users; + {total} + {count} /> diff --git a/src/routes/console/project-[project]/auth/usage/[[period]]/+page.ts b/src/routes/console/project-[project]/auth/usage/[[period]]/+page.ts index 6ba6fec31..977d7e7b3 100644 --- a/src/routes/console/project-[project]/auth/usage/[[period]]/+page.ts +++ b/src/routes/console/project-[project]/auth/usage/[[period]]/+page.ts @@ -1,4 +1,4 @@ -import type { Models } from '@appwrite.io/console'; +import type { Metric, UsageUsers } from '$lib/sdk/usage'; import { sdk } from '$lib/stores/sdk'; import type { PageLoad } from './$types'; import { error } from '@sveltejs/kit'; @@ -6,13 +6,12 @@ import { error } from '@sveltejs/kit'; export const load: PageLoad = async ({ params }) => { const { period } = params; try { - const response = await sdk.forProject.users.getUsage(period ?? '30d'); + const response = (await sdk.forProject.users.getUsage( + period ?? '30d' + )) as unknown as UsageUsers; return { - count: response.usersCount as unknown as Models.Metric[], - created: response.usersCreate as unknown as Models.Metric[], - read: response.usersRead as unknown as Models.Metric[], - updated: response.usersUpdate as unknown as Models.Metric[], - deleted: response.usersDelete as unknown as Models.Metric[] + usersTotal: response.usersTotal, + users: response.users as Metric[] }; } catch (e) { throw error(e.code, e.message); diff --git a/src/routes/console/project-[project]/auth/user-[user]/activity/+page.svelte b/src/routes/console/project-[project]/auth/user-[user]/activity/+page.svelte index 4870c8b9b..985496c75 100644 --- a/src/routes/console/project-[project]/auth/user-[user]/activity/+page.svelte +++ b/src/routes/console/project-[project]/auth/user-[user]/activity/+page.svelte @@ -5,4 +5,4 @@ export let data: PageData; - + diff --git a/src/routes/console/project-[project]/auth/user-[user]/deleteUser.svelte b/src/routes/console/project-[project]/auth/user-[user]/deleteUser.svelte index 9b3148270..fd769a16a 100644 --- a/src/routes/console/project-[project]/auth/user-[user]/deleteUser.svelte +++ b/src/routes/console/project-[project]/auth/user-[user]/deleteUser.svelte @@ -11,7 +11,7 @@ import { Submit, trackEvent, trackError } from '$lib/actions/analytics'; export let showDelete = false; - + let error: string; const deleteUser = async () => { try { await sdk.forProject.users.delete($user.$id); @@ -22,12 +22,9 @@ }); trackEvent(Submit.UserDelete); await goto(`${base}/console/project-${$page.params.project}/auth`); - } catch (error) { - addNotification({ - type: 'error', - message: error.message - }); - trackError(error, Submit.UserDelete); + } catch (e) { + error = e.message; + trackError(e, Submit.UserDelete); } }; @@ -38,7 +35,8 @@ onSubmit={deleteUser} icon="exclamation" state="warning" - headerDivider={false}> + headerDivider={false} + bind:error>

    Are you sure you want to delete {$user.name} from '{$project.name}'?

    diff --git a/src/routes/console/project-[project]/auth/user-[user]/sessions/+page.svelte b/src/routes/console/project-[project]/auth/user-[user]/sessions/+page.svelte index 793bd36a8..d7fc7a181 100644 --- a/src/routes/console/project-[project]/auth/user-[user]/sessions/+page.svelte +++ b/src/routes/console/project-[project]/auth/user-[user]/sessions/+page.svelte @@ -11,7 +11,7 @@ TableHeader, TableRow } from '$lib/elements/table'; - import { Container } from '$lib/layout'; + import { Container, ContainerHeader } from '$lib/layout'; import { sdk } from '$lib/stores/sdk'; import DeleteAllSessions from '../deleteAllSessions.svelte'; import DeleteSessions from '../deleteSession.svelte'; @@ -28,12 +28,14 @@ - {#if data.sessions.total} -
    + + {#if data.sessions.total} -
    + {/if} + + {#if data.sessions.total}
    Browser and device diff --git a/src/routes/console/project-[project]/auth/user-[user]/updateStatus.svelte b/src/routes/console/project-[project]/auth/user-[user]/updateStatus.svelte index 6c155ae4e..c0790da99 100644 --- a/src/routes/console/project-[project]/auth/user-[user]/updateStatus.svelte +++ b/src/routes/console/project-[project]/auth/user-[user]/updateStatus.svelte @@ -112,18 +112,18 @@ {$user.emailVerification && $user.phoneVerification ? 'verified' : $user.emailVerification - ? 'verified email' - : $user.phoneVerification - ? 'verified phone' - : 'unverified'} + ? 'verified email' + : $user.phoneVerification + ? 'verified phone' + : 'unverified'} {:else} {$user.emailVerification ? 'verified ' : $user.phoneVerification - ? 'verified ' - : 'unverified'} + ? 'verified ' + : 'unverified'} {/if} diff --git a/src/routes/console/project-[project]/databases/+page.svelte b/src/routes/console/project-[project]/databases/+page.svelte index b3c623013..e70630db2 100644 --- a/src/routes/console/project-[project]/databases/+page.svelte +++ b/src/routes/console/project-[project]/databases/+page.svelte @@ -2,9 +2,9 @@ import { goto } from '$app/navigation'; import { base } from '$app/paths'; import { page } from '$app/stores'; - import { Empty, PaginationWithLimit } from '$lib/components'; + import { Empty, PaginationWithLimit, ViewSelector } from '$lib/components'; import { Button } from '$lib/elements/forms'; - import { Container, GridHeader } from '$lib/layout'; + import { Container, ContainerHeader } from '$lib/layout'; import type { Models } from '@appwrite.io/console'; import type { PageData } from './$types'; @@ -13,10 +13,12 @@ import { columns } from './store'; import Table from './table.svelte'; import { registerCommands } from '$lib/commandCenter'; + import { tooltip } from '$lib/actions/tooltip'; export let data: PageData; let showCreate = false; + let isCreationDisabled = false; const project = $page.params.project; async function handleCreate(event: CustomEvent) { @@ -31,7 +33,7 @@ showCreate = true; }, keys: ['c'], - disabled: showCreate, + disabled: showCreate || isCreationDisabled, icon: 'plus', group: 'databases', rank: 10 @@ -40,17 +42,35 @@ - - - + total={data?.databases?.total} + on:data={(data) => { + isCreationDisabled = data.detail.isButtonDisabled; + }}> + +
    + +
    + +
    +
    +
    + {#if data.databases.total} {#if data.view === 'grid'} diff --git a/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/document-[document]/+page.svelte b/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/document-[document]/+page.svelte index 738d87c96..0ee809bd9 100644 --- a/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/document-[document]/+page.svelte +++ b/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/document-[document]/+page.svelte @@ -68,9 +68,15 @@ Permissions

    - Assign read or write permissions at the collection level or - document level. If collection level permissions are assigned, permissions applied - to individual documents are ignored. + A user requires appropriate permissions at either the collection level or + document level to access a document. If no permissions are configured, no user + can access the document + Learn more about database permissions.

    diff --git a/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/table.svelte b/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/table.svelte index 03b1def2d..a6c334900 100644 --- a/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/table.svelte +++ b/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/table.svelte @@ -158,9 +158,11 @@ - - {document.$id} - + {#key document.$id} + + {document.$id} + + {/key} {#each $columns as column} diff --git a/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/usage/[[period]]/+page.svelte b/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/usage/[[period]]/+page.svelte index b4f9eb530..6634fbb3b 100644 --- a/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/usage/[[period]]/+page.svelte +++ b/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/usage/[[period]]/+page.svelte @@ -4,39 +4,16 @@ import type { PageData } from './$types'; export let data: PageData; - - $: count = data.count; - $: created = data.created; - $: read = data.read; - $: updated = data.updated; - $: deleted = data.deleted; + $: total = data.documentsTotal; + $: count = data.documents; diff --git a/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/usage/[[period]]/+page.ts b/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/usage/[[period]]/+page.ts index b67082b4f..6228080b6 100644 --- a/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/usage/[[period]]/+page.ts +++ b/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/usage/[[period]]/+page.ts @@ -1,19 +1,16 @@ -import type { Models } from '@appwrite.io/console'; +import type { Metric, UsageCollection } from '$lib/sdk/usage'; import { sdk } from '$lib/stores/sdk'; import type { PageLoad } from './$types'; export const load: PageLoad = async ({ params }) => { - const response = await sdk.forProject.databases.getCollectionUsage( + const response = (await sdk.forProject.databases.getCollectionUsage( params.database, params.collection, params.period ?? '30d' - ); + )) as unknown as UsageCollection; return { - count: response.documentsCount as unknown as Models.Metric[], - created: response.documentsCreate as unknown as Models.Metric[], - read: response.documentsRead as unknown as Models.Metric[], - updated: response.documentsUpdate as unknown as Models.Metric[], - deleted: response.documentsDelete as unknown as Models.Metric[] + documentsTotal: response.documentsTotal, + documents: response.documents as Metric[] }; }; diff --git a/src/routes/console/project-[project]/databases/database-[database]/usage/[[period]]/+page.svelte b/src/routes/console/project-[project]/databases/database-[database]/usage/[[period]]/+page.svelte index 869150446..f5486b738 100644 --- a/src/routes/console/project-[project]/databases/database-[database]/usage/[[period]]/+page.svelte +++ b/src/routes/console/project-[project]/databases/database-[database]/usage/[[period]]/+page.svelte @@ -5,38 +5,16 @@ export let data: PageData; - $: count = data.count; - $: created = data.created; - $: read = data.read; - $: updated = data.updated; - $: deleted = data.deleted; + $: total = data.collectionsTotal; + $: count = data.collections; diff --git a/src/routes/console/project-[project]/databases/database-[database]/usage/[[period]]/+page.ts b/src/routes/console/project-[project]/databases/database-[database]/usage/[[period]]/+page.ts index 95b4ff7f2..407173bb8 100644 --- a/src/routes/console/project-[project]/databases/database-[database]/usage/[[period]]/+page.ts +++ b/src/routes/console/project-[project]/databases/database-[database]/usage/[[period]]/+page.ts @@ -1,18 +1,15 @@ -import type { Models } from '@appwrite.io/console'; +import type { Metric, UsageDatabase } from '$lib/sdk/usage'; import { sdk } from '$lib/stores/sdk'; import type { PageLoad } from './$types'; export const load: PageLoad = async ({ params }) => { - const response = await sdk.forProject.databases.getDatabaseUsage( + const response = (await sdk.forProject.databases.getDatabaseUsage( params.database, params.period ?? '30d' - ); + )) as unknown as UsageDatabase; return { - count: response.collectionsCount as unknown as Models.Metric[], - created: response.collectionsCreate as unknown as Models.Metric[], - read: response.collectionsRead as unknown as Models.Metric[], - updated: response.collectionsUpdate as unknown as Models.Metric[], - deleted: response.collectionsDelete as unknown as Models.Metric[] + collectionsTotal: response.collectionsTotal, + collections: response.collections as Metric[] }; }; diff --git a/src/routes/console/project-[project]/databases/grid.svelte b/src/routes/console/project-[project]/databases/grid.svelte index d4066b928..030241ac4 100644 --- a/src/routes/console/project-[project]/databases/grid.svelte +++ b/src/routes/console/project-[project]/databases/grid.svelte @@ -8,7 +8,11 @@ const project = $page.params.project; - (showCreate = true)} event="database"> + (showCreate = true)} + event="database" + service="databases"> {#each data.databases.databases as database} {database.name} diff --git a/src/routes/console/project-[project]/databases/usage/[[period]]/+page.svelte b/src/routes/console/project-[project]/databases/usage/[[period]]/+page.svelte index a4a116618..55b97f174 100644 --- a/src/routes/console/project-[project]/databases/usage/[[period]]/+page.svelte +++ b/src/routes/console/project-[project]/databases/usage/[[period]]/+page.svelte @@ -4,39 +4,16 @@ import type { PageData } from './$types'; export let data: PageData; - - $: count = data.count; - $: created = data.created; - $: read = data.read; - $: updated = data.updated; - $: deleted = data.deleted; + $: total = data.databasesTotal; + $: count = data.databases; diff --git a/src/routes/console/project-[project]/databases/usage/[[period]]/+page.ts b/src/routes/console/project-[project]/databases/usage/[[period]]/+page.ts index 5ebb5ac9f..1c99afacd 100644 --- a/src/routes/console/project-[project]/databases/usage/[[period]]/+page.ts +++ b/src/routes/console/project-[project]/databases/usage/[[period]]/+page.ts @@ -1,4 +1,4 @@ -import type { Models } from '@appwrite.io/console'; +import type { Metric, UsageDatabases } from '$lib/sdk/usage'; import { sdk } from '$lib/stores/sdk'; import type { PageLoad } from './$types'; import { error } from '@sveltejs/kit'; @@ -6,13 +6,12 @@ import { error } from '@sveltejs/kit'; export const load: PageLoad = async ({ params }) => { const { period } = params; try { - const response = await sdk.forProject.databases.getUsage(period ?? '30d'); + const response = (await sdk.forProject.databases.getUsage( + period ?? '30d' + )) as unknown as UsageDatabases; return { - count: response.databasesCount as unknown as Models.Metric[], - created: response.databasesCreate as unknown as Models.Metric[], - read: response.databasesRead as unknown as Models.Metric[], - updated: response.databasesUpdate as unknown as Models.Metric[], - deleted: response.databasesDelete as unknown as Models.Metric[] + databasesTotal: response.databasesTotal, + databases: response.databases as Metric[] }; } catch (e) { throw error(e.code, e.message); diff --git a/src/routes/console/project-[project]/functions/+page.svelte b/src/routes/console/project-[project]/functions/+page.svelte index 55c67f9e9..989f8ebab 100644 --- a/src/routes/console/project-[project]/functions/+page.svelte +++ b/src/routes/console/project-[project]/functions/+page.svelte @@ -1,18 +1,10 @@ -
    - Functions - -
    + {#if data.functions.total} + on:click={openWizard} + service="functions"> {#each data.functions.functions as func} @@ -130,7 +127,7 @@ {:else} {/if} diff --git a/src/routes/console/project-[project]/functions/function-[function]/+page.svelte b/src/routes/console/project-[project]/functions/function-[function]/+page.svelte index 2209e2ba2..1462e407d 100644 --- a/src/routes/console/project-[project]/functions/function-[function]/+page.svelte +++ b/src/routes/console/project-[project]/functions/function-[function]/+page.svelte @@ -26,7 +26,7 @@ TableScroll } from '$lib/elements/table'; import { deploymentList, execute, func, proxyRuleList } from './store'; - import { Container } from '$lib/layout'; + import { Container, ContainerHeader } from '$lib/layout'; import { app } from '$lib/stores/app'; import { calculateSize, humanFileSize } from '$lib/helpers/sizeConvertion'; import type { Models } from '@appwrite.io/console'; @@ -39,6 +39,8 @@ import DeploymentSource from './deploymentSource.svelte'; import DeploymentCreatedBy from './deploymentCreatedBy.svelte'; import DeploymentDomains from './deploymentDomains.svelte'; + import { GRACE_PERIOD_OVERRIDE, isCloud } from '$lib/system'; + import { readOnly } from '$lib/stores/billing'; export let data; @@ -56,10 +58,9 @@ -
    - Deployments + -
    +
    {#if $deploymentList?.total} {@const activeDeployment = data.activeDeployment}
    @@ -148,10 +149,34 @@ Redeploy - +
    + {:else if $deploymentList.total} + + + + +
    +

    + Add a new deployment, or activate an existing one to see your function in + action.
    Learn more about deployments in our + documentation. +

    +
    +
    {:else}
    diff --git a/src/routes/console/project-[project]/functions/function-[function]/create.svelte b/src/routes/console/project-[project]/functions/function-[function]/create.svelte index 14d3d0219..507352e0f 100644 --- a/src/routes/console/project-[project]/functions/function-[function]/create.svelte +++ b/src/routes/console/project-[project]/functions/function-[function]/create.svelte @@ -8,6 +8,7 @@ import { showCreateDeployment } from './store'; export let secondary = false; + export let round = false; // This allows us to know which one to open when the user uses the shortcut in the command center export let main = false; let show = false; @@ -23,11 +24,13 @@ - import { invalidate } from '$app/navigation'; - import { Alert, EmptySearch, Heading, Id, PaginationWithLimit } from '$lib/components'; - import { Dependencies } from '$lib/constants'; + import { Alert, EmptySearch, Id, PaginationWithLimit } from '$lib/components'; + import { BillingPlan, Dependencies } from '$lib/constants'; import { Pill } from '$lib/elements'; import { Button } from '$lib/elements/forms'; import { @@ -15,18 +15,20 @@ } from '$lib/elements/table'; import { timeFromNow } from '$lib/helpers/date'; import { calculateTime } from '$lib/helpers/timeConversion'; - import { Container } from '$lib/layout'; + import { Container, ContainerHeader } from '$lib/layout'; import { log } from '$lib/stores/logs'; import { sdk } from '$lib/stores/sdk'; import { onMount } from 'svelte'; import { func } from '../store'; import type { Models } from '@appwrite.io/console'; - import type { PageData } from './$types'; + import { organization } from '$lib/stores/organization'; + import { getServiceLimit, showUsageRatesModal } from '$lib/stores/billing'; import { project } from '$routes/console/project-[project]/store'; import Create from '../create.svelte'; import Execute from '../execute.svelte'; + import { abbreviateNumber } from '$lib/helpers/numbers'; - export let data: PageData; + export let data; let selectedFunction: Models.Function = null; @@ -43,16 +45,45 @@ $log.func = $func; $log.data = execution; } + + const logs = getServiceLimit('logs'); -
    - Executions + (selectedFunction = $func)}> + +

    The {tier} plan has limits

    +
      +
    • + {abbreviateNumber(limit)} function executions +
    • +
    • + {logs} hour of logs +
    • +
    + {#if $organization?.billingPlan === BillingPlan.STARTER} +

    + + to increase your resource limits. +

    + {:else} +

    + After this amount, . +

    + {/if} +
    +
    - -
    {#if !$func.logging}
    @@ -139,4 +170,6 @@ {/if} + + diff --git a/src/routes/console/project-[project]/functions/function-[function]/settings/updatePermissions.svelte b/src/routes/console/project-[project]/functions/function-[function]/settings/updatePermissions.svelte index 2a3950081..949a5f9d5 100644 --- a/src/routes/console/project-[project]/functions/function-[function]/settings/updatePermissions.svelte +++ b/src/routes/console/project-[project]/functions/function-[function]/settings/updatePermissions.svelte @@ -65,7 +65,7 @@ - Execute Access + Execute access

    Choose who can execute this function using the client API. Learn more about import { Container } from '$lib/layout'; import { Card, SecondaryTabsItem, SecondaryTabs, Heading } from '$lib/components'; - import { total } from '$lib/layout/usage.svelte'; import { BarChart } from '$lib/charts'; import { page } from '$app/stores'; import type { PageData } from './$types'; + import { formatNumberWithCommas } from '$lib/helpers/numbers'; export let data: PageData; - - $: count = data.count; - $: errors = data.errors; + $: total = data.executionsTotal; + $: count = data.executions; @@ -35,7 +34,7 @@

    {#if count} - {total(count)} + {formatNumberWithCommas(total)}

    Executions

    {/if} - {#if errors} - - {total(errors)} -

    Errors

    -
    - [e.date, e.value])] - } - ]} /> - - {/if} diff --git a/src/routes/console/project-[project]/functions/function-[function]/usage/[[period]]/+page.ts b/src/routes/console/project-[project]/functions/function-[function]/usage/[[period]]/+page.ts index e7391906f..dfeafeb47 100644 --- a/src/routes/console/project-[project]/functions/function-[function]/usage/[[period]]/+page.ts +++ b/src/routes/console/project-[project]/functions/function-[function]/usage/[[period]]/+page.ts @@ -1,18 +1,18 @@ -import type { Models } from '@appwrite.io/console'; +import type { Metric, UsageFunctions } from '$lib/sdk/usage'; import { sdk } from '$lib/stores/sdk'; import type { PageLoad } from './$types'; import { error } from '@sveltejs/kit'; export const load: PageLoad = async ({ params }) => { try { - const response = await sdk.forProject.functions.getFunctionUsage( + const response = (await sdk.forProject.functions.getFunctionUsage( params.function, params.period ?? '30d' - ); + )) as unknown as UsageFunctions; return { - count: response.executionsTotal as unknown as Models.Metric[], - errors: response.executionsFailure as unknown as Models.Metric[] + executionsTotal: response.executionsTotal, + executions: response.executions as Metric[] }; } catch (e) { throw error(e.code, e.message); diff --git a/src/routes/console/project-[project]/functions/store.ts b/src/routes/console/project-[project]/functions/store.ts index 6f4824186..3acf62136 100644 --- a/src/routes/console/project-[project]/functions/store.ts +++ b/src/routes/console/project-[project]/functions/store.ts @@ -15,3 +15,5 @@ export const baseRuntimesList = derived(runtimesList, async ($runtimesList) => { } return { runtimes: [...baseRuntimes.values()] }; }); + +export const functionsList = derived(page, ($page) => $page.data.functions as Models.FunctionList); diff --git a/src/routes/console/project-[project]/functions/templates/+page.svelte b/src/routes/console/project-[project]/functions/templates/+page.svelte index 110cb04fb..c1a0ba1f6 100644 --- a/src/routes/console/project-[project]/functions/templates/+page.svelte +++ b/src/routes/console/project-[project]/functions/templates/+page.svelte @@ -12,10 +12,13 @@ SvgIcon } from '$lib/components'; import { Button, InputSearch } from '$lib/elements/forms'; - import { Container } from '$lib/layout'; + import { Container, ContainerButton } from '$lib/layout'; import { app } from '$lib/stores/app'; + import { isServiceLimited } from '$lib/stores/billing'; import type { Runtime } from '$lib/stores/marketplace.js'; + import { organization } from '$lib/stores/organization'; import { connectTemplate } from '$lib/wizards/functions/cover.svelte'; + import { functionsList } from '../store'; export let data; @@ -83,6 +86,12 @@ target.searchParams.delete('page'); goto(target.toString(), { keepFocus: true }); } + + $: buttonDisabled = isServiceLimited( + 'functions', + $organization?.billingPlan, + $functionsList?.total ?? 0 + ); @@ -218,9 +227,14 @@ View details - + connectTemplate(template)} + showIcon={false} + buttonText="Create function" + buttonEvent="create_function" />
    diff --git a/src/routes/console/project-[project]/functions/templates/+page.ts b/src/routes/console/project-[project]/functions/templates/+page.ts index b4ae67288..3ce6a8184 100644 --- a/src/routes/console/project-[project]/functions/templates/+page.ts +++ b/src/routes/console/project-[project]/functions/templates/+page.ts @@ -1,9 +1,12 @@ -import { CARD_LIMIT } from '$lib/constants'; +import { CARD_LIMIT, Dependencies } from '$lib/constants'; import { getPage, getSearch, getView, pageToOffset, View } from '$lib/helpers/load'; import { marketplace } from '$lib/stores/marketplace'; +import { sdk } from '$lib/stores/sdk'; import type { PageLoad } from './$types'; -export const load: PageLoad = async ({ url, route }) => { +export const load: PageLoad = async ({ url, route, depends }) => { + depends(Dependencies.FUNCTIONS); + const limit = CARD_LIMIT; const page = getPage(url); const search = getSearch(url); @@ -52,6 +55,7 @@ export const load: PageLoad = async ({ url, route }) => { runtimes, useCases, sum: templates.length, - templates: templates.splice(((page === 0 ? 1 : page) - 1) * limit, limit) + templates: templates.splice(((page === 0 ? 1 : page) - 1) * limit, limit), + functions: await sdk.forProject.functions.list() }; }; diff --git a/src/routes/console/project-[project]/functions/templates/template-[template]/+page.svelte b/src/routes/console/project-[project]/functions/templates/template-[template]/+page.svelte index 15e43c994..fc6e5ec74 100644 --- a/src/routes/console/project-[project]/functions/templates/template-[template]/+page.svelte +++ b/src/routes/console/project-[project]/functions/templates/template-[template]/+page.svelte @@ -2,7 +2,7 @@ import { Alert, Card, Collapsible, Heading } from '$lib/components'; import { Pill } from '$lib/elements'; import { Button } from '$lib/elements/forms'; - import { Container } from '$lib/layout'; + import { Container, ContainerButton } from '$lib/layout'; import { isSelfHosted } from '$lib/system'; import AppwriteLogoDark from '$lib/images/appwrite-logo-dark.svg'; import AppwriteLogoLight from '$lib/images/appwrite-logo-light.svg'; @@ -10,8 +10,17 @@ import { consoleVariables } from '$routes/console/store'; import { template } from './store'; import { app } from '$lib/stores/app'; + import { isServiceLimited } from '$lib/stores/billing'; + import { organization } from '$lib/stores/organization'; + import { functionsList } from '../../store'; const isVcsEnabled = $consoleVariables?._APP_VCS_ENABLED === true; + + $: buttonDisabled = isServiceLimited( + 'functions', + $organization?.billingPlan, + $functionsList?.total + ); @@ -90,11 +99,13 @@ View source - + connectTemplate($template)} + showIcon={false} + buttonText="Create function" + buttonEvent="create_function" />
    diff --git a/src/routes/console/project-[project]/functions/templates/template-[template]/+page.ts b/src/routes/console/project-[project]/functions/templates/template-[template]/+page.ts index 7936cc751..0c7a6dec4 100644 --- a/src/routes/console/project-[project]/functions/templates/template-[template]/+page.ts +++ b/src/routes/console/project-[project]/functions/templates/template-[template]/+page.ts @@ -1,8 +1,13 @@ +import { Dependencies } from '$lib/constants'; import { marketplace } from '$lib/stores/marketplace'; +import { sdk } from '$lib/stores/sdk'; import type { PageLoad } from './$types'; -export const load: PageLoad = async ({ params }) => { +export const load: PageLoad = async ({ params, depends }) => { + depends(Dependencies.FUNCTIONS); + return { - template: marketplace.find((template) => template.id === params.template) + template: marketplace.find((template) => template.id === params.template), + functions: await sdk.forProject.functions.list() }; }; diff --git a/src/routes/console/project-[project]/functions/wizard/step1.svelte b/src/routes/console/project-[project]/functions/wizard/step1.svelte index 1878c57d6..17408aacb 100644 --- a/src/routes/console/project-[project]/functions/wizard/step1.svelte +++ b/src/routes/console/project-[project]/functions/wizard/step1.svelte @@ -27,6 +27,7 @@ label="Name" id="name" placeholder="Function name" + autofocus bind:value={$createFunction.name} required /> export function totalMetrics(set: Array): number { if (!set) return 0; - return total((set as Models.Metric[]).map((c) => c.value)); + return total((set as Metric[]).map((c) => c.value)); } @@ -14,7 +14,6 @@ import { Heading, Tab } from '$lib/components'; import { humanFileSize } from '$lib/helpers/sizeConvertion'; import { Container, type UsagePeriods } from '$lib/layout'; - import type { Models } from '@appwrite.io/console'; import { onMount } from 'svelte'; import { onboarding, project } from '../store'; import Bandwith from './bandwith.svelte'; @@ -25,6 +24,8 @@ import { usage } from './store'; import { formatNum } from '$lib/helpers/string'; import { total } from '$lib/helpers/array'; + import type { Metric } from '$lib/sdk/usage'; + import { periodToDates } from '$lib/layout/usage.svelte'; $: projectId = $page.params.project; $: path = `/console/project-${projectId}/overview`; @@ -34,7 +35,7 @@ afterNavigate(handle); async function handle() { - const promise = usage.load(period); + const promise = changePeriod(period); if ($usage) { await promise; @@ -43,7 +44,8 @@ function changePeriod(newPeriod: UsagePeriods) { period = newPeriod; - usage.load(period); + const dates = periodToDates(newPeriod); + return usage.load(dates.start, dates.end, dates.period); } $: $registerCommands([ @@ -82,7 +84,7 @@ {:else} {#if $usage} - {@const storage = humanFileSize(totalMetrics($usage.storage) ?? 0)} + {@const storage = humanFileSize($usage.filesStorageTotal ?? 0)}
    @@ -106,14 +108,14 @@
    - {formatNum(totalMetrics($usage.documents) ?? 0)} + {formatNum($usage.documentsTotal ?? 0)}
    Documents
    - Databases: {formatNum(totalMetrics($usage.databases) ?? 0)} + Databases: {formatNum($usage.databasesTotal ?? 0)}
    @@ -141,7 +143,7 @@
    - Buckets: {formatNum(totalMetrics($usage.buckets) ?? 0)} + Buckets: {formatNum($usage.bucketsTotal ?? 0)}
    @@ -161,7 +163,7 @@
    - {formatNum(totalMetrics($usage.users) ?? 0)} + {formatNum($usage.usersTotal ?? 0)}
    Users
    @@ -182,7 +184,7 @@
    - {formatNum(totalMetrics($usage.executions) ?? 0)} + {formatNum($usage.executionsTotal ?? 0)}
    Executions
    diff --git a/src/routes/console/project-[project]/overview/bandwith.svelte b/src/routes/console/project-[project]/overview/bandwith.svelte index 9325101bb..e508e935e 100644 --- a/src/routes/console/project-[project]/overview/bandwith.svelte +++ b/src/routes/console/project-[project]/overview/bandwith.svelte @@ -17,6 +17,7 @@ date: number; value: number; }>; + $: bandwith = humanFileSize(totalMetrics($usage?.network)); $: if (period) { diff --git a/src/routes/console/project-[project]/overview/keys/+page.svelte b/src/routes/console/project-[project]/overview/keys/+page.svelte index ca22e8ce0..8730feae9 100644 --- a/src/routes/console/project-[project]/overview/keys/+page.svelte +++ b/src/routes/console/project-[project]/overview/keys/+page.svelte @@ -24,7 +24,7 @@
    - API Keys + API keys - - addPlatform(Platform.Web)}>Web App - addPlatform(Platform.Flutter)}> - Flutter App - - addPlatform(Platform.Android)}> - Android App - - addPlatform(Platform.Apple)}>Apple App - - - -
    + + + + + addPlatform(Platform.Web)}>Web App + addPlatform(Platform.Flutter)}>Flutter App + addPlatform(Platform.Android)}>Android App + addPlatform(Platform.Apple)}>Apple App + + + {#if data.platforms.platforms.length}
    addPlatform(Platform.Web)}> Web - Ï + addPlatform(Platform.Flutter)}> Flutter diff --git a/src/routes/console/project-[project]/overview/platforms/[platform]/android.svelte b/src/routes/console/project-[project]/overview/platforms/[platform]/android.svelte index 92b912b4e..0c18d467f 100644 --- a/src/routes/console/project-[project]/overview/platforms/[platform]/android.svelte +++ b/src/routes/console/project-[project]/overview/platforms/[platform]/android.svelte @@ -46,7 +46,7 @@ - Package Name + Package name

    Your package name is generally the applicationId in your app-level build.gradle file.

    diff --git a/src/routes/console/project-[project]/overview/platforms/[platform]/flutterAndroid.svelte b/src/routes/console/project-[project]/overview/platforms/[platform]/flutterAndroid.svelte index fc5793332..c3e30ad26 100644 --- a/src/routes/console/project-[project]/overview/platforms/[platform]/flutterAndroid.svelte +++ b/src/routes/console/project-[project]/overview/platforms/[platform]/flutterAndroid.svelte @@ -46,7 +46,7 @@ - Package Name + Package name

    Your package name is generally the applicationId in your app-level build.gradle file.

    diff --git a/src/routes/console/project-[project]/overview/platforms/[platform]/flutterLinux.svelte b/src/routes/console/project-[project]/overview/platforms/[platform]/flutterLinux.svelte index a6587085c..1f0179b9a 100644 --- a/src/routes/console/project-[project]/overview/platforms/[platform]/flutterLinux.svelte +++ b/src/routes/console/project-[project]/overview/platforms/[platform]/flutterLinux.svelte @@ -46,7 +46,7 @@ - Package Name + Package name

    Your application name.

    diff --git a/src/routes/console/project-[project]/overview/platforms/[platform]/flutterWindows.svelte b/src/routes/console/project-[project]/overview/platforms/[platform]/flutterWindows.svelte index 0c20e127e..90e5a1de6 100644 --- a/src/routes/console/project-[project]/overview/platforms/[platform]/flutterWindows.svelte +++ b/src/routes/console/project-[project]/overview/platforms/[platform]/flutterWindows.svelte @@ -46,7 +46,7 @@ - Package Name + Package name

    Your application name.

    diff --git a/src/routes/console/project-[project]/overview/platforms/wizard/android/step3.svelte b/src/routes/console/project-[project]/overview/platforms/wizard/android/step3.svelte index 01c74f02f..736d87555 100644 --- a/src/routes/console/project-[project]/overview/platforms/wizard/android/step3.svelte +++ b/src/routes/console/project-[project]/overview/platforms/wizard/android/step3.svelte @@ -23,11 +23,14 @@ val client = Client(context) value={project}>Project ID.

    - +
    + +
    diff --git a/src/routes/console/project-[project]/overview/platforms/wizard/flutter/step2.svelte b/src/routes/console/project-[project]/overview/platforms/wizard/flutter/step2.svelte index 2f1c10431..6bd6f9e68 100644 --- a/src/routes/console/project-[project]/overview/platforms/wizard/flutter/step2.svelte +++ b/src/routes/console/project-[project]/overview/platforms/wizard/flutter/step2.svelte @@ -19,5 +19,7 @@

    You can also install the SDK using the Dart package manager from your terminal.

    - +
    + +
    diff --git a/src/routes/console/project-[project]/overview/platforms/wizard/flutter/step3.svelte b/src/routes/console/project-[project]/overview/platforms/wizard/flutter/step3.svelte index 95e585413..cc82830e2 100644 --- a/src/routes/console/project-[project]/overview/platforms/wizard/flutter/step3.svelte +++ b/src/routes/console/project-[project]/overview/platforms/wizard/flutter/step3.svelte @@ -25,7 +25,16 @@ client Initialize your SDK by pointing the client to your Appwrite project using your Project ID

    - +
    + +

    Before sending any API calls to your new Appwrite project, make sure your device or emulator has network access to your Appwrite project's hostname or IP address. diff --git a/src/routes/console/project-[project]/overview/platforms/wizard/web/step3.svelte b/src/routes/console/project-[project]/overview/platforms/wizard/web/step3.svelte index de3a41e49..c259253dd 100644 --- a/src/routes/console/project-[project]/overview/platforms/wizard/web/step3.svelte +++ b/src/routes/console/project-[project]/overview/platforms/wizard/web/step3.svelte @@ -21,5 +21,14 @@ client value={project}>Project ID.

    - +
    + +
    diff --git a/src/routes/console/project-[project]/overview/store.ts b/src/routes/console/project-[project]/overview/store.ts index f33bff720..ea055c522 100644 --- a/src/routes/console/project-[project]/overview/store.ts +++ b/src/routes/console/project-[project]/overview/store.ts @@ -1,17 +1,17 @@ import { sdk } from '$lib/stores/sdk'; import { cachedStore } from '$lib/helpers/cache'; -import type { Models } from '@appwrite.io/console'; import { writable, type Writable } from 'svelte/store'; +import type { Models } from '@appwrite.io/console'; export const usage = cachedStore< Models.UsageProject, { - load: (range: string) => Promise; + load: (start: string, end: string, period: '1h' | '1d') => Promise; } >('projectUsage', function ({ set }) { return { - load: async (range) => { - const usages = await sdk.forProject.project.getUsage(range); + load: async (start, end, period) => { + const usages = await sdk.forProject.project.getUsage(start, end, period); set(usages); } }; diff --git a/src/routes/console/project-[project]/settings/GitDisconnectModal.svelte b/src/routes/console/project-[project]/settings/GitDisconnectModal.svelte index 0e4f978a1..b414f37bd 100644 --- a/src/routes/console/project-[project]/settings/GitDisconnectModal.svelte +++ b/src/routes/console/project-[project]/settings/GitDisconnectModal.svelte @@ -18,7 +18,7 @@ await sdk.forProject.vcs.deleteInstallation(selectedInstallation.$id); await invalidate(Dependencies.PROJECT_INSTALLATIONS); addNotification({ - message: `${selectedInstallation.organization} has been disconnected from your project`, + message: `${selectedInstallation.organization} has been disconnected from this project`, type: 'success' }); trackEvent(Submit.InstallationDelete, { diff --git a/src/routes/console/project-[project]/settings/deleteProject.svelte b/src/routes/console/project-[project]/settings/deleteProject.svelte index 065e9eed8..b4d40ad24 100644 --- a/src/routes/console/project-[project]/settings/deleteProject.svelte +++ b/src/routes/console/project-[project]/settings/deleteProject.svelte @@ -7,11 +7,21 @@ import { toLocaleDateTime } from '$lib/helpers/date'; import { addNotification } from '$lib/stores/notifications'; import { sdk } from '$lib/stores/sdk'; + import { isCloud } from '$lib/system'; + import { onMount } from 'svelte'; import { project } from '../store'; + import type { RegionList } from '$lib/sdk/billing'; let showDelete = false; let name: string = null; + let regions: RegionList; + onMount(async () => { + if (isCloud) { + regions = await sdk.forConsole.billing.listRegions(); + } + }); + const handleDelete = async () => { try { await sdk.forConsole.projects.delete($project.$id); @@ -45,6 +55,10 @@
    {$project.name}
    + {#if isCloud && $project.region && regions?.total} + {@const projectRegion = regions.regions.find((r) => r.$id === $project?.region)} +

    Region: {projectRegion.name}

    + {/if}

    Last update: {toLocaleDateTime($project.$updatedAt)}

    diff --git a/src/routes/console/project-[project]/settings/disableAllServices.svelte b/src/routes/console/project-[project]/settings/disableAllServices.svelte index d051fff4d..4c81f671e 100644 --- a/src/routes/console/project-[project]/settings/disableAllServices.svelte +++ b/src/routes/console/project-[project]/settings/disableAllServices.svelte @@ -13,8 +13,8 @@ bind:show onSubmit={handleDisableAll}>

    - Are you sure you want to disable all services? This will disable API requests to your - project. + Are you sure you want to disable all services? This will disable API requests to this + project for all Client SDKs.

    diff --git a/src/routes/console/project-[project]/settings/header.svelte b/src/routes/console/project-[project]/settings/header.svelte index 5015df978..0a733acd1 100644 --- a/src/routes/console/project-[project]/settings/header.svelte +++ b/src/routes/console/project-[project]/settings/header.svelte @@ -31,6 +31,12 @@ href: `${path}/smtp`, title: 'SMTP', event: 'smtp' + }, + { + href: `${path}/usage`, + title: 'Usage', + event: 'usage', + hasChildren: true } ]; diff --git a/src/routes/console/project-[project]/settings/migrations/+page.svelte b/src/routes/console/project-[project]/settings/migrations/+page.svelte index 7a9863793..2a7877a02 100644 --- a/src/routes/console/project-[project]/settings/migrations/+page.svelte +++ b/src/routes/console/project-[project]/settings/migrations/+page.svelte @@ -15,7 +15,7 @@ import { isSameDay, toLocaleDate } from '$lib/helpers/date'; import { Container } from '$lib/layout'; import { sdk } from '$lib/stores/sdk'; - import { isSelfHosted } from '$lib/system'; + import { GRACE_PERIOD_OVERRIDE, isSelfHosted } from '$lib/system'; import { onMount } from 'svelte'; import { project } from '../../store'; import { openImportWizard } from './(import)'; @@ -23,6 +23,7 @@ import ExportModal from './exportModal.svelte'; import Status from '$lib/components/status.svelte'; import { capitalize } from '$lib/helpers/string'; + import { readOnly } from '$lib/stores/billing'; export let data; let details: string | null = null; @@ -222,7 +223,11 @@
    -
    @@ -251,8 +256,9 @@
    - + diff --git a/src/routes/console/project-[project]/settings/smtp/+page.svelte b/src/routes/console/project-[project]/settings/smtp/+page.svelte index 832f48baa..a0d273781 100644 --- a/src/routes/console/project-[project]/settings/smtp/+page.svelte +++ b/src/routes/console/project-[project]/settings/smtp/+page.svelte @@ -1,5 +1,5 @@ + + +
    + Usage + + {#if $organization?.billingPlan === BillingPlan.STARTER} + + {/if} +
    +
    + {#if $organization.billingPlan === BillingPlan.SCALE} +

    + On the Scale plan, you'll be charged only for any usage that exceeds the thresholds + per resource listed below. +

    + {:else if $organization.billingPlan === BillingPlan.PRO} +

    + On the Pro plan, you'll be charged only for any usage that exceeds the thresholds + per resource listed below. +

    + {:else if $organization.billingPlan === BillingPlan.STARTER} +

    + If you exceed the limits of the {plan} plan, services for your projects may be disrupted. + . +

    + {/if} + + +
    + + Bandwidth +

    Calculated for all bandwidth used in your project.

    + + {#if network} + {@const humanized = humanFileSize(total(network))} +
    + {humanized.value} + {humanized.unit} +
    + + value + ? `${humanFileSize(+value).value} ${ + humanFileSize(+value).unit + }` + : '0' + } + } + }} + series={[ + { + name: 'Bandwidth', + data: [...network.map((e) => [e.date, e.value])], + tooltip: { + valueFormatter: (value) => + `${humanFileSize(+value).value} ${humanFileSize(+value).unit}` + } + } + ]} /> + {:else} + +
    +
    +
    + {/if} +
    +
    + + Users + +

    Total user in your project.

    + + + {#if users} + {@const current = formatNum(usersTotal)} +
    +
    +

    + {current} + Users +

    +
    +
    + [e.date, e.value])] + } + ]} /> + {:else} + +
    +
    +
    + {/if} +
    +
    + + Executions + +

    + Calculated for all functions that are executed in all projects in your project. +

    + + + {#if executions} + {@const current = formatNum(executionsTotal)} +
    +
    +

    + {current} + Executions +

    +
    +
    + [e.date, e.value])] + } + ]} /> + {#if data.usage.executionsBreakdown.length > 0} +
    + + Function + Usage + + + + {#each data.usage.executionsBreakdown as func} + + + {func.name ?? func.resourceId} + + + {formatNum(func.value)} executions + + + View function + + + {/each} + +
    + {/if} + {:else} + +
    +
    +
    + {/if} + + + + Storage + +

    + Calculated for all your files, deployments, builds and databases. While in beta, only + file storage is counted against your plan limits. +

    + + + {#if storage} + {@const humanized = humanFileSize(storage)} +
    +
    +

    + {humanized.value} + {humanized.unit} +

    +
    +
    + {#if data.usage.bucketsBreakdown.length > 0} + + + Bucket + Usage + + + + {#each data.usage.bucketsBreakdown.sort((a, b) => b.value - a.value) as bucket} + {@const humanized = humanFileSize(bucket.value)} + + + {bucket.name ?? bucket.resourceId} + + + {humanized.value}{humanized.unit} + + + View bucket + + + {/each} + +
    + {/if} + {:else} + +
    +
    +
    + {/if} +
    +
    +

    + Metrics are estimates updated every 24 hours and may not accurately reflect your invoice. +

    +
    diff --git a/src/routes/console/project-[project]/settings/usage/[[invoice]]/+page.ts b/src/routes/console/project-[project]/settings/usage/[[invoice]]/+page.ts new file mode 100644 index 000000000..d29b1e799 --- /dev/null +++ b/src/routes/console/project-[project]/settings/usage/[[invoice]]/+page.ts @@ -0,0 +1,51 @@ +import { getSdkForProject, sdk } from '$lib/stores/sdk'; +import { Query } from '@appwrite.io/console'; +import type { PageLoad } from './$types'; +import type { Organization } from '$lib/stores/organization'; +import type { Aggregation, Invoice } from '$lib/sdk/billing'; +import { accumulateUsage } from '$lib/sdk/usage'; + +export const load: PageLoad = async ({ params, parent }) => { + const { invoice, project } = params; + const parentData = await parent(); + const org = parentData.organization as Organization; + + let startDate: string = org.billingCurrentInvoiceDate; + let endDate: string = org.billingNextInvoiceDate; + let currentInvoice: Invoice = undefined; + let currentAggregation: Aggregation = undefined; + + if (invoice) { + currentInvoice = await sdk.forConsole.billing.getInvoice(org.$id, invoice); + currentAggregation = await sdk.forConsole.billing.getAggregation( + org.$id, + currentInvoice.aggregationId + ); + + startDate = currentInvoice.from; + endDate = currentInvoice.to; + } + + const [invoices, usage] = await Promise.all([ + sdk.forConsole.billing.listInvoices(org.$id, [Query.orderDesc('from')]), + /** + * Workaround because project id might not be populated yet. + */ + getSdkForProject(project).project.getUsage(startDate, endDate) + ]); + + if (invoice) { + usage.usersTotal = currentAggregation.usageUsers; + usage.executionsTotal = currentAggregation.usageExecutions; + usage.filesStorageTotal = currentAggregation.usageStorage; + } + + usage.users = accumulateUsage(usage.users, usage.usersTotal); + + return { + usage, + invoices, + currentInvoice, + currentAggregation + }; +}; diff --git a/src/routes/console/project-[project]/settings/webhooks/+page.svelte b/src/routes/console/project-[project]/settings/webhooks/+page.svelte index 24c544917..d20533a1f 100644 --- a/src/routes/console/project-[project]/settings/webhooks/+page.svelte +++ b/src/routes/console/project-[project]/settings/webhooks/+page.svelte @@ -8,7 +8,6 @@ import { base } from '$app/paths'; import { page } from '$app/stores'; import { Empty } from '$lib/components'; - import { Button } from '$lib/elements/forms'; import { Pill } from '$lib/elements'; import { TableBody, @@ -19,11 +18,10 @@ TableHeader, TableScroll } from '$lib/elements/table'; - import { Container } from '$lib/layout'; + import { Container, ContainerHeader } from '$lib/layout'; import { wizard } from '$lib/stores/wizard'; import type { PageData } from './$types'; import Create from './createWebhook.svelte'; - import Heading from '$lib/components/heading.svelte'; import { updateCommandGroupRanks } from '$lib/commandCenter'; export let data: PageData; @@ -42,12 +40,12 @@ -
    - Webhooks - -
    + {#if data.webhooks.total} @@ -56,7 +54,7 @@ POST URL Events - + {#each data.webhooks.webhooks as webhook} diff --git a/src/routes/console/project-[project]/settings/webhooks/[webhook]/regenerate.svelte b/src/routes/console/project-[project]/settings/webhooks/[webhook]/regenerate.svelte index 360a2414d..a57746991 100644 --- a/src/routes/console/project-[project]/settings/webhooks/[webhook]/regenerate.svelte +++ b/src/routes/console/project-[project]/settings/webhooks/[webhook]/regenerate.svelte @@ -35,7 +35,7 @@

    Are you sure you want to generate a new Signature Key? - You will not be able to recover your current key. + You will not be able to recover the current key.

    diff --git a/src/routes/console/project-[project]/settings/webhooks/[webhook]/updateSignature.svelte b/src/routes/console/project-[project]/settings/webhooks/[webhook]/updateSignature.svelte index aefdeba8e..4d2db1e82 100644 --- a/src/routes/console/project-[project]/settings/webhooks/[webhook]/updateSignature.svelte +++ b/src/routes/console/project-[project]/settings/webhooks/[webhook]/updateSignature.svelte @@ -8,7 +8,7 @@ - Signature Key + Signature key
    - + ($showCreateBucket = true)} /> {#if data.buckets.total} ($showCreateBucket = true)}> {#each data.buckets.buckets as bucket} diff --git a/src/routes/console/project-[project]/storage/bucket-[bucket]/+page.svelte b/src/routes/console/project-[project]/storage/bucket-[bucket]/+page.svelte index f8732c02d..d02d6dd5c 100644 --- a/src/routes/console/project-[project]/storage/bucket-[bucket]/+page.svelte +++ b/src/routes/console/project-[project]/storage/bucket-[bucket]/+page.svelte @@ -1,52 +1,51 @@ - - - + + + +
    + +
    +
    +
    + + {#if tier === 'Starter'} +

    + You are limited to {limit} GB of storage on the {tier} plan. + + for addtional storage. +

    + {:else} +

    + You are limited to {limit} GB storage on the {tier} plan. After this amount + + . +

    + {/if} +
    +
    {#if data.files.total} @@ -200,7 +229,7 @@ {:else if data.search}
    - Sorry, we couldn't find ‘{data.search}' + Sorry, we couldn't find '{data.search}'

    There are no files that match your search.

    @@ -222,11 +251,10 @@ single href="https://appwrite.io/docs/products/storage/upload-download" target="file" - on:click={() => ($showCreate = true)} /> + on:click={() => wizard.start(Create)} /> {/if} - {#if selectedFile} - + {/if} diff --git a/src/routes/console/project-[project]/storage/bucket-[bucket]/+page.ts b/src/routes/console/project-[project]/storage/bucket-[bucket]/+page.ts index 203ea2410..13eb6f5fe 100644 --- a/src/routes/console/project-[project]/storage/bucket-[bucket]/+page.ts +++ b/src/routes/console/project-[project]/storage/bucket-[bucket]/+page.ts @@ -3,13 +3,20 @@ import { sdk } from '$lib/stores/sdk'; import { getLimit, getPage, getSearch, pageToOffset } from '$lib/helpers/load'; import { Dependencies, PAGE_LIMIT } from '$lib/constants'; import type { PageLoad } from './$types'; +import { isCloud } from '$lib/system'; +import type { OrganizationUsage } from '$lib/sdk/billing'; -export const load: PageLoad = async ({ params, depends, url, route }) => { +export const load: PageLoad = async ({ params, depends, url, route, parent }) => { + const { organization } = await parent(); depends(Dependencies.FILES); const page = getPage(url); const search = getSearch(url); const limit = getLimit(url, route, PAGE_LIMIT); const offset = pageToOffset(page, limit); + let organizationUsage: OrganizationUsage = null; + if (isCloud && organization?.$id) { + organizationUsage = await sdk.forConsole.billing.listUsage(organization.$id); + } return { offset, @@ -19,6 +26,7 @@ export const load: PageLoad = async ({ params, depends, url, route }) => { params.bucket, [Query.limit(limit), Query.offset(offset), Query.orderDesc('')], search - ) + ), + organizationUsage }; }; diff --git a/src/routes/console/project-[project]/storage/bucket-[bucket]/create-file/create.svelte b/src/routes/console/project-[project]/storage/bucket-[bucket]/create-file/create.svelte new file mode 100644 index 000000000..99c989561 --- /dev/null +++ b/src/routes/console/project-[project]/storage/bucket-[bucket]/create-file/create.svelte @@ -0,0 +1,60 @@ + + + diff --git a/src/routes/console/project-[project]/storage/bucket-[bucket]/create-file/step1.svelte b/src/routes/console/project-[project]/storage/bucket-[bucket]/create-file/step1.svelte new file mode 100644 index 000000000..8453a8ee0 --- /dev/null +++ b/src/routes/console/project-[project]/storage/bucket-[bucket]/create-file/step1.svelte @@ -0,0 +1,77 @@ + + + + Create file + Upload a file to add it to your bucket. + + {#if isCloud} + {@const size = humanFileSize(sizeToBytes(service, 'MB', 1000))} + {@const plan = tierToPlan($organization?.billingPlan)} + +

    + The {plan.name} plan has a maximum upload file size limit of {Math.floor( + parseInt(size.value) + )}{size.unit}. + {#if $organization?.billingPlan === BillingPlan.STARTER} + Upgrade to allow files of a larger size. + {/if} +

    + + {#if $organization?.billingPlan === BillingPlan.STARTER} +
    + +
    + {/if} +
    +
    + {/if} + + +
    + +
    + + {#if !showCustomId} +
    + (showCustomId = !showCustomId)}> + +
    + {:else} +
    + +
    + {/if} +
    +
    + + diff --git a/src/routes/console/project-[project]/storage/bucket-[bucket]/create-file/step2.svelte b/src/routes/console/project-[project]/storage/bucket-[bucket]/create-file/step2.svelte new file mode 100644 index 000000000..6a98039ef --- /dev/null +++ b/src/routes/console/project-[project]/storage/bucket-[bucket]/create-file/step2.svelte @@ -0,0 +1,39 @@ + + + + Update Permissions + + Choose who can access your buckets and files. For more information, check out the + + Permissions Guide + . + + {#if $bucket.fileSecurity} +
    + + File security enabled + Users will be able to access this file if they have been granted + either File or Bucket permissions. + +
    +
    + +
    + {:else} + + File security disabled + If you want to assign file permissions, navigate to Bucket settings and enable file security. + Otherwise, only Bucket permissions will be used. + + {/if} +
    diff --git a/src/routes/console/project-[project]/storage/bucket-[bucket]/create-file/store.ts b/src/routes/console/project-[project]/storage/bucket-[bucket]/create-file/store.ts new file mode 100644 index 000000000..6a6eb9248 --- /dev/null +++ b/src/routes/console/project-[project]/storage/bucket-[bucket]/create-file/store.ts @@ -0,0 +1,24 @@ +import { writable } from 'svelte/store'; + +type CreateFile = { + files: FileList | null; + id: string | null; + permissions: string[]; +}; + +const initialState: CreateFile = { + files: null, + id: null, + permissions: [] +}; + +export const createFile = (function initialize() { + const store = writable({ ...initialState }); + + return { + ...store, + reset() { + store.set({ ...initialState }); + } + }; +})(); diff --git a/src/routes/console/project-[project]/storage/bucket-[bucket]/settings/+page.svelte b/src/routes/console/project-[project]/storage/bucket-[bucket]/settings/+page.svelte index d93111fea..e229e256c 100644 --- a/src/routes/console/project-[project]/storage/bucket-[bucket]/settings/+page.svelte +++ b/src/routes/console/project-[project]/storage/bucket-[bucket]/settings/+page.svelte @@ -61,7 +61,9 @@ import { Button, Form, + FormItem, FormList, + InputChoice, InputSelect, InputSwitch, InputTags, @@ -78,6 +80,8 @@ import Delete from '../deleteBucket.svelte'; import { bucket } from '../store'; import UpdateMaxFileSize from './updateMaxFileSize.svelte'; + import { readOnly } from '$lib/stores/billing'; + import { GRACE_PERIOD_OVERRIDE } from '$lib/system'; let showDelete = false; @@ -229,7 +233,12 @@ - + @@ -243,13 +252,17 @@ id="name" label="Name" placeholder="Enter name" - autocomplete={false} + readonly={$readOnly && !GRACE_PERIOD_OVERRIDE} bind:value={bucketName} /> - @@ -300,7 +313,10 @@

    - @@ -316,54 +332,29 @@

    -
  • - -
  • -
  • - -
  • - -
  • + + + This parameter allows you to configure whether or not the files + inside the bucket should be scanned by the Appwrite Antivirus + scanner. + + @@ -405,7 +396,7 @@
    - File Extensions + Allowed file Extensions

    Allowed file extensions. A maximum of 100 file extensions can be added. Leave blank to allow all file types. @@ -438,7 +429,9 @@ - + diff --git a/src/routes/console/project-[project]/storage/bucket-[bucket]/settings/updateMaxFileSize.svelte b/src/routes/console/project-[project]/storage/bucket-[bucket]/settings/updateMaxFileSize.svelte index 2c6a5be45..501154834 100644 --- a/src/routes/console/project-[project]/storage/bucket-[bucket]/settings/updateMaxFileSize.svelte +++ b/src/routes/console/project-[project]/storage/bucket-[bucket]/settings/updateMaxFileSize.svelte @@ -1,11 +1,19 @@ diff --git a/src/routes/console/project-[project]/storage/bucket-[bucket]/usage/[[period]]/+page.ts b/src/routes/console/project-[project]/storage/bucket-[bucket]/usage/[[period]]/+page.ts index 2cb8294fa..f01198060 100644 --- a/src/routes/console/project-[project]/storage/bucket-[bucket]/usage/[[period]]/+page.ts +++ b/src/routes/console/project-[project]/storage/bucket-[bucket]/usage/[[period]]/+page.ts @@ -1,18 +1,15 @@ import { sdk } from '$lib/stores/sdk'; -import type { Models } from '@appwrite.io/console'; +import type { Metric, UsageBuckets } from '$lib/sdk/usage'; import type { PageLoad } from './$types'; export const load: PageLoad = async ({ params }) => { - const response = await sdk.forProject.storage.getBucketUsage( + const response = (await sdk.forProject.storage.getBucketUsage( params.bucket, params.period ?? '30d' - ); + )) as unknown as UsageBuckets; return { - count: response.filesCount as unknown as Models.Metric[], - created: response.filesCreate as unknown as Models.Metric[], - read: response.filesRead as unknown as Models.Metric[], - updated: response.filesUpdate as unknown as Models.Metric[], - deleted: response.filesDelete as unknown as Models.Metric[] + filesTotal: response.filesTotal, + files: response.files as Metric[] }; }; diff --git a/src/routes/console/project-[project]/storage/usage/[[period]]/+page.svelte b/src/routes/console/project-[project]/storage/usage/[[period]]/+page.svelte index 5ac40adb9..bc084c930 100644 --- a/src/routes/console/project-[project]/storage/usage/[[period]]/+page.svelte +++ b/src/routes/console/project-[project]/storage/usage/[[period]]/+page.svelte @@ -4,39 +4,16 @@ import type { PageData } from './$types'; export let data: PageData; - - $: count = data.count; - $: created = data.created; - $: read = data.read; - $: updated = data.updated; - $: deleted = data.deleted; + $: total = data.bucketsTotal; + $: count = data.buckets; diff --git a/src/routes/console/project-[project]/storage/usage/[[period]]/+page.ts b/src/routes/console/project-[project]/storage/usage/[[period]]/+page.ts index 0cc4a9cca..9c4f23b73 100644 --- a/src/routes/console/project-[project]/storage/usage/[[period]]/+page.ts +++ b/src/routes/console/project-[project]/storage/usage/[[period]]/+page.ts @@ -1,18 +1,17 @@ -import type { Models } from '@appwrite.io/console'; +import type { Metric, UsageStorage } from '$lib/sdk/usage'; import { sdk } from '$lib/stores/sdk'; import type { PageLoad } from './$types'; import { error } from '@sveltejs/kit'; export const load: PageLoad = async ({ params }) => { try { - const response = await sdk.forProject.storage.getUsage(params.period ?? '30d'); + const response = (await sdk.forProject.storage.getUsage( + params.period ?? '30d' + )) as unknown as UsageStorage; return { - count: response.bucketsCount as unknown as Models.Metric[], - created: response.bucketsCreate as unknown as Models.Metric[], - read: response.bucketsRead as unknown as Models.Metric[], - updated: response.bucketsUpdate as unknown as Models.Metric[], - deleted: response.bucketsDelete as unknown as Models.Metric[] + bucketsTotal: response.bucketsTotal, + buckets: response.buckets as Metric[] }; } catch (e) { throw error(e.code, e.message); diff --git a/src/routes/console/project-[project]/store.ts b/src/routes/console/project-[project]/store.ts index 4413c76dd..6af331f1c 100644 --- a/src/routes/console/project-[project]/store.ts +++ b/src/routes/console/project-[project]/store.ts @@ -3,7 +3,10 @@ import type { Models } from '@appwrite.io/console'; import type { BarSeriesOption } from 'echarts/charts'; import { derived, writable } from 'svelte/store'; -export const project = derived(page, ($page) => $page.data.project as Models.Project); +export const project = derived( + page, + ($page) => $page.data.project as Models.Project & { region?: string } +); export const onboarding = derived( project, ($project) => $project?.platforms?.length === 0 && $project?.keys?.length === 0 diff --git a/src/routes/console/project-[project]/uploadVariablesModal.svelte b/src/routes/console/project-[project]/uploadVariablesModal.svelte index 0bf44006a..84bfc6320 100644 --- a/src/routes/console/project-[project]/uploadVariablesModal.svelte +++ b/src/routes/console/project-[project]/uploadVariablesModal.svelte @@ -85,7 +85,7 @@ {/if}

  • - + diff --git a/src/routes/console/store.ts b/src/routes/console/store.ts index 594b0bf8f..af3eb65ee 100644 --- a/src/routes/console/store.ts +++ b/src/routes/console/store.ts @@ -1,9 +1,14 @@ import { page } from '$app/stores'; +import type { HeaderAlert } from '$lib/stores/headerAlert'; import type { Models } from '@appwrite.io/console'; -import { derived } from 'svelte/store'; +import { derived, writable } from 'svelte/store'; export const version = derived(page, ($page) => $page.data.version as string | null); export const consoleVariables = derived( page, ($page) => $page.data.consoleVariables as Models.ConsoleVariables ); + +export const showPostReleaseModal = writable(false); + +export const activeHeaderAlert = writable(null); diff --git a/src/routes/console/supportWizard.svelte b/src/routes/console/supportWizard.svelte new file mode 100644 index 000000000..a4e28d4c1 --- /dev/null +++ b/src/routes/console/supportWizard.svelte @@ -0,0 +1,100 @@ + + + + +

    Contact the Appwrite Team

    +

    + If you found a bug or have questions, please reach out to the Appwrite team. We try to + respond to all messages within our office hours. +

    +

    Available: Mon-Fri 09:00 - 17:00 UTC

    +
    + Currently: + {#if isSupportOnline()} +
    +
    +
    diff --git a/src/routes/console/wizard/cloudOrganization/addressDetails.svelte b/src/routes/console/wizard/cloudOrganization/addressDetails.svelte new file mode 100644 index 000000000..608833f9c --- /dev/null +++ b/src/routes/console/wizard/cloudOrganization/addressDetails.svelte @@ -0,0 +1,141 @@ + + + + Billing address + Add a billing address for your organization. + + + {#if addressList} + + +
    +

    {element.streetAddress}

    + {#if element?.addressLine2} +

    {element.addressLine2}

    + {/if} +

    {element.city}

    +

    {element.state}

    +

    {element.postalCode}

    +

    {element.country}

    +
    +
    + + + Add new billing address + + + + + + + + + + + + + +
    + {/if} +
    +
    diff --git a/src/routes/console/wizard/cloudOrganization/confirmDetails.svelte b/src/routes/console/wizard/cloudOrganization/confirmDetails.svelte new file mode 100644 index 000000000..58aedf179 --- /dev/null +++ b/src/routes/console/wizard/cloudOrganization/confirmDetails.svelte @@ -0,0 +1,104 @@ + + + + Confirm your details + + Confirm the details of your new organization and start your free trial. + + +

    Organization name

    +
    +

    {$createOrganization.name}

    + {#if $createOrganization?.id} + {$createOrganization.id} + {/if} +
    + + {#if $createOrganization.billingPlan !== BillingPlan.STARTER} +
    +

    Additional members

    +

    {collaboratorsNumber} members

    +
    +
    +

    Payment

    + {#await fetchCard()} +
    +
    +
    + {:then card} + +

    + {card?.brand} ending in {card?.last4} +

    + +
    + {/await} +
    + {/if} + + {#if $createOrganization.billingPlan !== BillingPlan.STARTER} + +

    {plan.name} plan

    +

    ${plan.price}

    +
    + +

    Additional members ({collaboratorsNumber})

    +

    ${collaboratorPrice * collaboratorsNumber}

    +
    +
    + {/if} + +

    Estimated total

    +

    ${totalExpences}

    +
    + + {#if $createOrganization.billingPlan !== BillingPlan.STARTER} +

    + This amount, and any additional usage fees, will be charged on a recurring 30-day + billing cycle after your trial period ends on {toLocaleDate(billingPayDate.toString())}. +

    + {/if} + + diff --git a/src/routes/console/wizard/cloudOrganization/inviteMembers.svelte b/src/routes/console/wizard/cloudOrganization/inviteMembers.svelte new file mode 100644 index 000000000..3c84e8c81 --- /dev/null +++ b/src/routes/console/wizard/cloudOrganization/inviteMembers.svelte @@ -0,0 +1,102 @@ + + + + Invite organization members + + Invite team members to collaborate with you in the Appwrite console. Members will have + access to all services and payment data within your organization. + + + + {#if $createOrganization.billingPlan === BillingPlan.SCALE} + You can add unlimited organization members on the {plan.name} plan at no cost. Each member + added will receive an email invite to your organization on completion. + {:else if $createOrganization.billingPlan === BillingPlan.PRO} + You can add unlimited organization members on the {plan.name} plan for + ${plan.addons.member.price} each per month. Each member added will receive an + email invite to your organization on completion. + {/if} + + +
    +
    + + + + + + +
    + + {#if $createOrganization?.collaborators?.length} +
    +
    + + Collaborator + {#if $createOrganization.billingPlan === BillingPlan.PRO} + Cost + {/if} + + + + {#each $createOrganization.collaborators as collaborator} + + {collaborator} + {#if $createOrganization.billingPlan === BillingPlan.PRO} + 15$ + {/if} + + + + + {/each} + +
    + + {/if} + diff --git a/src/routes/console/wizard/cloudOrganization/organizationDetails.svelte b/src/routes/console/wizard/cloudOrganization/organizationDetails.svelte new file mode 100644 index 000000000..90db8ad77 --- /dev/null +++ b/src/routes/console/wizard/cloudOrganization/organizationDetails.svelte @@ -0,0 +1,139 @@ + + + + Organization details + + + + {#if !showCustomId} +
    + (showCustomId = !showCustomId)}> + +
    + {:else} + + {/if} +
    + +

    Plan

    +

    + For more details on our plans, visit our pricing page. +

    +
      +
    • + + +
      +

      + {tierFree.name} - ${freePlan?.price}/month +

      +

      {tierFree.description}

      +
      +
      +
      +
    • + +
    • + + +
      +

      + {tierPro.name} - ${proPlan.price}/month per organization member + exta + usage +

      +

      + {tierPro.description} +

      +
      + 14 DAY FREE TRIAL +
      +
      +
    • +
    • + + +
      +

      + {tierScale.name} - ${scalePlan.price}/month + extra usage +

      +

      + {tierScale.description} +

      +
      +
      + + COMING SOON +
      +
      +
      +
    • +
    +
    diff --git a/src/routes/console/wizard/cloudOrganization/paymentDetails.svelte b/src/routes/console/wizard/cloudOrganization/paymentDetails.svelte new file mode 100644 index 000000000..b9378f5f1 --- /dev/null +++ b/src/routes/console/wizard/cloudOrganization/paymentDetails.svelte @@ -0,0 +1,115 @@ + + + + Payment details + + Add a payment method to your organization. You will not be charged until your trial ends on {toLocaleDate(billingPayDate.toString())}. + + + + + + +

    + Restrict your resource usage by setting a budget cap. . +

    + {#if budgetEnabled} +
    + +
    + {/if} +
    +
    +
    diff --git a/src/routes/console/wizard/cloudOrganization/store.ts b/src/routes/console/wizard/cloudOrganization/store.ts new file mode 100644 index 000000000..0c2e71e7a --- /dev/null +++ b/src/routes/console/wizard/cloudOrganization/store.ts @@ -0,0 +1,26 @@ +import { BillingPlan } from '$lib/constants'; +import type { WizardStepsType } from '$lib/layout/wizard.svelte'; +import type { Tier } from '$lib/stores/billing'; +import { writable } from 'svelte/store'; + +export const createOrgSteps = writable(new Map()); +export const createOrganizationFinalAction = writable('Start trial'); + +export const createOrganization = writable<{ + id?: string; + name: string; + billingPlan: Tier; + paymentMethodId: string; + billingAddressId: string; + collaborators?: string[]; + billingBudget?: number; + taxId?: string; +}>({ + id: null, + name: null, + billingPlan: BillingPlan.PRO, + paymentMethodId: null, + collaborators: [], + billingAddressId: null, + taxId: null +}); diff --git a/src/routes/console/wizard/cloudOrganization/usageRates.svelte b/src/routes/console/wizard/cloudOrganization/usageRates.svelte new file mode 100644 index 000000000..e90faac66 --- /dev/null +++ b/src/routes/console/wizard/cloudOrganization/usageRates.svelte @@ -0,0 +1,116 @@ + + + + {#if isFree} + Usage on the Starter plan is limited for the following resources. Next billing period: {toLocaleDate( + nextDate + )}. + {:else if tier === BillingPlan.PRO} +

    + Usage on the Pro plan will be charged at the end of each billing period at the following + rates. Next billing period: {toLocaleDate(nextDate)}. +

    + {:else if tier === BillingPlan.SCALE} +

    + Usage on the Scale plan will be charged at the end of each billing period at the + following rates. Next billing period: {toLocaleDate(nextDate)}. +

    + {/if} + + + Resource + Limit + {#if !isFree} + Rate + {/if} + + + {#each planData as usage} + {#if usage['id'] === 'members'} + + {usage.resource} + + {plan[usage.id] || 'Unlimited'} + + {#if !isFree} + + ${plan.addons.member.price}/{usage?.unit} + + {/if} + + {:else} + {@const addon = plan.addons[usage.id]} + + {usage.resource} + + {abbreviateNumber(plan[usage.id])}{usage?.unit} + + {#if !isFree} + + ${addon?.price}/{['MB', 'GB', 'TB'].includes(addon?.unit) + ? addon?.value + : abbreviateNumber(addon?.value, 0)}{usage?.unit} + + {/if} + + {/if} + {/each} + +
    + + + +
    diff --git a/src/routes/console/wizard/cloudOrganizationChangeTier/addressDetails.svelte b/src/routes/console/wizard/cloudOrganizationChangeTier/addressDetails.svelte new file mode 100644 index 000000000..5bd9ebaf5 --- /dev/null +++ b/src/routes/console/wizard/cloudOrganizationChangeTier/addressDetails.svelte @@ -0,0 +1,144 @@ + + + + Billing address + Add a billing address for your organization. + + + {#if addressList} + + +
    +

    {element.streetAddress}

    + {#if element?.addressLine2} +

    {element.addressLine2}

    + {/if} +

    {element.city}

    +

    {element.state}

    +

    {element.postalCode}

    +

    {element.country}

    +
    +
    + + + Add new billing address + + + + + + + + + + + + + +
    + {/if} +
    +
    diff --git a/src/routes/console/wizard/cloudOrganizationChangeTier/choosePlan.svelte b/src/routes/console/wizard/cloudOrganizationChangeTier/choosePlan.svelte new file mode 100644 index 000000000..76ff8498e --- /dev/null +++ b/src/routes/console/wizard/cloudOrganizationChangeTier/choosePlan.svelte @@ -0,0 +1,194 @@ + + + + Choose a plan + +

    Plan

    +

    + For more details on our plans, visit our pricing page. +

    +
      +
    • + + +
      +

      + {tierFree.name} - ${freePlan.price}/month +

      +

      {tierFree.description}

      +
      +
      + {#if $organization.billingPlan === BillingPlan.STARTER} + CURRENT PLAN + {/if} +
      +
      +
      +
    • +
    • + + +
      +

      + {tierPro.name} - ${proPlan.price}/month per organization member + extra + usage +

      +

      + {tierPro.description} +

      +
      +
      + {#if $organization.billingPlan === BillingPlan.PRO} + CURRENT PLAN + {:else} + 14 DAY FREE TRIAL + {/if} +
      +
      +
      +
    • +
    • + + +
      +

      + {tierScale.name} - ${scalePlan.price}/month + extra usage +

      +

      + {tierScale.description} +

      +
      +
      + COMING SOON +
      +
      +
      +
    • +
    +
    diff --git a/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte b/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte new file mode 100644 index 000000000..e3c33693b --- /dev/null +++ b/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte @@ -0,0 +1,140 @@ + + +{#if downgradeToStarter} + + Confirm plan change + + Your feedback is important to us and helps us improve the services Appwrite offer. If + there is a specific reason you chose to change your plan at this time, please let us + know. + + + + + +{:else} + + Confirm your details + + Confirm the details of your new organization and start your free trial. + + +

    Organization name

    +
    +

    {$organization.name}

    +
    + + {#if $changeOrganizationTier.billingPlan !== BillingPlan.STARTER} +
    +

    Additional members

    +

    {collaboratorsNumber} members

    +
    +
    +

    Payment

    + {#await fetchCard()} +
    +
    +
    + {:then card} + +

    + Card ending in {card.last4} +

    + +
    + {/await} +
    + {/if} + + + ($changeOrganizationTier.couponCode = e.detail.code)} /> + {#if $changeOrganizationTier.billingPlan !== BillingPlan.STARTER} + +

    {plan.name} plan

    +

    ${plan.price}

    +
    + +

    Additional members ({collaboratorsNumber})

    +

    ${collaboratorPrice * collaboratorsNumber}

    +
    + {#if couponData?.status === 'active'} + +

    Credits applied ({couponData.credits})

    +

    -${couponData.credits}

    +
    + {/if} + {/if} +
    + +

    Estimated total

    +

    + ${couponData?.status === 'active' + ? totalExpences - couponData.credits >= 0 + ? totalExpences - couponData.credits + : 0 + : totalExpences} +

    +
    + +

    + This amount, and any additional usage fees, will be charged on a recurring 30-day + billing cycle after your trial period ends on {toLocaleDate(billingPayDate.toString())}. +

    + + +{/if} diff --git a/src/routes/console/wizard/cloudOrganizationChangeTier/inviteMembers.svelte b/src/routes/console/wizard/cloudOrganizationChangeTier/inviteMembers.svelte new file mode 100644 index 000000000..32e30c8b3 --- /dev/null +++ b/src/routes/console/wizard/cloudOrganizationChangeTier/inviteMembers.svelte @@ -0,0 +1,118 @@ + + + + Invite organization members + + Invite team members to collaborate with you in the Appwrite console. Members will have + access to all services and payment data within your organization. + + + + {#if $changeOrganizationTier.billingPlan === BillingPlan.SCALE} + You can add unlimited organization members on the {plan.name} plan at no cost. Each member + added will receive an email invite to your organization on completion. + {:else if $changeOrganizationTier.billingPlan === BillingPlan.PRO} + You can add unlimited organization members on the {plan.name} plan for + ${plan.addons.member.price} each per month. Each member added will receive an + email invite to your organization on completion. + {/if} + + +
    +
    + + + + + +
    +
    + + {#if $changeOrganizationTier?.collaborators?.length} +
    + + + Collaborator + {#if $changeOrganizationTier.billingPlan === BillingPlan.PRO} + Cost + {/if} + + + + {#each $changeOrganizationTier.collaborators as collaborator} + + {collaborator} + {#if $changeOrganizationTier.billingPlan === BillingPlan.PRO} + 15$ + {/if} + + + + + {/each} + +
    +
    + {/if} +
    diff --git a/src/routes/console/wizard/cloudOrganizationChangeTier/paymentDetails.svelte b/src/routes/console/wizard/cloudOrganizationChangeTier/paymentDetails.svelte new file mode 100644 index 000000000..b82943719 --- /dev/null +++ b/src/routes/console/wizard/cloudOrganizationChangeTier/paymentDetails.svelte @@ -0,0 +1,124 @@ + + + + Payment details + + Confirm the payment method for your organization. + + + + + + +

    + Restrict your resource usage by setting a budget cap. . +

    + {#if budgetEnabled} +
    + +
    + {/if} +
    +
    +
    diff --git a/src/routes/console/wizard/cloudOrganizationChangeTier/planExcess.svelte b/src/routes/console/wizard/cloudOrganizationChangeTier/planExcess.svelte new file mode 100644 index 000000000..bfb737582 --- /dev/null +++ b/src/routes/console/wizard/cloudOrganizationChangeTier/planExcess.svelte @@ -0,0 +1,145 @@ + + + + + {#if currentTier === BillingPlan.STARTER} + Your usage exceeds the {plan.name} plan limits + {:else} + Changing your plan now will result in removal of organization members and more + {/if} + + + {#if excess?.members > 0} + {#if currentTier === BillingPlan.STARTER} + The Starter plan has a limit of one organization member. By proceeding, all but the + creator of the organization admin will be removed. + {:else if currentTier === BillingPlan.PRO} + Additional organization members on the Pro plan cost {collaboratorPrice} per member per billing + period. By proceeding, you acknowledge your fees may increase in your next billing period. + {/if} + {/if} + {#if excess?.bandwidth > 0 || excess?.executions > 0 || excess?.storage > 0 || excess?.users} + Until you reduce your usage, you will be unable to add to the resources listed below in all + projects within your organization. The current billing cycle will end on {toLocaleDate( + $organization.billingCurrentInvoiceDate + )}. Any executions, bandwidth, or messaging usage will be reset at that time. + {/if} + + + {#if currentTier === BillingPlan.STARTER} + + {:else if currentTier === BillingPlan.PRO} + + {/if} + + + + + + Resource + Free limit + Excess usage + + + {#if excess?.members} + + Organization members + {plan.members} members + +

    + + {excess?.members} members +

    +
    +
    + {/if} + {#if excess?.storage} + + Storage + {plan.storage} GB + +

    + + {humanFileSize(excess?.storage)} +

    +
    +
    + {/if} + {#if excess?.executions} + + Function executions + + {abbreviateNumber(plan.executions)} executions + + +

    + + + {formatNum(excess?.executions)} executions + +

    +
    +
    + {/if} + {#if excess?.users} + + Users + + {abbreviateNumber(plan.users)} users + + +

    + + + {formatNum(excess?.users)} users + +

    +
    +
    + {/if} +
    +
    diff --git a/src/routes/console/wizard/cloudOrganizationChangeTier/store.ts b/src/routes/console/wizard/cloudOrganizationChangeTier/store.ts new file mode 100644 index 000000000..f9f97b578 --- /dev/null +++ b/src/routes/console/wizard/cloudOrganizationChangeTier/store.ts @@ -0,0 +1,34 @@ +import { BillingPlan } from '$lib/constants'; +import type { WizardStepsType } from '$lib/layout/wizard.svelte'; +import type { Tier } from '$lib/stores/billing'; +import { writable } from 'svelte/store'; + +export const changeTierSteps = writable(new Map()); +export const isUpgrade = writable(false); +export const changeOrganizationFinalAction = writable('Start trial'); + +export const changeOrganizationTier = writable<{ + billingPlan: Tier; + paymentMethodId: string; + billingAddressId: string; + billingBudget?: number; + collaborators?: string[]; + isOverLimit?: boolean; + limitOverflow?: { + bandwidth?: number; + executions?: number; + storage?: number; + users?: number; + members?: number; + }; + taxId?: string; + feedbackMessage?: string; + couponCode?: string; +}>({ + billingPlan: BillingPlan.PRO, + paymentMethodId: null, + collaborators: [], + isOverLimit: false, + billingAddressId: null, + taxId: null +}); diff --git a/src/routes/console/wizard/cloudOrganizationChangeTier/usageExcess.svelte b/src/routes/console/wizard/cloudOrganizationChangeTier/usageExcess.svelte new file mode 100644 index 000000000..f3b1a6baa --- /dev/null +++ b/src/routes/console/wizard/cloudOrganizationChangeTier/usageExcess.svelte @@ -0,0 +1,20 @@ + + + + Your usage exceeds the limits of the {tierToPlan($organization.billingPlan).name} plan + + View the current usage for {$organization.name} and where you will exceed the limits of + your new plan. + + + + diff --git a/src/routes/console/wizardFeedback/step1.svelte b/src/routes/console/wizard/feedback/step1.svelte similarity index 100% rename from src/routes/console/wizardFeedback/step1.svelte rename to src/routes/console/wizard/feedback/step1.svelte diff --git a/src/routes/console/wizardFeedback/step2.svelte b/src/routes/console/wizard/feedback/step2.svelte similarity index 100% rename from src/routes/console/wizardFeedback/step2.svelte rename to src/routes/console/wizard/feedback/step2.svelte diff --git a/src/routes/console/wizard/support/mobileSupportModal.svelte b/src/routes/console/wizard/support/mobileSupportModal.svelte new file mode 100644 index 000000000..31f2108c6 --- /dev/null +++ b/src/routes/console/wizard/support/mobileSupportModal.svelte @@ -0,0 +1,10 @@ + + + + + diff --git a/src/routes/console/wizard/support/step1.svelte b/src/routes/console/wizard/support/step1.svelte new file mode 100644 index 000000000..06f8f265b --- /dev/null +++ b/src/routes/console/wizard/support/step1.svelte @@ -0,0 +1,61 @@ + + + + How can we help you? + + Please describe your request in detail. If applicable, include steps for reproduction of any + in-app issues. + +
    +

    Choose a topic

    +
    + {#each ['general', 'billing', 'technical'] as topic} + { + $supportData.category = topic; + }}>{topic} + {/each} +
    +
    +
    + + {#if options?.length} + + {/if} + + +
    +
    diff --git a/src/routes/console/wizard/support/store.ts b/src/routes/console/wizard/support/store.ts new file mode 100644 index 000000000..a447e1d4d --- /dev/null +++ b/src/routes/console/wizard/support/store.ts @@ -0,0 +1,32 @@ +import { writable } from 'svelte/store'; + +export type SupportData = { + message: string; + category: string; + file?: File | null; + project?: string; +}; + +export const supportData = writable({ + message: '', + category: 'general', + file: null +}); + +export function isSupportOnline() { + const currentDate = new Date(); + const day = currentDate.getUTCDay(); + const hour = currentDate.getUTCHours(); + + if (day === 1 || day === 6) { + return false; + } + + if (hour < 9 || hour > 17) { + return false; + } + + return true; +} + +export const showSupportModal = writable(false); diff --git a/src/routes/login/+page.svelte b/src/routes/login/+page.svelte index 13ef9c298..a46062288 100644 --- a/src/routes/login/+page.svelte +++ b/src/routes/login/+page.svelte @@ -15,6 +15,7 @@ import { Dependencies } from '$lib/constants'; import { Submit, trackEvent, trackError } from '$lib/actions/analytics'; import { isCloud } from '$lib/system'; + import { page } from '$app/stores'; let mail: string, pass: string, disabled: boolean; @@ -28,7 +29,17 @@ message: 'Successfully logged in.' }); trackEvent(Submit.AccountCreate); - await goto(`${base}/console`); + if ($page.url.searchParams) { + const redirect = $page.url.searchParams.get('redirect'); + $page.url.searchParams.delete('redirect'); + if (redirect) { + await goto(`${base}${redirect}${$page.url.search}`); + } else { + await goto(`${base}/console${$page.url.search ?? ''}`); + } + } else { + await goto(`${base}/console`); + } } catch (error) { disabled = false; addNotification({ @@ -40,9 +51,19 @@ } function onGithubLogin() { + let url = window.location.origin; + if ($page.url.searchParams) { + const redirect = $page.url.searchParams.get('redirect'); + $page.url.searchParams.delete('redirect'); + if (redirect) { + url = `${base}${redirect}${$page.url.search}`; + } else { + url = `${base}/console${$page.url.search ?? ''}`; + } + } sdk.forConsole.account.createOAuth2Session( 'github', - window.location.origin, + window.location.origin + url, window.location.origin, ['read:user', 'user:email'] ); @@ -93,7 +114,9 @@ Forgot Password? diff --git a/src/routes/register/+page.svelte b/src/routes/register/+page.svelte index 3677e7de3..f2c15e4f3 100644 --- a/src/routes/register/+page.svelte +++ b/src/routes/register/+page.svelte @@ -18,6 +18,7 @@ import { Submit, trackError, trackEvent } from '$lib/actions/analytics'; import { ID } from '@appwrite.io/console'; import { isCloud } from '$lib/system'; + import { page } from '$app/stores'; let name: string, mail: string, pass: string, disabled: boolean; let terms = false; @@ -28,7 +29,17 @@ await sdk.forConsole.account.create(ID.unique(), mail, pass, name ?? ''); await sdk.forConsole.account.createEmailSession(mail, pass); await invalidate(Dependencies.ACCOUNT); - await goto(`${base}/console`); + if ($page.url.searchParams) { + const redirect = $page.url.searchParams.get('redirect'); + $page.url.searchParams.delete('redirect'); + if (redirect) { + await goto(`${base}${redirect}${$page.url.search}`); + } else { + await goto(`${base}/console${$page.url.search ?? ''}`); + } + } else { + await goto(`${base}/console`); + } trackEvent(Submit.AccountCreate); } catch (error) { disabled = false; diff --git a/src/routes/register/invite/[slug]/+page.svelte b/src/routes/register/invite/[slug]/+page.svelte index 0d31350a4..fa7cacb81 100644 --- a/src/routes/register/invite/[slug]/+page.svelte +++ b/src/routes/register/invite/[slug]/+page.svelte @@ -73,7 +73,9 @@ throw new Error((await res.json()).message); } else { await sdk.forConsole.account.createEmailSession(mail, pass); - await sdk.forConsole.account.updatePrefs({ code }); + const prefs = await sdk.forConsole.account.getPrefs(); + const newPrefs = { ...prefs, code }; + await sdk.forConsole.account.updatePrefs(newPrefs); await invalidate(Dependencies.ACCOUNT); await goto(`${base}/console`); trackEvent('submit_account_create', { code: code }); diff --git a/src/routes/store.ts b/src/routes/store.ts index be6859877..5c5fe880d 100644 --- a/src/routes/store.ts +++ b/src/routes/store.ts @@ -1,10 +1,5 @@ -import { page } from '$app/stores'; -import type { Models } from '@appwrite.io/console'; -import { derived, writable } from 'svelte/store'; +import { writable } from 'svelte/store'; export const loading = writable(true); -export const organizations = derived(page, ($page) => { - return $page.data.organizations as Models.TeamList; -}); export const requestedMigration = writable | null>(null); diff --git a/svelte.config.js b/svelte.config.js index ca8f1dd0b..a3e96612f 100644 --- a/svelte.config.js +++ b/svelte.config.js @@ -1,11 +1,13 @@ import adapter from '@sveltejs/adapter-static'; import preprocess from 'svelte-preprocess'; +import { preprocessMeltUI } from '@melt-ui/pp'; +import sequence from 'svelte-sequential-preprocessor'; /** @type {import('@sveltejs/kit').Config} */ const config = { // Consult https://github.com/sveltejs/svelte-preprocess // for more information about preprocessors - preprocess: preprocess(), + preprocess: sequence([preprocess(), preprocessMeltUI()]), compilerOptions: { accessors: process.env.VITEST },

    Add the Signature Key to the X-Appwrite-Webhook-Signature header to validate your webhooks. import { goto } from '$app/navigation'; - import { base } from '$app/paths'; - import { page } from '$app/stores'; - import { tooltip } from '$lib/actions/tooltip'; - import { - CardContainer, - Empty, - GridItem1, - Heading, - Id, - PaginationWithLimit - } from '$lib/components'; + import { Empty, GridItem1, CardContainer, PaginationWithLimit, Id } from '$lib/components'; import { Pill } from '$lib/elements'; - import { Button } from '$lib/elements/forms'; - import { Container } from '$lib/layout'; + import Create from './create.svelte'; + import { Container, ContainerHeader } from '$lib/layout'; + import { base } from '$app/paths'; + import { tooltip } from '$lib/actions/tooltip'; + import { page } from '$app/stores'; import type { Models } from '@appwrite.io/console'; import { writable } from 'svelte/store'; import type { PageData } from './$types'; - import Create from './create.svelte'; export let data: PageData; @@ -34,19 +26,18 @@ -