Merge remote-tracking branch 'upstream/master' into feat/image-upload
No files matched your search
@@ -30,7 +30,8 @@
|
||||
"react-router-dom": "^6.23.1",
|
||||
"react-toastify": "^10.0.5",
|
||||
"recharts": "2.12.7",
|
||||
"redux-persist": "6.0.0"
|
||||
"redux-persist": "6.0.0",
|
||||
"vite-plugin-svgr": "^4.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.2.66",
|
||||
@@ -47,7 +48,6 @@
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
|
||||
"integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@jridgewell/gen-mapping": "^0.3.5",
|
||||
@@ -74,7 +74,6 @@
|
||||
"version": "7.24.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.7.tgz",
|
||||
"integrity": "sha512-qJzAIcv03PyaWqxRgO4mSU3lihncDT296vnyuE2O8uA4w3UHWI4S3hgeZd1L8W1Bft40w9JxJ2b412iDUFFRhw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
@@ -84,7 +83,6 @@
|
||||
"version": "7.24.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.7.tgz",
|
||||
"integrity": "sha512-nykK+LEK86ahTkX/3TgauT0ikKoNCfKHEaZYTUVupJdTLzGNvrblu4u6fa7DhZONAltdf8e662t/abY8idrd/g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@ampproject/remapping": "^2.2.0",
|
||||
@@ -115,7 +113,6 @@
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
|
||||
"integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@babel/generator": {
|
||||
@@ -137,7 +134,6 @@
|
||||
"version": "7.24.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.7.tgz",
|
||||
"integrity": "sha512-ctSdRHBi20qWOfy27RUb4Fhp07KSJ3sXcuSvTrXrc4aG8NSYDo1ici3Vhg9bg69y5bj0Mr1lh0aeEgTvc12rMg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/compat-data": "^7.24.7",
|
||||
@@ -204,7 +200,6 @@
|
||||
"version": "7.24.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.7.tgz",
|
||||
"integrity": "sha512-1fuJEwIrp+97rM4RWdO+qrRsZlAeL1lQJoPqtCYWv0NL115XM93hIH4CSRln2w52SqvmY5hqdtauB6QFCDiZNQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/helper-environment-visitor": "^7.24.7",
|
||||
@@ -234,7 +229,6 @@
|
||||
"version": "7.24.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz",
|
||||
"integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/traverse": "^7.24.7",
|
||||
@@ -278,7 +272,6 @@
|
||||
"version": "7.24.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.7.tgz",
|
||||
"integrity": "sha512-yy1/KvjhV/ZCL+SM7hBrvnZJ3ZuT9OuZgIJAGpPEToANvc3iM6iDvBnRjtElWibHU6n8/LPR/EjX9EtIEYO3pw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
@@ -288,7 +281,6 @@
|
||||
"version": "7.24.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.7.tgz",
|
||||
"integrity": "sha512-NlmJJtvcw72yRJRcnCmGvSi+3jDEg8qFu3z0AFoymmzLx5ERVWyzd9kVXr7Th9/8yIJi2Zc6av4Tqz3wFs8QWg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/template": "^7.24.7",
|
||||
@@ -571,7 +563,6 @@
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -588,7 +579,6 @@
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -605,7 +595,6 @@
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -622,7 +611,6 @@
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -639,7 +627,6 @@
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -656,7 +643,6 @@
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -673,7 +659,6 @@
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -690,7 +675,6 @@
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -707,7 +691,6 @@
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -724,7 +707,6 @@
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -741,7 +723,6 @@
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -758,7 +739,6 @@
|
||||
"cpu": [
|
||||
"loong64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -775,7 +755,6 @@
|
||||
"cpu": [
|
||||
"mips64el"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -792,7 +771,6 @@
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -809,7 +787,6 @@
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -826,7 +803,6 @@
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -843,7 +819,6 @@
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -860,7 +835,6 @@
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -877,7 +851,6 @@
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -894,7 +867,6 @@
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -911,7 +883,6 @@
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -928,7 +899,6 @@
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -945,7 +915,6 @@
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -1766,6 +1735,27 @@
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/pluginutils": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz",
|
||||
"integrity": "sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==",
|
||||
"dependencies": {
|
||||
"@types/estree": "^1.0.0",
|
||||
"estree-walker": "^2.0.2",
|
||||
"picomatch": "^2.3.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"rollup": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm-eabi": {
|
||||
"version": "4.18.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz",
|
||||
@@ -1773,7 +1763,6 @@
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -1787,7 +1776,6 @@
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -1801,7 +1789,6 @@
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -1815,7 +1802,6 @@
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -1829,7 +1815,6 @@
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -1843,7 +1828,6 @@
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -1857,7 +1841,6 @@
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -1871,7 +1854,6 @@
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -1885,7 +1867,6 @@
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -1899,7 +1880,6 @@
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -1913,7 +1893,6 @@
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -1927,7 +1906,6 @@
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -1941,7 +1919,6 @@
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -1955,7 +1932,6 @@
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -1969,7 +1945,6 @@
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -1983,7 +1958,6 @@
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -2011,6 +1985,232 @@
|
||||
"integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==",
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/@svgr/babel-plugin-add-jsx-attribute": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz",
|
||||
"integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/gregberge"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/core": "^7.0.0-0"
|
||||
}
|
||||
},
|
||||
"node_modules/@svgr/babel-plugin-remove-jsx-attribute": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz",
|
||||
"integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/gregberge"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/core": "^7.0.0-0"
|
||||
}
|
||||
},
|
||||
"node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz",
|
||||
"integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/gregberge"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/core": "^7.0.0-0"
|
||||
}
|
||||
},
|
||||
"node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz",
|
||||
"integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/gregberge"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/core": "^7.0.0-0"
|
||||
}
|
||||
},
|
||||
"node_modules/@svgr/babel-plugin-svg-dynamic-title": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz",
|
||||
"integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/gregberge"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/core": "^7.0.0-0"
|
||||
}
|
||||
},
|
||||
"node_modules/@svgr/babel-plugin-svg-em-dimensions": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz",
|
||||
"integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/gregberge"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/core": "^7.0.0-0"
|
||||
}
|
||||
},
|
||||
"node_modules/@svgr/babel-plugin-transform-react-native-svg": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz",
|
||||
"integrity": "sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/gregberge"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/core": "^7.0.0-0"
|
||||
}
|
||||
},
|
||||
"node_modules/@svgr/babel-plugin-transform-svg-component": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz",
|
||||
"integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/gregberge"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/core": "^7.0.0-0"
|
||||
}
|
||||
},
|
||||
"node_modules/@svgr/babel-preset": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.1.0.tgz",
|
||||
"integrity": "sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==",
|
||||
"dependencies": {
|
||||
"@svgr/babel-plugin-add-jsx-attribute": "8.0.0",
|
||||
"@svgr/babel-plugin-remove-jsx-attribute": "8.0.0",
|
||||
"@svgr/babel-plugin-remove-jsx-empty-expression": "8.0.0",
|
||||
"@svgr/babel-plugin-replace-jsx-attribute-value": "8.0.0",
|
||||
"@svgr/babel-plugin-svg-dynamic-title": "8.0.0",
|
||||
"@svgr/babel-plugin-svg-em-dimensions": "8.0.0",
|
||||
"@svgr/babel-plugin-transform-react-native-svg": "8.1.0",
|
||||
"@svgr/babel-plugin-transform-svg-component": "8.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/gregberge"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/core": "^7.0.0-0"
|
||||
}
|
||||
},
|
||||
"node_modules/@svgr/core": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz",
|
||||
"integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==",
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.21.3",
|
||||
"@svgr/babel-preset": "8.1.0",
|
||||
"camelcase": "^6.2.0",
|
||||
"cosmiconfig": "^8.1.3",
|
||||
"snake-case": "^3.0.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/gregberge"
|
||||
}
|
||||
},
|
||||
"node_modules/@svgr/core/node_modules/cosmiconfig": {
|
||||
"version": "8.3.6",
|
||||
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz",
|
||||
"integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==",
|
||||
"dependencies": {
|
||||
"import-fresh": "^3.3.0",
|
||||
"js-yaml": "^4.1.0",
|
||||
"parse-json": "^5.2.0",
|
||||
"path-type": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/d-fischer"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": ">=4.9.5"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"typescript": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@svgr/hast-util-to-babel-ast": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz",
|
||||
"integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==",
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.21.3",
|
||||
"entities": "^4.4.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/gregberge"
|
||||
}
|
||||
},
|
||||
"node_modules/@svgr/plugin-jsx": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz",
|
||||
"integrity": "sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==",
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.21.3",
|
||||
"@svgr/babel-preset": "8.1.0",
|
||||
"@svgr/hast-util-to-babel-ast": "8.0.0",
|
||||
"svg-parser": "^2.0.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/gregberge"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@svgr/core": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/babel__core": {
|
||||
"version": "7.20.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
|
||||
@@ -2123,7 +2323,6 @@
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
|
||||
"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/parse-json": {
|
||||
@@ -2266,7 +2465,6 @@
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
|
||||
"dev": true,
|
||||
"license": "Python-2.0"
|
||||
},
|
||||
"node_modules/array-buffer-byte-length": {
|
||||
@@ -2489,7 +2687,6 @@
|
||||
"version": "4.23.1",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.1.tgz",
|
||||
"integrity": "sha512-TUfofFo/KsK/bWZ9TWQ5O26tsWW4Uhmt8IYklbnUa70udB6P2wA7w7o4PY4muaEPBQaAX+CEnmmIA41NVHtPVw==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
@@ -2547,11 +2744,21 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/camelcase": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
|
||||
"integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001636",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001636.tgz",
|
||||
"integrity": "sha512-bMg2vmr8XBsbL6Lr0UHXy/21m84FTxDLWn2FSqMd5PrlbMxwJlQnC2YWYxVgp66PZE+BBNF2jYQUBKCo1FDeZg==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
@@ -2989,13 +3196,32 @@
|
||||
"csstype": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/dot-case": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz",
|
||||
"integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==",
|
||||
"dependencies": {
|
||||
"no-case": "^3.0.4",
|
||||
"tslib": "^2.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/electron-to-chromium": {
|
||||
"version": "1.4.810",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.810.tgz",
|
||||
"integrity": "sha512-Kaxhu4T7SJGpRQx99tq216gCq2nMxJo+uuT6uzz9l8TVN2stL7M06MIIXAtr9jsrLs2Glflgf2vMQRepxawOdQ==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/entities": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
|
||||
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
|
||||
"engines": {
|
||||
"node": ">=0.12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/error-ex": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
|
||||
@@ -3175,7 +3401,6 @@
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz",
|
||||
"integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
@@ -3214,7 +3439,6 @@
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz",
|
||||
"integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
@@ -3551,6 +3775,11 @@
|
||||
"node": ">=4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/estree-walker": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
|
||||
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
|
||||
},
|
||||
"node_modules/esutils": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
|
||||
@@ -3720,7 +3949,6 @@
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
@@ -3773,7 +4001,6 @@
|
||||
"version": "1.0.0-beta.2",
|
||||
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
|
||||
"integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
@@ -4509,7 +4736,6 @@
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
||||
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"argparse": "^2.0.1"
|
||||
@@ -4561,7 +4787,6 @@
|
||||
"version": "2.2.3",
|
||||
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
|
||||
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"json5": "lib/cli.js"
|
||||
@@ -4666,11 +4891,18 @@
|
||||
"loose-envify": "cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/lower-case": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz",
|
||||
"integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==",
|
||||
"dependencies": {
|
||||
"tslib": "^2.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/lru-cache": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
|
||||
"integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"yallist": "^3.0.2"
|
||||
@@ -4720,7 +4952,6 @@
|
||||
"version": "3.3.7",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
|
||||
"integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
@@ -4742,11 +4973,19 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/no-case": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz",
|
||||
"integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==",
|
||||
"dependencies": {
|
||||
"lower-case": "^2.0.2",
|
||||
"tslib": "^2.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/node-releases": {
|
||||
"version": "2.0.14",
|
||||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz",
|
||||
"integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/object-assign": {
|
||||
@@ -5011,6 +5250,17 @@
|
||||
"integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/picomatch": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
||||
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
|
||||
"engines": {
|
||||
"node": ">=8.6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
}
|
||||
},
|
||||
"node_modules/possible-typed-array-names": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz",
|
||||
@@ -5025,7 +5275,6 @@
|
||||
"version": "8.4.38",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz",
|
||||
"integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
@@ -5433,7 +5682,6 @@
|
||||
"version": "4.18.0",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.18.0.tgz",
|
||||
"integrity": "sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/estree": "1.0.5"
|
||||
@@ -5539,7 +5787,6 @@
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
@@ -5621,6 +5868,15 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/snake-case": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz",
|
||||
"integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==",
|
||||
"dependencies": {
|
||||
"dot-case": "^3.0.4",
|
||||
"tslib": "^2.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map": {
|
||||
"version": "0.5.7",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
|
||||
@@ -5634,7 +5890,6 @@
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz",
|
||||
"integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
@@ -5775,6 +6030,11 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/svg-parser": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz",
|
||||
"integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ=="
|
||||
},
|
||||
"node_modules/text-table": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
|
||||
@@ -5797,6 +6057,11 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "2.6.3",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
|
||||
"integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ=="
|
||||
},
|
||||
"node_modules/type-check": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
||||
@@ -5920,7 +6185,6 @@
|
||||
"version": "1.0.16",
|
||||
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz",
|
||||
"integrity": "sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
@@ -5992,7 +6256,6 @@
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-5.3.1.tgz",
|
||||
"integrity": "sha512-XBmSKRLXLxiaPYamLv3/hnP/KXDai1NDexN0FpkTaZXTfycHvkRHoenpgl/fvuK/kPbB6xAgoyiryAhQNxYmAQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"esbuild": "^0.21.3",
|
||||
@@ -6044,6 +6307,19 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/vite-plugin-svgr": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/vite-plugin-svgr/-/vite-plugin-svgr-4.2.0.tgz",
|
||||
"integrity": "sha512-SC7+FfVtNQk7So0XMjrrtLAbEC8qjFPifyD7+fs/E6aaNdVde6umlVVh0QuwDLdOMu7vp5RiGFsB70nj5yo0XA==",
|
||||
"dependencies": {
|
||||
"@rollup/pluginutils": "^5.0.5",
|
||||
"@svgr/core": "^8.1.0",
|
||||
"@svgr/plugin-jsx": "^8.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vite": "^2.6.0 || 3 || 4 || 5"
|
||||
}
|
||||
},
|
||||
"node_modules/which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
@@ -6164,7 +6440,6 @@
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
|
||||
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/yaml": {
|
||||
|
||||
@@ -32,7 +32,8 @@
|
||||
"react-router-dom": "^6.23.1",
|
||||
"react-toastify": "^10.0.5",
|
||||
"recharts": "2.12.7",
|
||||
"redux-persist": "6.0.0"
|
||||
"redux-persist": "6.0.0",
|
||||
"vite-plugin-svgr": "^4.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.2.66",
|
||||
|
||||
@@ -18,6 +18,7 @@ import CheckEmail from "./Pages/CheckEmail";
|
||||
import SetNewPassword from "./Pages/SetNewPassword";
|
||||
import NewPasswordConfirmed from "./Pages/NewPasswordConfirmed";
|
||||
import ProtectedRoute from "./Components/ProtectedRoute";
|
||||
import Maintenance from "./Pages/Maintenance";
|
||||
|
||||
function App() {
|
||||
return (
|
||||
@@ -49,6 +50,10 @@ function App() {
|
||||
path="integrations"
|
||||
element={<ProtectedRoute Component={Integrations} />}
|
||||
/>
|
||||
<Route
|
||||
path="maintenance"
|
||||
element={<ProtectedRoute Component={Maintenance} />}
|
||||
/>
|
||||
<Route
|
||||
path="settings"
|
||||
element={<ProtectedRoute Component={Settings} />}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
.alert {
|
||||
margin: 0;
|
||||
width: fit-content;
|
||||
padding: var(--env-var-spacing-1-plus);
|
||||
font-size: var(--env-var-font-size-medium);
|
||||
}
|
||||
.alert .MuiStack-root {
|
||||
max-width: 85%;
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
import PropTypes from "prop-types";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { Box, Stack } from "@mui/material";
|
||||
import InfoOutlinedIcon from "@mui/icons-material/InfoOutlined";
|
||||
import ErrorOutlineOutlinedIcon from "@mui/icons-material/ErrorOutlineOutlined";
|
||||
import WarningAmberOutlinedIcon from "@mui/icons-material/WarningAmberOutlined";
|
||||
import "./index.css";
|
||||
|
||||
/**
|
||||
* Icons mapping for different alert variants.
|
||||
* @type {Object<string, JSX.Element>}
|
||||
*/
|
||||
|
||||
const icons = {
|
||||
info: <InfoOutlinedIcon />,
|
||||
error: <ErrorOutlineOutlinedIcon />,
|
||||
warning: <WarningAmberOutlinedIcon />,
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Object} props
|
||||
* @param {'info' | 'error' | 'warning'} props.variant - The type of alert.
|
||||
* @param {string} [props.title] - The title of the alert.
|
||||
* @param {string} [props.body] - The body text of the alert.
|
||||
* @returns {JSX.Element}
|
||||
*/
|
||||
|
||||
const Alert = ({ variant, title, body }) => {
|
||||
const theme = useTheme();
|
||||
const { bg, border, color } = theme.alert[variant];
|
||||
const icon = icons[variant];
|
||||
|
||||
return (
|
||||
<Stack
|
||||
direction="row"
|
||||
justifyContent="flex-start"
|
||||
className="alert row-stack"
|
||||
gap={theme.gap.ml}
|
||||
sx={{
|
||||
backgroundColor: bg,
|
||||
border: `solid 1px ${border}`,
|
||||
borderRadius: `${theme.shape.borderRadius}px`,
|
||||
}}
|
||||
>
|
||||
{icon && <Box sx={{ color: color }}>{icon}</Box>}
|
||||
<Stack direction="column" gap="2px" sx={{ flex: 1, color: color }}>
|
||||
{title && <Box sx={{ fontWeight: "700" }}>{title}</Box>}
|
||||
{body && <Box sx={{ fontWeight: "400" }}>{body}</Box>}
|
||||
</Stack>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
Alert.propTypes = {
|
||||
variant: PropTypes.oneOf(["info", "error", "warning"]).isRequired,
|
||||
title: PropTypes.string,
|
||||
body: PropTypes.string,
|
||||
};
|
||||
|
||||
export default Alert;
|
||||
@@ -12,7 +12,7 @@
|
||||
}
|
||||
|
||||
.server-status-tile {
|
||||
min-width: 310px;
|
||||
min-width: 250px;
|
||||
width: calc(100% - 310px);
|
||||
padding: var(--spacing-general-1);
|
||||
border: 1px solid var(--color-border-0);
|
||||
|
||||
@@ -5,6 +5,7 @@ import Monitors from "../../assets/Images/Icon-monitor-gray.png";
|
||||
import Incidents from "../../assets/Images/Icon-warning-gray.png";
|
||||
import SensorsIcon from "../../assets/Images/Icon-signal-gray.png";
|
||||
import AllInclusiveIcon from "../../assets/Images/Icon-link-gray.png";
|
||||
import MaintenanceIcon from "../../assets/Images/Icon-maintenance-gray.png";
|
||||
import SettingsIcon from "../../assets/Images/Icon-setting-gray.png";
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { useNavigate, useLocation } from "react-router-dom";
|
||||
@@ -62,6 +63,13 @@ function DashboardMenu() {
|
||||
activeButton === "/integrations",
|
||||
() => handleClick(pathMap["/integrations"], "/integrations")
|
||||
)}
|
||||
{DashboardMenuButton(
|
||||
MaintenanceIcon,
|
||||
"Maintenance",
|
||||
"/maintenance",
|
||||
activeButton === "/maintenance",
|
||||
() => handleClick(pathMap["/maintenance"], "/maintenance")
|
||||
)}
|
||||
{DashboardMenuButton(
|
||||
SettingsIcon,
|
||||
"Settings",
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
.host-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.host-row a {
|
||||
width: var(--env-var-img-width-2);
|
||||
height: var(--env-var-img-width-2);
|
||||
color: var(--env-var-color-5);
|
||||
margin-right: 10px;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
.host-row a svg {
|
||||
width: var(--env-var-font-size-large);
|
||||
height: var(--env-var-font-size-large);
|
||||
}
|
||||
.host-row .host-percentage {
|
||||
font-size: var(--env-var-font-size-small);
|
||||
}
|
||||
|
||||
.host-name {
|
||||
width: fit-content;
|
||||
margin-right: 10px;
|
||||
font-weight: 700;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.host-status {
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
.host-status-details {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border: 1px solid var(--env-var-color-4);
|
||||
border-radius: var(--env-var-radius-2);
|
||||
padding: calc(var(--env-var-spacing-1) / 2);
|
||||
}
|
||||
|
||||
.host-status-text {
|
||||
font-size: var(--env-var-font-size-medium);
|
||||
line-height: var(--env-var-font-size-medium);
|
||||
}
|
||||
.host-status-dot {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border-radius: 50%;
|
||||
margin-right: calc(var(--env-var-spacing-1) / 2);
|
||||
}
|
||||
|
||||
.monitors .MuiPaper-root:has(table.MuiTable-root) {
|
||||
box-shadow: none;
|
||||
border: solid 1px var(--env-var-color-16);
|
||||
border-radius: var(--env-var-radius-1);
|
||||
}
|
||||
.monitors .MuiTableFooter-root .MuiTableCell-root {
|
||||
border: none;
|
||||
}
|
||||
.monitors .MuiTableHead-root,
|
||||
.monitors .MuiTableRow-root:hover {
|
||||
background-color: var(--env-var-color-13);
|
||||
}
|
||||
.monitors .MuiTableHead-root .MuiTableCell-root,
|
||||
.monitors .MuiTableBody-root .MuiTableCell-root {
|
||||
font-size: var(--env-var-font-size-medium);
|
||||
}
|
||||
.monitors .MuiTableHead-root .MuiTableCell-root {
|
||||
padding: var(--env-var-spacing-1) var(--env-var-spacing-2);
|
||||
font-weight: 500;
|
||||
color: var(--env-var-color-2);
|
||||
}
|
||||
.monitors .MuiTableHead-root span {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
height: 14px;
|
||||
width: 20px;
|
||||
overflow: hidden;
|
||||
margin-bottom: -3px;
|
||||
margin-left: 2px;
|
||||
}
|
||||
.monitors .MuiTableHead-root span svg {
|
||||
position: absolute;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
bottom: 0;
|
||||
}
|
||||
.monitors .MuiTableBody-root .MuiTableCell-root {
|
||||
color: var(--env-var-color-5);
|
||||
padding: 6px var(--env-var-spacing-2);
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
import "./index.css";
|
||||
import { useState } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import OpenIt from "../../assets/Images/Icon-open-in-tab-gray.png";
|
||||
import ResponseTimeChart from "../Charts/ResponseTimeChart";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableContainer,
|
||||
TableHead,
|
||||
TableRow,
|
||||
TableFooter,
|
||||
TablePagination,
|
||||
Paper,
|
||||
} from "@mui/material";
|
||||
import SouthRoundedIcon from "@mui/icons-material/SouthRounded";
|
||||
import OpenInNewPage from "../../assets/icons/open-in-new-page.svg?react"
|
||||
|
||||
/**
|
||||
* Host component.
|
||||
* This subcomponent receives a params object and displays the host details.
|
||||
*
|
||||
* @component
|
||||
* @param {Object} params - An object containing the following properties:
|
||||
* @param {string} params.url - The URL of the host.
|
||||
* @param {string} params.title - The name of the host.
|
||||
* @param {string} params.percentageColor - The color of the percentage text.
|
||||
* @param {number} params.precentage - The percentage to display.
|
||||
* @returns {React.ElementType} Returns a div element with the host details.
|
||||
*/
|
||||
const Host = ({ params }) => {
|
||||
return (
|
||||
<div className="host-row">
|
||||
<a href={params.url} target="_blank">
|
||||
<OpenInNewPage />
|
||||
</a>
|
||||
<div className="host-name">{params.title}</div>
|
||||
<div
|
||||
className="host-percentage"
|
||||
style={{ color: params.percentageColor }}
|
||||
>
|
||||
{params.precentage}%
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Status component.
|
||||
* This subcomponent receives a params object and displays the status details of a monitor.
|
||||
*
|
||||
* @component
|
||||
* @param {Object} params - An object containing the following properties:
|
||||
* @param {string} params.backgroundColor - The background color of the status box.
|
||||
* @param {string} params.statusDotColor - The color of the status dot.
|
||||
* @param {string} params.status - The status text to display.
|
||||
* @returns {React.ElementType} Returns a div element with the host status.
|
||||
*/
|
||||
const Status = ({ params }) => {
|
||||
return (
|
||||
<div className="host-status">
|
||||
<div
|
||||
className="host-status-details"
|
||||
style={{ backgroundColor: params.backgroundColor }}
|
||||
>
|
||||
<div
|
||||
className="host-status-dot"
|
||||
style={{ backgroundColor: params.statusDotColor }}
|
||||
/>
|
||||
<span
|
||||
className="host-status-text"
|
||||
style={{ textTransform: "capitalize" }}
|
||||
>
|
||||
{params.status}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* MonitorTable component.
|
||||
* Takes an array of monitor objects and displays them in a table.
|
||||
* Each row in the table represents a monitor and includes the host, status, response time, and action.
|
||||
*
|
||||
* @component
|
||||
* @param {Object[]} monitors - An array of monitor objects. Each object should have the following properties:
|
||||
* @param {string} monitors[].url - The URL of the monitor.
|
||||
* @param {string} monitors[].name - The name of the monitor.
|
||||
* @param {boolean} monitors[].status - The status of the monitor. True if the monitor is up, false otherwise.
|
||||
* @param {Object[]} monitors[].checks - An array of check objects for the response time chart.
|
||||
* @returns {React.Component} Returns a table with the monitor data.
|
||||
*/
|
||||
const MonitorTable = ({ monitors = [] }) => {
|
||||
const [page, setPage] = useState(0);
|
||||
const [rowsPerPage, setRowsPerPage] = useState(5);
|
||||
|
||||
const handleChangePage = (event, newPage) => {
|
||||
setPage(newPage);
|
||||
};
|
||||
|
||||
const handleChangeRowsPerPage = (event) => {
|
||||
setRowsPerPage(parseInt(event.target.value, 10));
|
||||
setPage(0);
|
||||
};
|
||||
|
||||
const mappedRows = monitors
|
||||
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
|
||||
.map((monitor) => {
|
||||
const params = {
|
||||
url: monitor.url,
|
||||
title: monitor.name,
|
||||
precentage: 100,
|
||||
percentageColor:
|
||||
monitor.status === true
|
||||
? "var(--env-var-color-17)"
|
||||
: "var(--env-var-color-19)",
|
||||
status: monitor.status === true ? "up" : "down",
|
||||
backgroundColor:
|
||||
monitor.status === true
|
||||
? "var(--env-var-color-20)"
|
||||
: "var(--env-var-color-21)",
|
||||
statusDotColor:
|
||||
monitor.status === true
|
||||
? "var(--env-var-color-17)"
|
||||
: "var(--env-var-color-19)",
|
||||
};
|
||||
|
||||
return (
|
||||
<TableRow key={monitor._id}>
|
||||
<TableCell>
|
||||
<Host params={params} />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Status params={params} />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<ResponseTimeChart checks={monitor.checks} />
|
||||
</TableCell>
|
||||
<TableCell>TODO Add Actions</TableCell>
|
||||
</TableRow>
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
<TableContainer component={Paper}>
|
||||
<Table>
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell>Host</TableCell>
|
||||
<TableCell>
|
||||
Status
|
||||
<span>
|
||||
<SouthRoundedIcon />
|
||||
</span>
|
||||
</TableCell>
|
||||
<TableCell>Response Time</TableCell>
|
||||
<TableCell>Actions</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>{mappedRows}</TableBody>
|
||||
<TableFooter>
|
||||
<TableRow>
|
||||
<TablePagination
|
||||
rowsPerPageOptions={[5, 10, 25]}
|
||||
count={monitors.length}
|
||||
rowsPerPage={rowsPerPage}
|
||||
page={page}
|
||||
onPageChange={handleChangePage}
|
||||
onRowsPerPageChange={handleChangeRowsPerPage}
|
||||
/>
|
||||
</TableRow>
|
||||
</TableFooter>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
);
|
||||
};
|
||||
|
||||
MonitorTable.propTypes = {
|
||||
monitors: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
};
|
||||
|
||||
Status.propTypes = { params: PropTypes.object.isRequired };
|
||||
Host.propTypes = { params: PropTypes.object.isRequired };
|
||||
|
||||
export default MonitorTable;
|
||||
@@ -24,3 +24,9 @@
|
||||
box-shadow: none;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
#menu-appbar svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
color: var(--env-var-color-25);
|
||||
}
|
||||
@@ -18,8 +18,18 @@ import { clearMonitorState } from "../../Features/Monitors/monitorsSlice";
|
||||
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import LockSvg from "../../assets/icons/lock.svg?react";
|
||||
import UserSvg from "../../assets/icons/user.svg?react";
|
||||
import TeamSvg from "../../assets/icons/user-two.svg?react";
|
||||
import LogoutSvg from "../../assets/icons/logout.svg?react";
|
||||
|
||||
const settings = ["Profile", "Team", "Invite Colleagues", "Logout"];
|
||||
const settings = ["Profile", "Password", "Team", "Logout"];
|
||||
const icons = {
|
||||
Profile: <UserSvg />,
|
||||
Team: <TeamSvg />,
|
||||
Password: <LockSvg />,
|
||||
Logout: <LogoutSvg />,
|
||||
};
|
||||
|
||||
/**
|
||||
* NavBar component
|
||||
@@ -71,8 +81,8 @@ function NavBar() {
|
||||
case "Team":
|
||||
navigate("/account/team");
|
||||
break;
|
||||
case "Invite Colleagues":
|
||||
console.log("Invite Colleagues");
|
||||
case "Password":
|
||||
navigate("/account/password");
|
||||
break;
|
||||
case "Logout":
|
||||
logout();
|
||||
@@ -184,10 +194,13 @@ function NavBar() {
|
||||
id="menu-item"
|
||||
key={setting}
|
||||
onClick={() => handleCloseUserMenu(setting)}
|
||||
sx={{ width: "150px" }}
|
||||
>
|
||||
{icons[setting]}
|
||||
<Typography
|
||||
fontSize="var(--env-var-font-size-medium)"
|
||||
textAlign="center"
|
||||
marginLeft="8px"
|
||||
>
|
||||
{setting}
|
||||
</Typography>
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
import TabPanel from "@mui/lab/TabPanel";
|
||||
import React, { useState } from "react";
|
||||
// import AnnouncementsDualButtonWithIcon from "../../Announcements/AnnouncementsDualButtonWithIcon/AnnouncementsDualButtonWithIcon";
|
||||
import AnnouncementsDualButtonWithIcon from "../../Toast/AnnouncementsDualButtonWithIcon/AnnouncementsDualButtonWithIcon";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { Box, Divider, Stack, Typography } from "@mui/material";
|
||||
import InfoOutlinedIcon from "@mui/icons-material/InfoOutlined";
|
||||
import WarningAmberOutlinedIcon from "@mui/icons-material/WarningAmberOutlined";
|
||||
import ButtonSpinner from "../../ButtonSpinner";
|
||||
import PasswordTextField from "../../TextFields/Password/PasswordTextField";
|
||||
import { editPasswordValidation } from "../../../Validation/validation";
|
||||
import Alert from "../../Alert";
|
||||
|
||||
/**
|
||||
* PasswordPanel component manages the form for editing password.
|
||||
@@ -96,13 +93,9 @@ const PasswordPanel = () => {
|
||||
spellCheck="false"
|
||||
>
|
||||
<div className="edit-password-form__wrapper">
|
||||
<AnnouncementsDualButtonWithIcon
|
||||
icon={
|
||||
<InfoOutlinedIcon
|
||||
style={{ fill: theme.palette.secondary.main }}
|
||||
/>
|
||||
}
|
||||
subject="SSO login"
|
||||
<Alert
|
||||
variant="info"
|
||||
title="SSO login"
|
||||
body="Since you logged in via SSO, you cannot reset or modify your password."
|
||||
/>
|
||||
</div>
|
||||
@@ -181,8 +174,8 @@ const PasswordPanel = () => {
|
||||
<div className="edit-password-form__wrapper">
|
||||
<Stack></Stack>
|
||||
<Box sx={{ flex: 1 }}>
|
||||
<AnnouncementsDualButtonWithIcon
|
||||
icon={<WarningAmberOutlinedIcon style={{ fill: "#f79009" }} />}
|
||||
<Alert
|
||||
variant="warning"
|
||||
body="New password must contain at least 8 characters and must have at least one uppercase letter, one number and one symbol."
|
||||
/>
|
||||
</Box>
|
||||
|
||||
@@ -28,8 +28,7 @@
|
||||
margin: 50px 0;
|
||||
}
|
||||
.account .MuiDivider-root,
|
||||
.account .MuiOutlinedInput-root fieldset,
|
||||
.account .announcement-tile {
|
||||
.account .MuiOutlinedInput-root fieldset {
|
||||
border-color: var(--env-var-color-29);
|
||||
}
|
||||
.account [class$="-form"] {
|
||||
@@ -42,9 +41,9 @@
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
}
|
||||
.edit-profile-form__wrapper .MuiStack-root:not(.row-stack),
|
||||
.edit-password-form__wrapper .MuiStack-root:not(.row-stack),
|
||||
.edit-organization-form__wrapper .MuiStack-root:not(.row-stack) {
|
||||
.edit-profile-form__wrapper>.MuiStack-root:not(.row-stack),
|
||||
.edit-password-form__wrapper>.MuiStack-root:not(.row-stack),
|
||||
.edit-organization-form__wrapper>.MuiStack-root:not(.row-stack) {
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
margin-right: 10px;
|
||||
@@ -74,36 +73,13 @@
|
||||
#input-team-member {
|
||||
padding: 10px;
|
||||
}
|
||||
.edit-password-form__wrapper > .announcement-tile {
|
||||
width: 100%;
|
||||
}
|
||||
.edit-password-form__wrapper
|
||||
> .announcement-tile
|
||||
.announcement-content-subject {
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
#edit-new-password + div > button > svg,
|
||||
#edit-confirm-password + div > button > svg,
|
||||
#edit-current-password + div > button > svg {
|
||||
color: var(--env-var-color-29);
|
||||
}
|
||||
.edit-password-form__wrapper .announcement-tile {
|
||||
margin: 0;
|
||||
}
|
||||
.edit-password-form__wrapper .announcement-tile .announcement-close {
|
||||
margin-left: auto;
|
||||
}
|
||||
.MuiBox-root > .announcement-tile {
|
||||
border-color: var(--env-var-color-27);
|
||||
background-color: var(--lighter-env-var-color-27);
|
||||
}
|
||||
.MuiBox-root > .announcement-tile .announcement-content-body {
|
||||
color: var(--env-var-color-28);
|
||||
}
|
||||
.MuiBox-root > .announcement-tile .announcement-close svg,
|
||||
.edit-password-form__wrapper > .announcement-tile .announcement-close svg {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
#org-name-flex-container .Mui-disabled {
|
||||
color: var(--env-var-color-2) !important;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
font-size: var(--env-var-font-size-large);
|
||||
}
|
||||
.create-monitor-form p.MuiTypography-root,
|
||||
.create-monitor-form button.MuiButtonBase-root,
|
||||
#monitor-frequencies {
|
||||
font-size: var(--env-var-font-size-medium);
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import { createMonitorValidation } from "../../Validation/validation";
|
||||
import { createMonitor } from "../../Features/Monitors/monitorsSlice";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import WestRoundedIcon from "@mui/icons-material/WestRounded";
|
||||
|
||||
const CreateNewMonitor = () => {
|
||||
const MS_PER_MINUTE = 60000;
|
||||
@@ -133,6 +134,20 @@ const CreateNewMonitor = () => {
|
||||
padding: `${theme.content.pY} ${theme.content.pX}`,
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
level="tertiary"
|
||||
label="Back"
|
||||
img={<WestRoundedIcon />}
|
||||
onClick={() => navigate("/monitors")}
|
||||
sx={{
|
||||
backgroundColor: "#f4f4f4",
|
||||
mb: theme.gap.medium,
|
||||
px: theme.gap.ml,
|
||||
"& svg.MuiSvgIcon-root": {
|
||||
pr: theme.gap.small,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
<Typography component="h1">Create new monitor</Typography>
|
||||
<div className="monitors-gaps-medium"></div>
|
||||
<ConfigBox
|
||||
@@ -326,7 +341,7 @@ const CreateNewMonitor = () => {
|
||||
MenuProps={{
|
||||
PaperProps: {
|
||||
style: {
|
||||
marginTop: "10px"
|
||||
marginTop: "10px",
|
||||
},
|
||||
},
|
||||
}}
|
||||
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
Tabs,
|
||||
Typography,
|
||||
Stack,
|
||||
Box,
|
||||
} from "@mui/material";
|
||||
import { ColoredLabel, StatusLabel } from "../../Components/Label/";
|
||||
import Avatar from "../../Components/Avatar/";
|
||||
@@ -38,6 +39,7 @@ import { getMonitors } from "../../Features/Monitors/monitorsSlice";
|
||||
import { getMonitorsByUserId } from "../../Features/Monitors/monitorsSlice";
|
||||
import ImageField from "../../Components/TextFields/Image";
|
||||
import ProgressUpload from "../../Components/ProgressBars";
|
||||
import Alert from "../../Components/Alert";
|
||||
|
||||
const cols = [
|
||||
{
|
||||
@@ -426,6 +428,29 @@ const Demo = () => {
|
||||
<ProgressUpload icon={<ImageIcon />} label="image.jpg" size="2 MB" />
|
||||
</Stack>
|
||||
<Divider sx={{ margin: `${theme.spacing(2)}` }} />
|
||||
<Stack justifyContent="center" alignItems="center">
|
||||
<Box width="500px">
|
||||
<Alert
|
||||
variant="info"
|
||||
title="SSO login"
|
||||
body="Since you logged in via SSO, you cannot reset or modify your password."
|
||||
/>
|
||||
</Box>
|
||||
<Box width="500px" mt="5px">
|
||||
<Alert
|
||||
variant="warning"
|
||||
body="New password must contain at least 8 characters and must have at least one uppercase letter, one number and one symbol."
|
||||
/>
|
||||
</Box>
|
||||
<Box width="500px" mt="5px">
|
||||
<Alert
|
||||
variant="error"
|
||||
title="Error"
|
||||
body="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
|
||||
/>
|
||||
</Box>
|
||||
</Stack>
|
||||
<Divider sx={{ margin: `${theme.spacing(2)}` }} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -41,13 +41,13 @@
|
||||
|
||||
#login-email-input {
|
||||
width: 308px;
|
||||
height: 11px;
|
||||
height: 1px;
|
||||
font-size: var(--env-var-font-size-medium);
|
||||
}
|
||||
|
||||
#login-password-input {
|
||||
width: 308px;
|
||||
height: 11px;
|
||||
height: 1px;
|
||||
font-size: var(--env-var-font-size-medium);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
.maintenance-checklist-main {
|
||||
max-width: 350px;
|
||||
min-height: 390px;
|
||||
margin: auto;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.maintenance-image {
|
||||
width: 280px;
|
||||
height: 150px;
|
||||
background-color: whitesmoke;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.maintenance-title {
|
||||
color: var(--env-var-color-2);
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
margin-top: 40px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.checklist-item {
|
||||
font-size: 13px;
|
||||
color: var(--env-var-color-2);
|
||||
display: flex;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.checklist-item-text {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.maintenance-checklist-main .maintenance-checklist-button {
|
||||
margin-top: 30px;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
import React from "react";
|
||||
import "./index.css";
|
||||
import WindowFrame from "./../../assets/Images/maintenance_window_frame.svg";
|
||||
import { Button } from "@mui/material";
|
||||
import CheckCircleOutlineIcon from "@mui/icons-material/CheckCircleOutline";
|
||||
|
||||
const Maintenance = () => {
|
||||
const maintenanceItems = [
|
||||
{ id: 1, text: "Mark your maintenance periods" },
|
||||
{ id: 2, text: "Eliminate any misunderstandings" },
|
||||
{ id: 3, text: "Stop sending alerts in maintenance windows" },
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="maintenance-checklist-main">
|
||||
<img className="maintenance-image" src={WindowFrame} alt="WindowFrame" />
|
||||
<div className="maintenance-title">Create a maintenance window to</div>
|
||||
<div>
|
||||
{maintenanceItems.map((item) => (
|
||||
<div key={item.id} className="checklist-item">
|
||||
<CheckCircleOutlineIcon color="primary" />
|
||||
<div className="checklist-item-text">{item.text}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
className="maintenance-checklist-button"
|
||||
sx={{ textTransform: "none" }}
|
||||
>
|
||||
Let's create your maintenance window
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Maintenance;
|
||||
@@ -1,7 +1,6 @@
|
||||
.monitors,
|
||||
.new-monitor {
|
||||
width: 70vw;
|
||||
padding: 4vw;
|
||||
}
|
||||
|
||||
.monitors {
|
||||
@@ -9,13 +8,13 @@
|
||||
}
|
||||
|
||||
.monitors-bar {
|
||||
margin-top: calc(2 * var(--env-var-spacing-2));
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.monitors-bar-title {
|
||||
color: var(--env-var-color-1);
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
@@ -7,10 +7,11 @@ import { useNavigate } from "react-router-dom";
|
||||
import Button from "../../Components/Button";
|
||||
import ServerStatus from "../../Components/Charts/Servers/ServerStatus";
|
||||
import SearchTextField from "../../Components/TextFields/Search/SearchTextField";
|
||||
import HostsTable from "../../Components/HostsTable";
|
||||
import Pagination from "../../Components/Pagination";
|
||||
import MonitorTable from "../../Components/MonitorTable";
|
||||
import { useTheme } from "@emotion/react";
|
||||
|
||||
const Monitors = () => {
|
||||
const theme = useTheme();
|
||||
const navigate = useNavigate();
|
||||
const monitorState = useSelector((state) => state.monitors);
|
||||
const authState = useSelector((state) => state.auth);
|
||||
@@ -25,9 +26,13 @@ const Monitors = () => {
|
||||
}, 0);
|
||||
|
||||
const down = monitorState.monitors.length - up;
|
||||
|
||||
return (
|
||||
<div className="monitors">
|
||||
<div
|
||||
className="monitors"
|
||||
style={{
|
||||
padding: `${theme.content.pY} ${theme.content.pX}`,
|
||||
}}
|
||||
>
|
||||
<div className="monitors-bar">
|
||||
<div className="monitors-bar-title">
|
||||
Hello, {authState.user.firstname}
|
||||
@@ -38,7 +43,7 @@ const Monitors = () => {
|
||||
onClick={() => {
|
||||
navigate("/monitors/create");
|
||||
}}
|
||||
sx={{ padding: "10px 20px", fontSize: "13px" }}
|
||||
sx={{ padding: "6px 25px", fontSize: "13px" }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -60,10 +65,9 @@ const Monitors = () => {
|
||||
<SearchTextField />
|
||||
</div>
|
||||
</div>
|
||||
<div className="monitors-v-gaping"></div>
|
||||
<HostsTable monitors={monitorState.monitors} />
|
||||
<div className="monitors-v-gaping"></div>
|
||||
<Pagination />
|
||||
<div className="monitors-v-gaping" />
|
||||
<MonitorTable monitors={monitorState.monitors} />
|
||||
<div className="monitors-v-gaping" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
.current-monitors-title-holder {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.current-monitors-bar {
|
||||
@@ -18,16 +19,22 @@
|
||||
font-size: 1rem;
|
||||
font-weight: bold;
|
||||
margin-right: var(--env-var-spacing-1);
|
||||
color: var(--env-var-color-1);
|
||||
}
|
||||
|
||||
.current-monitors-counter {
|
||||
width: var(--env-var-spacing-2);
|
||||
height: var(--env-var-spacing-2);
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 2px;
|
||||
min-width: 22px;
|
||||
min-height: 22px;
|
||||
background-color: var(--env-var-color-15);
|
||||
border: 1px solid var(--env-var-color-6);
|
||||
border-radius: 50%;
|
||||
text-align: center;
|
||||
align-items: center;
|
||||
font-size: var(--env-var-font-size-medium);
|
||||
font-weight: 500;
|
||||
color: var(--env-var-color-5);
|
||||
}
|
||||
|
||||
.monitors-v-gaping {
|
||||
@@ -66,24 +73,6 @@
|
||||
font-size: var(--env-var-font-size-medium);
|
||||
}
|
||||
|
||||
.host-list-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.host-list-item-open {
|
||||
width: var(--env-var-img-width-2);
|
||||
height: var(--env-var-img-width-2);
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.host-list-item-name {
|
||||
font-size: var(--env-var-font-size-medium);
|
||||
font-weight: bold;
|
||||
margin-right: var(--env-var-spacing-1);
|
||||
}
|
||||
|
||||
.host-list-item-precentage {
|
||||
font-size: var(--env-var-font-size-medium);
|
||||
}
|
||||
@@ -101,13 +90,6 @@
|
||||
padding: calc(var(--env-var-spacing-1) / 2);
|
||||
}
|
||||
|
||||
.host-status-box-circle {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border-radius: 50%;
|
||||
margin-right: calc(var(--env-var-spacing-1) / 2);
|
||||
}
|
||||
|
||||
.host-actions {
|
||||
margin: auto;
|
||||
cursor: pointer;
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import React from 'react'
|
||||
import React from "react";
|
||||
|
||||
const Status = () => {
|
||||
return (
|
||||
<div>Status</div>
|
||||
)
|
||||
}
|
||||
return <div>Status</div>;
|
||||
};
|
||||
|
||||
export default Status
|
||||
export default Status;
|
||||
@@ -1,9 +1,10 @@
|
||||
const pathMap = {
|
||||
"/monitors": "Monitors",
|
||||
"/incidents": "Incidents",
|
||||
"/status" : "Status Pages",
|
||||
"/integrations": "Integrations",
|
||||
"/settings" : "Settings"
|
||||
}
|
||||
"/monitors": "Monitors",
|
||||
"/incidents": "Incidents",
|
||||
"/status": "Status Pages",
|
||||
"/integrations": "Integrations",
|
||||
"/maintenance": "maintenance",
|
||||
"/settings": "Settings",
|
||||
};
|
||||
|
||||
export default pathMap;
|
||||
export default pathMap;
|
||||
@@ -88,14 +88,32 @@ const theme = createTheme({
|
||||
},
|
||||
content: {
|
||||
pX: "80px",
|
||||
pY: "40px"
|
||||
pY: "40px",
|
||||
},
|
||||
gap: {
|
||||
small: "8px",
|
||||
medium: "12px",
|
||||
ml: "16px",
|
||||
large: "24px",
|
||||
xl: "40px"
|
||||
}
|
||||
xl: "40px",
|
||||
},
|
||||
alert: {
|
||||
info: {
|
||||
color: secondaryMain,
|
||||
bg: otherColorsWhite,
|
||||
border: "#d0d5dd",
|
||||
},
|
||||
error: {
|
||||
color: "#d92d20",
|
||||
bg: "hsla(0, 100%, 52%, 0.03)",
|
||||
border: "#f04438",
|
||||
},
|
||||
warning: {
|
||||
color: "#f79009",
|
||||
bg: "#fffaef",
|
||||
border: "#fecf60"
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default theme;
|
||||
|
After Width: | Height: | Size: 744 B |
@@ -0,0 +1,9 @@
|
||||
<svg width="256" height="136" viewBox="0 0 256 136" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="0.390244" y="0.390244" width="255.22" height="135.22" rx="7.41463" fill="white"/>
|
||||
<rect x="0.390244" y="0.390244" width="255.22" height="135.22" rx="7.41463" stroke="#EBEBEB" stroke-width="0.780488"/>
|
||||
<rect x="17.9512" y="16.3901" width="220.098" height="54.6341" rx="3.12195" fill="#EFF2FF"/>
|
||||
<rect x="17.9512" y="78.8293" width="85.0732" height="9.36585" rx="3.12195" fill="#D9D9D9"/>
|
||||
<rect x="111" y="79" width="127" height="9" rx="3.12195" fill="#F3F3F3"/>
|
||||
<rect width="85" height="9" rx="3.12195" transform="matrix(-1 0 0 1 238 98)" fill="#D9D9D9"/>
|
||||
<rect width="127" height="9" rx="3.12195" transform="matrix(-1 0 0 1 145 98)" fill="#F3F3F3"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 766 B |
@@ -0,0 +1,3 @@
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10.3337 5.66667V4.33333C10.3337 2.49238 8.84127 1 7.00033 1C5.15938 1 3.66699 2.49238 3.66699 4.33333V5.66667M7.00033 8.66667V10M4.86699 13H9.13366C10.2538 13 10.8138 13 11.2416 12.782C11.618 12.5903 11.9239 12.2843 12.1157 11.908C12.3337 11.4802 12.3337 10.9201 12.3337 9.8V8.86667C12.3337 7.74656 12.3337 7.18651 12.1157 6.75869C11.9239 6.38236 11.618 6.0764 11.2416 5.88465C10.8138 5.66667 10.2538 5.66667 9.13366 5.66667H4.86699C3.74689 5.66667 3.18683 5.66667 2.75901 5.88465C2.38269 6.0764 2.07673 6.38236 1.88498 6.75869C1.66699 7.18651 1.66699 7.74656 1.66699 8.86667V9.8C1.66699 10.9201 1.66699 11.4802 1.88498 11.908C2.07673 12.2843 2.38269 12.5903 2.75901 12.782C3.18683 13 3.74689 13 4.86699 13Z" stroke="#667085" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 907 B |
@@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10.6667 11.3333L14 8M14 8L10.6667 4.66667M14 8H6M6 2H5.2C4.0799 2 3.51984 2 3.09202 2.21799C2.7157 2.40973 2.40973 2.71569 2.21799 3.09202C2 3.51984 2 4.07989 2 5.2V10.8C2 11.9201 2 12.4802 2.21799 12.908C2.40973 13.2843 2.71569 13.5903 3.09202 13.782C3.51984 14 4.0799 14 5.2 14H6" stroke="#667085" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 481 B |
@@ -0,0 +1,3 @@
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M13 5L13 1M13 1H9M13 1L7.66667 6.33333M5.66667 2.33333H4.2C3.0799 2.33333 2.51984 2.33333 2.09202 2.55132C1.71569 2.74307 1.40973 3.04903 1.21799 3.42535C1 3.85318 1 4.41323 1 5.53333V9.8C1 10.9201 1 11.4802 1.21799 11.908C1.40973 12.2843 1.71569 12.5903 2.09202 12.782C2.51984 13 3.0799 13 4.2 13H8.46667C9.58677 13 10.1468 13 10.5746 12.782C10.951 12.5903 11.2569 12.2843 11.4487 11.908C11.6667 11.4802 11.6667 10.9201 11.6667 9.8V8.33333" stroke="#667085" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 620 B |
@@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M14.6663 14V12.6667C14.6663 11.4241 13.8165 10.38 12.6663 10.084M10.333 2.19384C11.3103 2.58943 11.9997 3.54754 11.9997 4.66667C11.9997 5.78579 11.3103 6.7439 10.333 7.13949M11.333 14C11.333 12.7575 11.333 12.1362 11.13 11.6462C10.8594 10.9928 10.3402 10.4736 9.68683 10.203C9.19677 10 8.57552 10 7.33301 10H5.33301C4.0905 10 3.46924 10 2.97919 10.203C2.32578 10.4736 1.80665 10.9928 1.536 11.6462C1.33301 12.1362 1.33301 12.7575 1.33301 14M8.99967 4.66667C8.99967 6.13943 7.80577 7.33333 6.33301 7.33333C4.86025 7.33333 3.66634 6.13943 3.66634 4.66667C3.66634 3.19391 4.86025 2 6.33301 2C7.80577 2 8.99967 3.19391 8.99967 4.66667Z" stroke="#667085" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 830 B |
@@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M13.3337 14C13.3337 13.0696 13.3337 12.6044 13.2188 12.2259C12.9603 11.3736 12.2934 10.7067 11.4411 10.4482C11.0626 10.3333 10.5974 10.3333 9.66699 10.3333H6.33366C5.40328 10.3333 4.93809 10.3333 4.55956 10.4482C3.7073 10.7067 3.04035 11.3736 2.78182 12.2259C2.66699 12.6044 2.66699 13.0696 2.66699 14M11.0003 5C11.0003 6.65685 9.65718 8 8.00033 8C6.34347 8 5.00033 6.65685 5.00033 5C5.00033 3.34315 6.34347 2 8.00033 2C9.65718 2 11.0003 3.34315 11.0003 5Z" stroke="#667085" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 655 B |
@@ -1,9 +1,10 @@
|
||||
import { defineConfig } from 'vite'
|
||||
import react from '@vitejs/plugin-react'
|
||||
import svgr from 'vite-plugin-svgr';
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
plugins: [svgr(), react()],
|
||||
optimizeDeps: {
|
||||
include: ['@mui/material/Tooltip', '@emotion/styled'],
|
||||
},
|
||||
|
||||
@@ -7,6 +7,7 @@ const {
|
||||
recoveryValidation,
|
||||
recoveryTokenValidation,
|
||||
newPasswordValidation,
|
||||
deleteUserParamValidation,
|
||||
} = require("../validation/joi");
|
||||
const logger = require("../utils/logger");
|
||||
require("dotenv").config();
|
||||
@@ -58,6 +59,7 @@ const registerController = async (req, res, next) => {
|
||||
|
||||
const userForToken = { ...newUser._doc };
|
||||
delete userForToken.profileImage;
|
||||
delete userForToken.avatarImage;
|
||||
|
||||
const token = issueToken(userForToken);
|
||||
|
||||
@@ -261,6 +263,85 @@ const resetPasswordController = async (req, res, next) => {
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Deletes a user and all associated monitors, checks, and alerts.
|
||||
*
|
||||
* @param {Object} req - The request object.
|
||||
* @param {Object} res - The response object.
|
||||
* @param {Function} next - The next middleware function.
|
||||
* @returns {Object} The response object with success status and message.
|
||||
* @throws {Error} If user validation fails or user is not found in the database.
|
||||
*/
|
||||
const deleteUserController = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.headers.authorization.split(" ")[1];
|
||||
const decodedToken = jwt.decode(token);
|
||||
const { _id, email } = decodedToken;
|
||||
|
||||
const decodedTokenCastedAsRequest = {
|
||||
params: {
|
||||
userId: _id,
|
||||
},
|
||||
body: {
|
||||
email,
|
||||
},
|
||||
};
|
||||
|
||||
// Validate user
|
||||
await deleteUserParamValidation.validateAsync(
|
||||
decodedTokenCastedAsRequest.body
|
||||
);
|
||||
|
||||
// Check if the user exists
|
||||
const user = await req.db.getUserByEmail(decodedTokenCastedAsRequest);
|
||||
if (!user) {
|
||||
throw new Error(errorMessages.DB_USER_NOT_FOUND);
|
||||
}
|
||||
|
||||
// 1. Find all the monitors associated with the user id
|
||||
const monitors = await req.db.getMonitorsByUserId(
|
||||
decodedTokenCastedAsRequest
|
||||
);
|
||||
|
||||
if (monitors) {
|
||||
// 2. Delete jobs associated with each monitor
|
||||
for (const monitor of monitors) {
|
||||
await req.jobQueue.deleteJob(monitor);
|
||||
}
|
||||
|
||||
// 3. Delete all checks associated with each monitor
|
||||
for (const monitor of monitors) {
|
||||
await req.db.deleteChecks(monitor._id);
|
||||
}
|
||||
|
||||
// 4. Delete all alerts associated with each monitor
|
||||
for (const monitor of monitors) {
|
||||
await req.db.deleteAlertByMonitorId(monitor._id);
|
||||
}
|
||||
|
||||
// 5. Delete each monitor
|
||||
await req.db.deleteMonitorsByUserId(user._id);
|
||||
|
||||
// 6. Delete the user by id
|
||||
await req.db.deleteUser(decodedTokenCastedAsRequest);
|
||||
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.AUTH_DELETE_USER,
|
||||
});
|
||||
} else {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
msg: errorMessages.MONITOR_GET_BY_USER_ID,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
error.service = SERVICE_NAME;
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
registerController,
|
||||
loginController,
|
||||
@@ -269,4 +350,5 @@ module.exports = {
|
||||
recoveryRequestController,
|
||||
validateRecoveryTokenController,
|
||||
resetPasswordController,
|
||||
deleteUserController,
|
||||
};
|
||||
@@ -8,6 +8,7 @@ const crypto = require("crypto");
|
||||
const DUPLICATE_KEY_CODE = 11000; // MongoDB error code for duplicate key
|
||||
const { errorMessages, successMessages } = require("../utils/messages");
|
||||
const { error } = require("console");
|
||||
const { GenerateAvatarImage } = require("../utils/imageProcessing");
|
||||
const connect = async () => {
|
||||
try {
|
||||
await mongoose.connect(process.env.DB_CONNECTION_STRING);
|
||||
@@ -33,12 +34,16 @@ const connect = async () => {
|
||||
const insertUser = async (req, res) => {
|
||||
try {
|
||||
const userData = { ...req.body };
|
||||
console.log(req.file);
|
||||
if (req.file) {
|
||||
// 1. Save the full size image
|
||||
userData.profileImage = {
|
||||
data: req.file.buffer,
|
||||
contentType: req.file.mimetype,
|
||||
};
|
||||
|
||||
// 2. Get the avatar sized image
|
||||
const avatar = await GenerateAvatarImage(req.file);
|
||||
userData.avatarImage = avatar;
|
||||
}
|
||||
const newUser = new UserModel(userData);
|
||||
await newUser.save();
|
||||
@@ -96,10 +101,15 @@ const updateUser = async (req, res) => {
|
||||
try {
|
||||
const candidateUser = { ...req.body };
|
||||
if (req.file) {
|
||||
// 1. Save the full size image
|
||||
candidateUser.profileImage = {
|
||||
data: req.file.buffer,
|
||||
contentType: req.file.mimetype,
|
||||
};
|
||||
|
||||
// 2. Get the avaatar sized image
|
||||
const avatar = await GenerateAvatarImage(req.file);
|
||||
candidateUser.avatarImage = avatar;
|
||||
}
|
||||
|
||||
const updatedUser = await UserModel.findByIdAndUpdate(
|
||||
@@ -115,6 +125,27 @@ const updateUser = async (req, res) => {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Delete a user by ID
|
||||
* @async
|
||||
* @param {Express.Request} req
|
||||
* @param {Express.Response} res
|
||||
* @returns {Promise<UserModel>}
|
||||
* @throws {Error}
|
||||
*/
|
||||
const deleteUser = async (req, res) => {
|
||||
const userId = req.params.userId;
|
||||
try {
|
||||
const deletedUser = await UserModel.findByIdAndDelete(userId);
|
||||
if (!deletedUser) {
|
||||
throw new Error(errorMessages.DB_USER_NOT_FOUND);
|
||||
}
|
||||
return deletedUser;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Request a recovery token
|
||||
* @async
|
||||
@@ -319,6 +350,21 @@ const deleteAllMonitors = async (req, res) => {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Delete all monitors associated with a user ID
|
||||
* @async
|
||||
* @param {string} userId - The ID of the user whose monitors are to be deleted.
|
||||
* @returns {Promise} A promise that resolves when the operation is complete.
|
||||
*/
|
||||
const deleteMonitorsByUserId = async (userId) => {
|
||||
try {
|
||||
const result = await Monitor.deleteMany({ userId: userId });
|
||||
return result;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Edit a monitor by ID
|
||||
* @async
|
||||
@@ -520,6 +566,13 @@ const deleteAlert = async (alertId) => {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Deletes alerts by monitor ID.
|
||||
*
|
||||
* @param {string} monitorId - The ID of the monitor.
|
||||
* @returns {Promise} A promise that resolves to the result of the delete operation.
|
||||
* @throws {Error} If an error occurs while deleting the alerts.
|
||||
*/
|
||||
const deleteAlertByMonitorId = async (monitorId) => {
|
||||
try {
|
||||
const result = await Alert.deleteMany({ monitorId });
|
||||
@@ -534,6 +587,7 @@ module.exports = {
|
||||
insertUser,
|
||||
getUserByEmail,
|
||||
updateUser,
|
||||
deleteUser,
|
||||
requestRecoveryToken,
|
||||
validateRecoveryToken,
|
||||
resetPassword,
|
||||
@@ -555,4 +609,5 @@ module.exports = {
|
||||
editAlert,
|
||||
deleteAlert,
|
||||
deleteAlertByMonitorId,
|
||||
deleteMonitorsByUserId,
|
||||
};
|
||||
@@ -20,6 +20,9 @@ const UserSchema = mongoose.Schema(
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
avatarImage: {
|
||||
type: String,
|
||||
},
|
||||
profileImage: {
|
||||
data: Buffer,
|
||||
contentType: String,
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
"mongoose": "^8.3.3",
|
||||
"multer": "1.4.5-lts.1",
|
||||
"ping": "0.4.4",
|
||||
"sharp": "0.33.4",
|
||||
"winston": "^3.13.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
const router = require("express").Router();
|
||||
const { verifyJWT } = require("../middleware/verifyJWT");
|
||||
const { verifyOwnership } = require("../middleware/verifyOwnership");
|
||||
const multer = require("multer");
|
||||
const upload = multer();
|
||||
const User = require("../models/user");
|
||||
|
||||
const {
|
||||
registerController,
|
||||
@@ -11,6 +13,7 @@ const {
|
||||
validateRecoveryTokenController,
|
||||
resetPasswordController,
|
||||
checkAdminController,
|
||||
deleteUserController
|
||||
} = require("../controllers/authController");
|
||||
|
||||
//Auth routes
|
||||
@@ -23,6 +26,7 @@ router.post(
|
||||
userEditController
|
||||
);
|
||||
router.get("/users/admin", checkAdminController);
|
||||
router.delete("/user/:userId", verifyJWT, verifyOwnership(User, "userId") , deleteUserController);
|
||||
|
||||
//Recovery routes
|
||||
router.post("/recovery/request", recoveryRequestController);
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
const sharp = require("sharp");
|
||||
/**
|
||||
* Generates a 64 * 64 pixel image from a given image
|
||||
* @param {} file
|
||||
*/
|
||||
const GenerateAvatarImage = async (file) => {
|
||||
try {
|
||||
// Resize to target 64 * 64
|
||||
let resizedImageBuffer = await sharp(file.buffer)
|
||||
.resize({
|
||||
width: 64,
|
||||
height: 64,
|
||||
fit: "cover",
|
||||
})
|
||||
.toBuffer();
|
||||
|
||||
//Get b64 string
|
||||
const base64Image = resizedImageBuffer.toString("base64");
|
||||
return base64Image;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
GenerateAvatarImage,
|
||||
};
|
||||
@@ -57,6 +57,7 @@ const successMessages = {
|
||||
AUTH_VERIFY_RECOVERY_TOKEN: "Recovery token verified successfully",
|
||||
AUTH_RESET_PASSWORD: "Password reset successfully",
|
||||
AUTH_ADMIN_CHECK: "Admin check completed successfully",
|
||||
AUTH_DELETE_USER: "User deleted successfully",
|
||||
|
||||
// Check Controller
|
||||
CHECK_CREATE: "Check created successfully",
|
||||
|
||||
@@ -46,6 +46,10 @@ const newPasswordValidation = joi.object({
|
||||
confirm: joi.string(),
|
||||
});
|
||||
|
||||
const deleteUserParamValidation = joi.object({
|
||||
email: joi.string().email().required(),
|
||||
});
|
||||
|
||||
//****************************************
|
||||
// Monitors
|
||||
//****************************************
|
||||
@@ -161,4 +165,5 @@ module.exports = {
|
||||
createCheckBodyValidation,
|
||||
getChecksParamValidation,
|
||||
deleteChecksParamValidation,
|
||||
deleteUserParamValidation
|
||||
};
|
||||