Compare commits
4 Commits
d293ca6981
...
50cf87380d
| Author | SHA1 | Date | |
|---|---|---|---|
| 50cf87380d | |||
| 5fcadb9fc8 | |||
| 6fb615a743 | |||
| f5fd1fc605 |
@@ -10,7 +10,7 @@
|
|||||||
{"type": "test", "section": "📝 Testing Code"},
|
{"type": "test", "section": "📝 Testing Code"},
|
||||||
{"type": "ci", "section": "📈 Project changes"}
|
{"type": "ci", "section": "📈 Project changes"}
|
||||||
],
|
],
|
||||||
"commitUrlFormat": "https://git.tuffraid.net/cowch/lstV2/commits{{hash}}",
|
"commitUrlFormat": "https://git.tuffraid.net/cowch/lstV2/commits/{{hash}}",
|
||||||
"compareUrlFormat": "https://git.tuffraid.net/cowch/lstV2/compare/{{previousTag}}...{{currentTag}}",
|
"compareUrlFormat": "https://git.tuffraid.net/cowch/lstV2/compare/{{previousTag}}...{{currentTag}}",
|
||||||
"header": "# All CHanges to LST can be found below.\n"
|
"header": "# All CHanges to LST can be found below.\n"
|
||||||
}
|
}
|
||||||
|
|||||||
65
frontend/package-lock.json
generated
65
frontend/package-lock.json
generated
@@ -381,6 +381,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"ppc64"
|
"ppc64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -397,6 +398,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -413,6 +415,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -429,6 +432,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -445,6 +449,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -461,6 +466,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -477,6 +483,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -493,6 +500,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -509,6 +517,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -525,6 +534,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -541,6 +551,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"ia32"
|
"ia32"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -557,6 +568,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"loong64"
|
"loong64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -573,6 +585,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"mips64el"
|
"mips64el"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -589,6 +602,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"ppc64"
|
"ppc64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -605,6 +619,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"riscv64"
|
"riscv64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -621,6 +636,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"s390x"
|
"s390x"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -637,6 +653,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -653,6 +670,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -669,6 +687,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -685,6 +704,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -701,6 +721,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -717,6 +738,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -733,6 +755,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -749,6 +772,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"ia32"
|
"ia32"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -765,6 +789,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -1883,6 +1908,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -1896,6 +1922,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -1909,6 +1936,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -1922,6 +1950,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -1935,6 +1964,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -1948,6 +1978,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -1961,6 +1992,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -1974,6 +2006,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -1987,6 +2020,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -2000,6 +2034,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -2013,6 +2048,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"loong64"
|
"loong64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -2026,6 +2062,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"ppc64"
|
"ppc64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -2039,6 +2076,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"riscv64"
|
"riscv64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -2052,6 +2090,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"s390x"
|
"s390x"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -2065,6 +2104,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -2078,6 +2118,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -2091,6 +2132,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -2104,6 +2146,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"ia32"
|
"ia32"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -2117,6 +2160,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -2918,6 +2962,7 @@
|
|||||||
"version": "1.0.6",
|
"version": "1.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
|
||||||
"integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
|
"integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@types/json-schema": {
|
"node_modules/@types/json-schema": {
|
||||||
@@ -2931,7 +2976,7 @@
|
|||||||
"version": "19.0.10",
|
"version": "19.0.10",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.0.10.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.0.10.tgz",
|
||||||
"integrity": "sha512-JuRQ9KXLEjaUNjTWpzuR231Z2WpIwczOkBEIvbHNCzQefFIT0L8IqE6NV6ULLyC1SI/i234JnDoMkfg+RjQj2g==",
|
"integrity": "sha512-JuRQ9KXLEjaUNjTWpzuR231Z2WpIwczOkBEIvbHNCzQefFIT0L8IqE6NV6ULLyC1SI/i234JnDoMkfg+RjQj2g==",
|
||||||
"devOptional": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"csstype": "^3.0.2"
|
"csstype": "^3.0.2"
|
||||||
@@ -2941,7 +2986,7 @@
|
|||||||
"version": "19.0.4",
|
"version": "19.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.0.4.tgz",
|
||||||
"integrity": "sha512-4fSQ8vWFkg+TGhePfUzVmat3eC14TXYSsiiDSLI0dVLsrm9gZFABjPy/Qu6TKgl1tq1Bu1yDsuQgY3A3DOjCcg==",
|
"integrity": "sha512-4fSQ8vWFkg+TGhePfUzVmat3eC14TXYSsiiDSLI0dVLsrm9gZFABjPy/Qu6TKgl1tq1Bu1yDsuQgY3A3DOjCcg==",
|
||||||
"devOptional": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@types/react": "^19.0.0"
|
"@types/react": "^19.0.0"
|
||||||
@@ -3531,7 +3576,7 @@
|
|||||||
"version": "3.1.3",
|
"version": "3.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
|
||||||
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
|
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
|
||||||
"devOptional": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/debug": {
|
"node_modules/debug": {
|
||||||
@@ -3632,6 +3677,7 @@
|
|||||||
"version": "0.25.0",
|
"version": "0.25.0",
|
||||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.0.tgz",
|
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.0.tgz",
|
||||||
"integrity": "sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw==",
|
"integrity": "sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw==",
|
||||||
|
"dev": true,
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"bin": {
|
"bin": {
|
||||||
@@ -4003,6 +4049,7 @@
|
|||||||
"version": "2.3.3",
|
"version": "2.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||||
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
|
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
|
||||||
|
"dev": true,
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
@@ -4036,7 +4083,7 @@
|
|||||||
"version": "4.10.0",
|
"version": "4.10.0",
|
||||||
"resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.0.tgz",
|
"resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.0.tgz",
|
||||||
"integrity": "sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==",
|
"integrity": "sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==",
|
||||||
"devOptional": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"resolve-pkg-maps": "^1.0.0"
|
"resolve-pkg-maps": "^1.0.0"
|
||||||
@@ -4724,6 +4771,7 @@
|
|||||||
"version": "3.3.8",
|
"version": "3.3.8",
|
||||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz",
|
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz",
|
||||||
"integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==",
|
"integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==",
|
||||||
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "github",
|
"type": "github",
|
||||||
@@ -4868,6 +4916,7 @@
|
|||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
|
||||||
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
|
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
|
||||||
|
"dev": true,
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/picomatch": {
|
"node_modules/picomatch": {
|
||||||
@@ -4887,6 +4936,7 @@
|
|||||||
"version": "8.5.3",
|
"version": "8.5.3",
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz",
|
||||||
"integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==",
|
"integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==",
|
||||||
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "opencollective",
|
"type": "opencollective",
|
||||||
@@ -5178,7 +5228,7 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
|
||||||
"integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
|
"integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
|
||||||
"devOptional": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
|
"url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
|
||||||
@@ -5199,6 +5249,7 @@
|
|||||||
"version": "4.34.8",
|
"version": "4.34.8",
|
||||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.8.tgz",
|
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.8.tgz",
|
||||||
"integrity": "sha512-489gTVMzAYdiZHFVA/ig/iYFllCcWFHMvUHI1rpFmkoUtRlQxqh6/yiNqnYibjMZ2b/+FUQwldG+aLsEt6bglQ==",
|
"integrity": "sha512-489gTVMzAYdiZHFVA/ig/iYFllCcWFHMvUHI1rpFmkoUtRlQxqh6/yiNqnYibjMZ2b/+FUQwldG+aLsEt6bglQ==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/estree": "1.0.6"
|
"@types/estree": "1.0.6"
|
||||||
@@ -5332,6 +5383,7 @@
|
|||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
||||||
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
|
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
|
||||||
|
"dev": true,
|
||||||
"license": "BSD-3-Clause",
|
"license": "BSD-3-Clause",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
@@ -5445,7 +5497,7 @@
|
|||||||
"version": "4.19.3",
|
"version": "4.19.3",
|
||||||
"resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.3.tgz",
|
"resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.3.tgz",
|
||||||
"integrity": "sha512-4H8vUNGNjQ4V2EOoGw005+c+dGuPSnhpPBPHBtsZdGZBk/iJb4kguGlPWaZTZ3q5nMtFOEsY0nRDlh9PJyd6SQ==",
|
"integrity": "sha512-4H8vUNGNjQ4V2EOoGw005+c+dGuPSnhpPBPHBtsZdGZBk/iJb4kguGlPWaZTZ3q5nMtFOEsY0nRDlh9PJyd6SQ==",
|
||||||
"devOptional": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"esbuild": "~0.25.0",
|
"esbuild": "~0.25.0",
|
||||||
@@ -5622,6 +5674,7 @@
|
|||||||
"version": "6.2.0",
|
"version": "6.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/vite/-/vite-6.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/vite/-/vite-6.2.0.tgz",
|
||||||
"integrity": "sha512-7dPxoo+WsT/64rDcwoOjk76XHj+TqNTIvHKcuMQ1k4/SeHDaQt5GFAeLYzrimZrMpn/O6DtdI03WUjdxuPM0oQ==",
|
"integrity": "sha512-7dPxoo+WsT/64rDcwoOjk76XHj+TqNTIvHKcuMQ1k4/SeHDaQt5GFAeLYzrimZrMpn/O6DtdI03WUjdxuPM0oQ==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"esbuild": "^0.25.0",
|
"esbuild": "^0.25.0",
|
||||||
|
|||||||
121
frontend/src/components/admin/settings/SettingForm.tsx
Normal file
121
frontend/src/components/admin/settings/SettingForm.tsx
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
import {Button} from "@/components/ui/button";
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogDescription,
|
||||||
|
DialogFooter,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
DialogTrigger,
|
||||||
|
} from "@/components/ui/dialog";
|
||||||
|
import {Input} from "@/components/ui/input";
|
||||||
|
import {Label} from "@/components/ui/label";
|
||||||
|
import {Settings} from "./SettingsPage";
|
||||||
|
import {toast} from "sonner";
|
||||||
|
import {useState} from "react";
|
||||||
|
import {useForm} from "react-hook-form";
|
||||||
|
import {z} from "zod";
|
||||||
|
import {zodResolver} from "@hookform/resolvers/zod";
|
||||||
|
import {useQuery} from "@tanstack/react-query";
|
||||||
|
import {getSettings} from "@/utils/querys/settings";
|
||||||
|
import {useSessionStore} from "@/lib/store/sessionStore";
|
||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
const FormSchema = z.object({
|
||||||
|
value: z.string().min(1, "You must enter a value greater than 0"),
|
||||||
|
});
|
||||||
|
export function ChangeSetting({setting}: {setting: Settings}) {
|
||||||
|
const {token} = useSessionStore();
|
||||||
|
const {refetch} = useQuery(getSettings(token ?? ""));
|
||||||
|
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
const [saving, setSaving] = useState(false);
|
||||||
|
const {
|
||||||
|
register,
|
||||||
|
handleSubmit,
|
||||||
|
reset,
|
||||||
|
formState: {errors},
|
||||||
|
} = useForm<z.infer<typeof FormSchema>>({
|
||||||
|
resolver: zodResolver(FormSchema),
|
||||||
|
defaultValues: {
|
||||||
|
value: setting.value || "",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const onSubmit = async (data: z.infer<typeof FormSchema>) => {
|
||||||
|
setSaving(!saving);
|
||||||
|
const update = {...data, name: setting.name};
|
||||||
|
// console.log(update);
|
||||||
|
try {
|
||||||
|
const result = await axios.patch("/api/server/settings", update, {
|
||||||
|
headers: {Authorization: `Bearer ${token}`},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result.data.success) {
|
||||||
|
setOpen(!open);
|
||||||
|
setSaving(false);
|
||||||
|
refetch();
|
||||||
|
toast.success(result.data.message);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Dialog
|
||||||
|
open={open}
|
||||||
|
onOpenChange={(isOpen) => {
|
||||||
|
if (!open) {
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
setOpen(isOpen);
|
||||||
|
// toast.message("Model was something", {
|
||||||
|
// description: isOpen ? "Modal is open" : "Modal is closed",
|
||||||
|
// });
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<DialogTrigger asChild>
|
||||||
|
<Button variant="outline">Edit</Button>
|
||||||
|
</DialogTrigger>
|
||||||
|
<DialogContent className="sm:max-w-[425px]">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>{setting.name}</DialogTitle>
|
||||||
|
<DialogDescription>
|
||||||
|
Update the setting and press save to complete the changes.
|
||||||
|
</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
<form onSubmit={handleSubmit(onSubmit)}>
|
||||||
|
<div>
|
||||||
|
<>
|
||||||
|
<Label htmlFor={"value"} className="m-1">
|
||||||
|
Value
|
||||||
|
</Label>
|
||||||
|
<Input
|
||||||
|
{...register("value")}
|
||||||
|
className={errors.value ? "border-red-500" : ""}
|
||||||
|
aria-invalid={!!errors.value}
|
||||||
|
/>
|
||||||
|
{errors.value && <p className="text-red-500 text-sm mt-1">{errors.value.message}</p>}
|
||||||
|
</>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<DialogFooter>
|
||||||
|
<div className="flex justify-end mt-2">
|
||||||
|
<Button type="submit" disabled={saving}>
|
||||||
|
{saving ? (
|
||||||
|
<>
|
||||||
|
<span>Saving....</span>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<span>Save setting</span>
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</DialogFooter>
|
||||||
|
</form>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,21 +1,24 @@
|
|||||||
import {LstCard} from "@/components/extendedUI/LstCard";
|
import {LstCard} from "@/components/extendedUI/LstCard";
|
||||||
|
import {Table, TableBody, TableCaption, TableCell, TableHead, TableHeader, TableRow} from "@/components/ui/table";
|
||||||
import {useSessionStore} from "@/lib/store/sessionStore";
|
import {useSessionStore} from "@/lib/store/sessionStore";
|
||||||
import {useModuleStore} from "@/lib/store/useModuleStore";
|
import {useModuleStore} from "@/lib/store/useModuleStore";
|
||||||
import {useQuery} from "@tanstack/react-query";
|
import {useQuery} from "@tanstack/react-query";
|
||||||
import {useRouter} from "@tanstack/react-router";
|
import {useRouter} from "@tanstack/react-router";
|
||||||
import axios from "axios";
|
import {ChangeSetting} from "./SettingForm";
|
||||||
|
import {getSettings} from "@/utils/querys/settings";
|
||||||
|
|
||||||
|
export type Settings = {
|
||||||
|
settings_id?: string;
|
||||||
|
name?: string;
|
||||||
|
value?: string;
|
||||||
|
description?: string;
|
||||||
|
};
|
||||||
|
|
||||||
export default function SettingsPage() {
|
export default function SettingsPage() {
|
||||||
const token = localStorage.getItem("auth_token");
|
const {user, token} = useSessionStore();
|
||||||
const {user} = useSessionStore();
|
|
||||||
const {modules} = useModuleStore();
|
const {modules} = useModuleStore();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const fetchSettings = async () => {
|
|
||||||
const {data} = await axios.get("/api/server/settings", {headers: {Authorization: `Bearer ${token}`}});
|
|
||||||
return data.data;
|
|
||||||
};
|
|
||||||
|
|
||||||
const adminModule = modules.filter((n) => n.name === "admin");
|
const adminModule = modules.filter((n) => n.name === "admin");
|
||||||
const userLevel = user?.roles.filter((r) => r.module_id === adminModule[0].module_id) || [];
|
const userLevel = user?.roles.filter((r) => r.module_id === adminModule[0].module_id) || [];
|
||||||
|
|
||||||
@@ -23,12 +26,7 @@ export default function SettingsPage() {
|
|||||||
router.navigate({to: "/"});
|
router.navigate({to: "/"});
|
||||||
}
|
}
|
||||||
|
|
||||||
const {data, isError, error, isLoading} = useQuery({
|
const {data, isError, error, isLoading} = useQuery(getSettings(token ?? ""));
|
||||||
queryKey: ["settings"],
|
|
||||||
queryFn: fetchSettings,
|
|
||||||
enabled: !!token,
|
|
||||||
refetchOnWindowFocus: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
return <div>Loading.....</div>;
|
return <div>Loading.....</div>;
|
||||||
@@ -38,10 +36,29 @@ export default function SettingsPage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<LstCard className="m-2 flex place-content-center w-dvh">
|
||||||
{data.map((i: any) => {
|
<Table>
|
||||||
return <LstCard key={i.settings_id}>{i.name}</LstCard>;
|
<TableCaption>All Settings</TableCaption>
|
||||||
})}
|
<TableHeader>
|
||||||
</div>
|
<TableRow>
|
||||||
|
<TableHead>Name</TableHead>
|
||||||
|
<TableHead>Value</TableHead>
|
||||||
|
<TableHead>Change</TableHead>
|
||||||
|
</TableRow>
|
||||||
|
</TableHeader>
|
||||||
|
<TableBody>
|
||||||
|
{data?.map((setting: Settings) => (
|
||||||
|
<TableRow key={setting.settings_id}>
|
||||||
|
<TableCell className="font-medium">{setting.name}</TableCell>
|
||||||
|
<TableCell className="font-medium">{setting.value}</TableCell>
|
||||||
|
<TableCell className="font-medium">{setting.description}</TableCell>
|
||||||
|
<TableCell className="font-medium">
|
||||||
|
<ChangeSetting setting={setting} />
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</LstCard>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,7 +81,9 @@ const LoginForm = () => {
|
|||||||
<hr className="rounded"></hr>
|
<hr className="rounded"></hr>
|
||||||
<form onSubmit={handleSubmit(onSubmitLogin)}>
|
<form onSubmit={handleSubmit(onSubmitLogin)}>
|
||||||
<div>
|
<div>
|
||||||
<Label>Username</Label>
|
<Label htmlFor="username" className="m-1">
|
||||||
|
Username
|
||||||
|
</Label>
|
||||||
<Input
|
<Input
|
||||||
placeholder="smith001"
|
placeholder="smith001"
|
||||||
{...register("username")}
|
{...register("username")}
|
||||||
@@ -92,7 +94,9 @@ const LoginForm = () => {
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<>
|
<>
|
||||||
<Label htmlFor={"password"}>Password</Label>
|
<Label htmlFor={"password"} className="m-1">
|
||||||
|
Password
|
||||||
|
</Label>
|
||||||
<Input
|
<Input
|
||||||
type="password"
|
type="password"
|
||||||
{...register("password")}
|
{...register("password")}
|
||||||
@@ -106,15 +110,24 @@ const LoginForm = () => {
|
|||||||
<div className="flex">
|
<div className="flex">
|
||||||
<Controller
|
<Controller
|
||||||
render={({field}) => (
|
render={({field}) => (
|
||||||
<Checkbox id="remember" checked={field.value} onCheckedChange={field.onChange} />
|
<>
|
||||||
|
<Checkbox
|
||||||
|
id="remember"
|
||||||
|
checked={field.value}
|
||||||
|
onCheckedChange={field.onChange}
|
||||||
|
/>
|
||||||
|
<label
|
||||||
|
htmlFor="remember"
|
||||||
|
className="pl-2 text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
|
||||||
|
>
|
||||||
|
remember me
|
||||||
|
</label>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
control={control}
|
control={control}
|
||||||
name="rememberMe"
|
name="rememberMe"
|
||||||
defaultValue={rememeberMe}
|
defaultValue={rememeberMe}
|
||||||
/>
|
/>
|
||||||
<Label htmlFor="remember" className="pl-2">
|
|
||||||
remember me
|
|
||||||
</Label>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex justify-end">
|
<div className="flex justify-end">
|
||||||
|
|||||||
133
frontend/src/components/ui/dialog.tsx
Normal file
133
frontend/src/components/ui/dialog.tsx
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
import * as React from "react"
|
||||||
|
import * as DialogPrimitive from "@radix-ui/react-dialog"
|
||||||
|
import { XIcon } from "lucide-react"
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
|
function Dialog({
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof DialogPrimitive.Root>) {
|
||||||
|
return <DialogPrimitive.Root data-slot="dialog" {...props} />
|
||||||
|
}
|
||||||
|
|
||||||
|
function DialogTrigger({
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
|
||||||
|
return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />
|
||||||
|
}
|
||||||
|
|
||||||
|
function DialogPortal({
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof DialogPrimitive.Portal>) {
|
||||||
|
return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />
|
||||||
|
}
|
||||||
|
|
||||||
|
function DialogClose({
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof DialogPrimitive.Close>) {
|
||||||
|
return <DialogPrimitive.Close data-slot="dialog-close" {...props} />
|
||||||
|
}
|
||||||
|
|
||||||
|
function DialogOverlay({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof DialogPrimitive.Overlay>) {
|
||||||
|
return (
|
||||||
|
<DialogPrimitive.Overlay
|
||||||
|
data-slot="dialog-overlay"
|
||||||
|
className={cn(
|
||||||
|
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/80",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function DialogContent({
|
||||||
|
className,
|
||||||
|
children,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof DialogPrimitive.Content>) {
|
||||||
|
return (
|
||||||
|
<DialogPortal data-slot="dialog-portal">
|
||||||
|
<DialogOverlay />
|
||||||
|
<DialogPrimitive.Content
|
||||||
|
data-slot="dialog-content"
|
||||||
|
className={cn(
|
||||||
|
"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
<DialogPrimitive.Close className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4">
|
||||||
|
<XIcon />
|
||||||
|
<span className="sr-only">Close</span>
|
||||||
|
</DialogPrimitive.Close>
|
||||||
|
</DialogPrimitive.Content>
|
||||||
|
</DialogPortal>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
data-slot="dialog-header"
|
||||||
|
className={cn("flex flex-col gap-2 text-center sm:text-left", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function DialogFooter({ className, ...props }: React.ComponentProps<"div">) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
data-slot="dialog-footer"
|
||||||
|
className={cn(
|
||||||
|
"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function DialogTitle({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof DialogPrimitive.Title>) {
|
||||||
|
return (
|
||||||
|
<DialogPrimitive.Title
|
||||||
|
data-slot="dialog-title"
|
||||||
|
className={cn("text-lg leading-none font-semibold", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function DialogDescription({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof DialogPrimitive.Description>) {
|
||||||
|
return (
|
||||||
|
<DialogPrimitive.Description
|
||||||
|
data-slot="dialog-description"
|
||||||
|
className={cn("text-muted-foreground text-sm", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
Dialog,
|
||||||
|
DialogClose,
|
||||||
|
DialogContent,
|
||||||
|
DialogDescription,
|
||||||
|
DialogFooter,
|
||||||
|
DialogHeader,
|
||||||
|
DialogOverlay,
|
||||||
|
DialogPortal,
|
||||||
|
DialogTitle,
|
||||||
|
DialogTrigger,
|
||||||
|
}
|
||||||
58
frontend/src/components/ui/spinner.tsx
Normal file
58
frontend/src/components/ui/spinner.tsx
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
import * as React from "react";
|
||||||
|
import {Slot} from "@radix-ui/react-slot";
|
||||||
|
import {cva, type VariantProps} from "class-variance-authority";
|
||||||
|
import {cn} from "@/lib/utils";
|
||||||
|
|
||||||
|
const spinnerVariants = cva("relative block opacity-[0.65]", {
|
||||||
|
variants: {
|
||||||
|
size: {
|
||||||
|
sm: "w-4 h-4",
|
||||||
|
md: "w-6 h-6",
|
||||||
|
lg: "w-8 h-8",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
defaultVariants: {
|
||||||
|
size: "sm",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export interface SpinnerProps extends React.HTMLAttributes<HTMLSpanElement>, VariantProps<typeof spinnerVariants> {
|
||||||
|
loading?: boolean;
|
||||||
|
asChild?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Spinner = React.forwardRef<HTMLSpanElement, SpinnerProps>(
|
||||||
|
({className, size, loading = true, asChild = false, ...props}, ref) => {
|
||||||
|
const Comp = asChild ? Slot : "span";
|
||||||
|
|
||||||
|
const [bgColorClass, filteredClassName] = React.useMemo(() => {
|
||||||
|
const bgClass = className?.match(/(?:dark:bg-|bg-)[a-zA-Z0-9-]+/g) || [];
|
||||||
|
const filteredClasses = className?.replace(/(?:dark:bg-|bg-)[a-zA-Z0-9-]+/g, "").trim();
|
||||||
|
|
||||||
|
return [bgClass, filteredClasses];
|
||||||
|
}, [className]);
|
||||||
|
|
||||||
|
if (!loading) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Comp className={cn(spinnerVariants({size, className: filteredClassName}))} ref={ref} {...props}>
|
||||||
|
{Array.from({length: 8}).map((_, i) => (
|
||||||
|
<span
|
||||||
|
key={i}
|
||||||
|
className="absolute top-0 left-1/2 w-[12.5%] h-full animate-spinner-leaf-fade"
|
||||||
|
style={{
|
||||||
|
transform: `rotate(${i * 45}deg)`,
|
||||||
|
animationDelay: `${-(7 - i) * 100}ms`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span className={cn("block w-full h-[30%] rounded-full", bgColorClass)}></span>
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
|
</Comp>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
Spinner.displayName = "Spinner";
|
||||||
|
|
||||||
|
export {Spinner};
|
||||||
114
frontend/src/components/ui/table.tsx
Normal file
114
frontend/src/components/ui/table.tsx
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
import * as React from "react"
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
|
function Table({ className, ...props }: React.ComponentProps<"table">) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
data-slot="table-container"
|
||||||
|
className="relative w-full overflow-x-auto"
|
||||||
|
>
|
||||||
|
<table
|
||||||
|
data-slot="table"
|
||||||
|
className={cn("w-full caption-bottom text-sm", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function TableHeader({ className, ...props }: React.ComponentProps<"thead">) {
|
||||||
|
return (
|
||||||
|
<thead
|
||||||
|
data-slot="table-header"
|
||||||
|
className={cn("[&_tr]:border-b", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function TableBody({ className, ...props }: React.ComponentProps<"tbody">) {
|
||||||
|
return (
|
||||||
|
<tbody
|
||||||
|
data-slot="table-body"
|
||||||
|
className={cn("[&_tr:last-child]:border-0", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function TableFooter({ className, ...props }: React.ComponentProps<"tfoot">) {
|
||||||
|
return (
|
||||||
|
<tfoot
|
||||||
|
data-slot="table-footer"
|
||||||
|
className={cn(
|
||||||
|
"bg-muted/50 border-t font-medium [&>tr]:last:border-b-0",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function TableRow({ className, ...props }: React.ComponentProps<"tr">) {
|
||||||
|
return (
|
||||||
|
<tr
|
||||||
|
data-slot="table-row"
|
||||||
|
className={cn(
|
||||||
|
"hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function TableHead({ className, ...props }: React.ComponentProps<"th">) {
|
||||||
|
return (
|
||||||
|
<th
|
||||||
|
data-slot="table-head"
|
||||||
|
className={cn(
|
||||||
|
"text-muted-foreground h-10 px-2 text-left align-middle font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function TableCell({ className, ...props }: React.ComponentProps<"td">) {
|
||||||
|
return (
|
||||||
|
<td
|
||||||
|
data-slot="table-cell"
|
||||||
|
className={cn(
|
||||||
|
"p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function TableCaption({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<"caption">) {
|
||||||
|
return (
|
||||||
|
<caption
|
||||||
|
data-slot="table-caption"
|
||||||
|
className={cn("text-muted-foreground mt-4 text-sm", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
Table,
|
||||||
|
TableHeader,
|
||||||
|
TableBody,
|
||||||
|
TableFooter,
|
||||||
|
TableHead,
|
||||||
|
TableRow,
|
||||||
|
TableCell,
|
||||||
|
TableCaption,
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
|
import {useSessionStore} from "@/lib/store/sessionStore";
|
||||||
import {useRouter} from "@tanstack/react-router";
|
import {useRouter} from "@tanstack/react-router";
|
||||||
import {useSessionStore} from "../store/sessionStore";
|
|
||||||
|
|
||||||
export const useLogout = () => {
|
export const useLogout = () => {
|
||||||
const {clearSession} = useSessionStore();
|
const {clearSession} = useSessionStore();
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import {useQuery} from "@tanstack/react-query";
|
import {useQuery} from "@tanstack/react-query";
|
||||||
import {useSessionStore} from "../store/sessionStore";
|
import {useSessionStore} from "../lib/store/sessionStore";
|
||||||
import {useEffect} from "react";
|
import {useEffect} from "react";
|
||||||
|
|
||||||
const fetchSession = async () => {
|
const fetchSession = async () => {
|
||||||
@@ -34,6 +34,7 @@ export const useSession = () => {
|
|||||||
staleTime: 60 * 1000,
|
staleTime: 60 * 1000,
|
||||||
gcTime: 10 * 60 * 1000, // 10 mins
|
gcTime: 10 * 60 * 1000, // 10 mins
|
||||||
refetchOnWindowFocus: true,
|
refetchOnWindowFocus: true,
|
||||||
|
//refetchInterval: 1000 * 60 * 2, // Auto-refetch every 2 minutes
|
||||||
});
|
});
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (data) {
|
if (data) {
|
||||||
@@ -17,9 +17,10 @@ import {
|
|||||||
import {SessionProvider} from "../components/providers/Providers";
|
import {SessionProvider} from "../components/providers/Providers";
|
||||||
import {Toaster} from "sonner";
|
import {Toaster} from "sonner";
|
||||||
import {Button} from "../components/ui/button";
|
import {Button} from "../components/ui/button";
|
||||||
import {useLogout} from "../lib/hooks/useLogout";
|
|
||||||
import {useSession} from "../lib/hooks/useSession";
|
|
||||||
import {useSessionStore} from "../lib/store/sessionStore";
|
import {useSessionStore} from "../lib/store/sessionStore";
|
||||||
|
import {useSession} from "@/hooks/useSession";
|
||||||
|
import {useLogout} from "@/hooks/useLogout";
|
||||||
|
|
||||||
// same as the layout
|
// same as the layout
|
||||||
export const Route = createRootRoute({
|
export const Route = createRootRoute({
|
||||||
|
|||||||
3
frontend/src/utils/delay.ts
Normal file
3
frontend/src/utils/delay.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export function delay(ms: number) {
|
||||||
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||||
|
}
|
||||||
17
frontend/src/utils/querys/settings.tsx
Normal file
17
frontend/src/utils/querys/settings.tsx
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import {queryOptions} from "@tanstack/react-query";
|
||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
export function getSettings(token: string) {
|
||||||
|
return queryOptions({
|
||||||
|
queryKey: ["settings"],
|
||||||
|
queryFn: () => fetchSettings(token),
|
||||||
|
enabled: !!token,
|
||||||
|
staleTime: 1000,
|
||||||
|
refetchOnWindowFocus: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const fetchSettings = async (token: string) => {
|
||||||
|
const {data} = await axios.get("/api/server/settings", {headers: {Authorization: `Bearer ${token}`}});
|
||||||
|
return data.data;
|
||||||
|
};
|
||||||
@@ -9,7 +9,7 @@ import {log} from "../../logger/logger.js";
|
|||||||
/**
|
/**
|
||||||
* Authenticate a user and return a JWT.
|
* Authenticate a user and return a JWT.
|
||||||
*/
|
*/
|
||||||
const {sign, verify} = jwt;
|
const {sign} = jwt;
|
||||||
|
|
||||||
export async function login(
|
export async function login(
|
||||||
username: string,
|
username: string,
|
||||||
@@ -56,5 +56,6 @@ export async function login(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const token = sign({user: userData}, secret, {expiresIn: expiresIn * 60});
|
const token = sign({user: userData}, secret, {expiresIn: expiresIn * 60});
|
||||||
|
|
||||||
return {token, user: userData};
|
return {token, user: userData};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,13 @@ import {z, createRoute, OpenAPIHono} from "@hono/zod-openapi";
|
|||||||
import {verify} from "hono/jwt";
|
import {verify} from "hono/jwt";
|
||||||
import {log} from "../../logger/logger.js";
|
import {log} from "../../logger/logger.js";
|
||||||
import {authMiddleware} from "../middleware/authMiddleware.js";
|
import {authMiddleware} from "../middleware/authMiddleware.js";
|
||||||
|
import jwt from "jsonwebtoken";
|
||||||
|
|
||||||
const session = new OpenAPIHono();
|
const session = new OpenAPIHono();
|
||||||
|
const expiresIn = Number(process.env.JWT_EXPIRES!) || 60;
|
||||||
|
const secret: string = process.env.JWT_SECRET!;
|
||||||
|
|
||||||
|
const {sign} = jwt;
|
||||||
const UserSchema = z.object({
|
const UserSchema = z.object({
|
||||||
username: z
|
username: z
|
||||||
.string()
|
.string()
|
||||||
@@ -79,7 +83,11 @@ session.openapi(
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const payload = await verify(token, process.env.JWT_SECRET!);
|
const payload = await verify(token, process.env.JWT_SECRET!);
|
||||||
return c.json({data: {token: token, user: payload.user}}, 200);
|
|
||||||
|
// If it's valid, return a new token
|
||||||
|
const newToken = sign({user: payload.user}, secret, {expiresIn: expiresIn * 60});
|
||||||
|
|
||||||
|
return c.json({data: {token: newToken, user: payload.user}}, 200);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
log.error(error, "Failed session check, user must be logged out");
|
log.error(error, "Failed session check, user must be logged out");
|
||||||
return c.json({message: "Unauthorized"}, 401);
|
return c.json({message: "Unauthorized"}, 401);
|
||||||
|
|||||||
37
server/services/server/controller/settings/updateSetting.ts
Normal file
37
server/services/server/controller/settings/updateSetting.ts
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import {and, eq, sql} from "drizzle-orm";
|
||||||
|
import {db} from "../../../../../database/dbclient.js";
|
||||||
|
import {settings} from "../../../../../database/schema/settings.js";
|
||||||
|
import {log} from "../../../logger/logger.js";
|
||||||
|
import {userRoles} from "../../../../../database/schema/userRoles.js";
|
||||||
|
import {users} from "../../../../../database/schema/users.js";
|
||||||
|
|
||||||
|
export const updateSetting = async (data: any, user_id: string) => {
|
||||||
|
log.info(user_id, "Adding a new setting");
|
||||||
|
|
||||||
|
// make sure the user is a system admin before moving forward
|
||||||
|
const sysAdmin = await db
|
||||||
|
.select()
|
||||||
|
.from(userRoles)
|
||||||
|
.where(and(eq(userRoles.user_id, user_id), eq(userRoles.role, "systemAdmin")));
|
||||||
|
|
||||||
|
if (sysAdmin) {
|
||||||
|
log.info(`Setting ${data.name} is being updated`);
|
||||||
|
|
||||||
|
//get the username so we can update the correct field
|
||||||
|
const user = await db.select().from(users).where(eq(users.user_id, user_id));
|
||||||
|
try {
|
||||||
|
//const settingID = await db.select().from(settings).where(eq(settings.name, data.module));
|
||||||
|
|
||||||
|
const updateSetting = await db
|
||||||
|
.update(settings)
|
||||||
|
.set({value: data.value, upd_user: user[0].username, upd_date: sql`NOW()`})
|
||||||
|
.where(eq(settings.name, data.name));
|
||||||
|
} catch (error) {
|
||||||
|
log.error(error, "Error updating setting");
|
||||||
|
throw new Error("Error updating Setting");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.info("This user cannot add new roles");
|
||||||
|
throw new Error("The user trying to add a setting dose not have the correct permissions");
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -17,7 +17,7 @@ const AddSetting = z.object({
|
|||||||
|
|
||||||
app.openapi(
|
app.openapi(
|
||||||
createRoute({
|
createRoute({
|
||||||
tags: ["server"],
|
tags: ["server:settings"],
|
||||||
summary: "Add Setting",
|
summary: "Add Setting",
|
||||||
method: "post",
|
method: "post",
|
||||||
path: "/settings",
|
path: "/settings",
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ const app = new OpenAPIHono();
|
|||||||
|
|
||||||
app.openapi(
|
app.openapi(
|
||||||
createRoute({
|
createRoute({
|
||||||
tags: ["server"],
|
tags: ["server:settings"],
|
||||||
summary: "Returns all modules in the server",
|
summary: "Returns all modules in the server",
|
||||||
method: "delete",
|
method: "delete",
|
||||||
path: "/settings",
|
path: "/settings",
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ const app = new OpenAPIHono();
|
|||||||
|
|
||||||
app.openapi(
|
app.openapi(
|
||||||
createRoute({
|
createRoute({
|
||||||
tags: ["server"],
|
tags: ["server:settings"],
|
||||||
summary: "Returns all settings based on your permissions",
|
summary: "Returns all settings based on your permissions",
|
||||||
method: "get",
|
method: "get",
|
||||||
path: "/settings",
|
path: "/settings",
|
||||||
|
|||||||
@@ -1,13 +1,29 @@
|
|||||||
import {createRoute, OpenAPIHono, z} from "@hono/zod-openapi";
|
import {createRoute, OpenAPIHono, z} from "@hono/zod-openapi";
|
||||||
|
import type {User} from "../../../../types/users.js";
|
||||||
|
import {log} from "../../../logger/logger.js";
|
||||||
|
import {verify} from "hono/jwt";
|
||||||
|
import {updateSetting} from "../../controller/settings/updateSetting.js";
|
||||||
|
|
||||||
const app = new OpenAPIHono();
|
const app = new OpenAPIHono();
|
||||||
|
|
||||||
|
const UpdateSetting = z.object({
|
||||||
|
name: z.string().openapi({example: "server"}),
|
||||||
|
value: z.string().openapi({example: "localhost"}),
|
||||||
|
});
|
||||||
|
|
||||||
app.openapi(
|
app.openapi(
|
||||||
createRoute({
|
createRoute({
|
||||||
tags: ["server"],
|
tags: ["server:settings"],
|
||||||
summary: "Returns all modules in the server",
|
summary: "Updates A setting",
|
||||||
method: "post",
|
method: "patch",
|
||||||
path: "/",
|
path: "/settings",
|
||||||
|
request: {
|
||||||
|
body: {
|
||||||
|
content: {
|
||||||
|
"application/json": {schema: UpdateSetting},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
responses: {
|
responses: {
|
||||||
200: {
|
200: {
|
||||||
content: {
|
content: {
|
||||||
@@ -20,10 +36,63 @@ app.openapi(
|
|||||||
},
|
},
|
||||||
description: "Response message",
|
description: "Response message",
|
||||||
},
|
},
|
||||||
|
400: {
|
||||||
|
content: {
|
||||||
|
"application/json": {
|
||||||
|
schema: z.object({message: z.string().optional().openapi({example: "Internal Server error"})}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
description: "Internal Server Error",
|
||||||
|
},
|
||||||
|
401: {
|
||||||
|
content: {
|
||||||
|
"application/json": {
|
||||||
|
schema: z.object({message: z.string().optional().openapi({example: "Unauthenticated"})}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
description: "Unauthorized",
|
||||||
|
},
|
||||||
|
500: {
|
||||||
|
content: {
|
||||||
|
"application/json": {
|
||||||
|
schema: z.object({message: z.string().optional().openapi({example: "Internal Server error"})}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
description: "Internal Server Error",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
async (c) => {
|
async (c) => {
|
||||||
return c.json({success: true, message: "Example"}, 200);
|
// make sure we have a vaid user being accessed thats really logged in
|
||||||
|
const authHeader = c.req.header("Authorization");
|
||||||
|
|
||||||
|
if (authHeader?.includes("Basic")) {
|
||||||
|
return c.json({message: "You are a Basic user! Please login to get a token"}, 401);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!authHeader) {
|
||||||
|
return c.json({message: "Unauthorized"}, 401);
|
||||||
|
}
|
||||||
|
|
||||||
|
const token = authHeader?.split("Bearer ")[1] || "";
|
||||||
|
let user: User;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const payload = await verify(token, process.env.JWT_SECRET!);
|
||||||
|
user = payload.user as User;
|
||||||
|
} catch (error) {
|
||||||
|
log.error(error, "Failed session check, user must be logged out");
|
||||||
|
return c.json({message: "Unauthorized"}, 401);
|
||||||
|
}
|
||||||
|
|
||||||
|
// now pass all the data over to update the user info
|
||||||
|
try {
|
||||||
|
const data = await c?.req.json();
|
||||||
|
await updateSetting(data, user.user_id ?? "");
|
||||||
|
return c.json({success: true, message: "The Setting was just updated", data}, 200);
|
||||||
|
} catch (error) {
|
||||||
|
return c.json({message: "There was an error updating the settings.", error}, 400);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
export default app;
|
export default app;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import updateModule from "./route/modules/updateModules.js";
|
|||||||
import addModule from "./route/modules/addModule.js";
|
import addModule from "./route/modules/addModule.js";
|
||||||
import addSetting from "./route/settings/addSetting.js";
|
import addSetting from "./route/settings/addSetting.js";
|
||||||
import getSettings from "./route/settings/getSettings.js";
|
import getSettings from "./route/settings/getSettings.js";
|
||||||
|
import updateSetting from "./route/settings/updateSetting.js";
|
||||||
|
|
||||||
areModulesIn();
|
areModulesIn();
|
||||||
const app = new OpenAPIHono();
|
const app = new OpenAPIHono();
|
||||||
@@ -18,6 +19,7 @@ const routes = [
|
|||||||
// settings
|
// settings
|
||||||
addSetting,
|
addSetting,
|
||||||
getSettings,
|
getSettings,
|
||||||
|
updateSetting,
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
// app.route("/server", modules);
|
// app.route("/server", modules);
|
||||||
|
|||||||
Reference in New Issue
Block a user