Compare commits
361 Commits
dev
...
ecb07c7e7c
| Author | SHA1 | Date | |
|---|---|---|---|
| ecb07c7e7c | |||
| dcfa96b710 | |||
| 8c5c9fd244 | |||
| 2ffc3cc242 | |||
| e780a24a8a | |||
| 8b7353d42b | |||
| 4ef0c51ab2 | |||
| c6fe7dbbce | |||
| 9ae324193a | |||
| e8cd5916d0 | |||
| 9c65b8b377 | |||
| 7aa897bcc9 | |||
| 085dc64db9 | |||
| 3df1ceaaac | |||
| 07c0be0ea1 | |||
| 68ccf2382b | |||
| 632e07967a | |||
| a68a3ba640 | |||
| af8d53cac1 | |||
| 5cdca0a41f | |||
| 9cb8ca6813 | |||
| d5114ba243 | |||
| e7e35336f8 | |||
| fae1f36555 | |||
| 69031a7f0e | |||
| fc621c8ca6 | |||
| be1074d142 | |||
| 365a24ce5f | |||
| 94f5906299 | |||
| 35652e3735 | |||
| 84e0c46be9 | |||
| f5fd1c0890 | |||
| 7dab5f36ec | |||
| 1b69edfef0 | |||
| 4c799c70ab | |||
| fbd63e6da2 | |||
| be31ae2c04 | |||
| 5f486bf6cd | |||
| 8cf4e3e31c | |||
| 558673d8c4 | |||
| 9add660249 | |||
| 02912825de | |||
| 0793c5f7d6 | |||
| 46bb695840 | |||
| c79496eaac | |||
| 50fcfb05ce | |||
| a6f29fe11c | |||
| 30cdb3f073 | |||
| fbc2282aee | |||
| 26798ca140 | |||
| 2d39f93e42 | |||
| 917090eaa9 | |||
| c25c2d006a | |||
| 95ca2ff2b3 | |||
| 2eafbdf45e | |||
| 7a3732d5b2 | |||
| d0a19b5589 | |||
| 71f1cf0f21 | |||
| 56252e2439 | |||
| 142be260bd | |||
| a751bb6a50 | |||
| 1a5d066eb4 | |||
| 1bc7949f30 | |||
| 450e5acd34 | |||
| d4edeb15d9 | |||
| a0afb305fc | |||
| 2a6af066bc | |||
| acd89d926c | |||
| bb20046890 | |||
| ae7ea2bb90 | |||
| 17773e9a23 | |||
| 25785703db | |||
| 087d14c585 | |||
| 328b61f6cc | |||
| c02d289b80 | |||
| e0e7e03d37 | |||
| 5fb7b5c59e | |||
| aabcf12bee | |||
| f0a5d6e949 | |||
| bdeea6bd1a | |||
| 89ace4343c | |||
| 242b90c75a | |||
| 9baeb1ceff | |||
| 148919a411 | |||
| 090f618ebd | |||
| d96cd4416e | |||
| 99abded7b9 | |||
| 7532c89ae2 | |||
| dd6895fac2 | |||
| 95c869d667 | |||
| 9325e58551 | |||
| 17b6c0ac66 | |||
| 3241cf810a | |||
| b5b57fe3bf | |||
| 08b052ea5a | |||
| 8ad64bb67a | |||
| e0eb26b544 | |||
| 2090f8ce71 | |||
| db1d5f1601 | |||
| c5d53e03d3 | |||
| fb0b3f06a4 | |||
| 6e2e17bdde | |||
| 6665b77e09 | |||
| 2e2699ab3c | |||
| bad390ec17 | |||
| efc630f5f8 | |||
| ded074a1ce | |||
| ca0b027e67 | |||
| 1282f5efe4 | |||
| 77988477f6 | |||
| 37b26c4c92 | |||
| 72e2c6ea6a | |||
| ffe80d6a58 | |||
| 9dcd07bf2a | |||
| 4a36107ebb | |||
| fb03fc83e6 | |||
| 8c522c5b72 | |||
| e9c9a84a82 | |||
| ff2ecff146 | |||
| 3757b367d5 | |||
| 4d979089cb | |||
| b1e611c7b8 | |||
| 02fdc14769 | |||
| a794943740 | |||
| c2ad046fb0 | |||
| ba2b8036b8 | |||
| 26aa9d8f80 | |||
| 663f2f436c | |||
| 88f05eaf65 | |||
| b84d6f5186 | |||
| 410790e693 | |||
| f847ce423d | |||
| 27126cca35 | |||
| 04f524419d | |||
| d8edfaf05f | |||
| 92d251c122 | |||
| b4a4dfcb75 | |||
| b630bae50d | |||
| 4371fcc028 | |||
| 9deedd86e5 | |||
| 5a48c91801 | |||
| 51d65cc0b1 | |||
| 6c94005971 | |||
| 8afdc71bbf | |||
| 358e5524c7 | |||
| ef61dad210 | |||
| 7d03d0c42a | |||
| 4effb25e9d | |||
| dc5ee5b97a | |||
| 75f94eae14 | |||
| 31fbfa4eb3 | |||
| b589bf9724 | |||
| 17ed18669a | |||
| b9f080f130 | |||
| ce546c0d35 | |||
| 51cc4aa370 | |||
| 95bebbde2b | |||
| 85e3d46b2e | |||
| 525de7dab2 | |||
| 1956ee313a | |||
| 536899b6e7 | |||
| d9e60451f8 | |||
| 85577b291f | |||
| f1abe7b33d | |||
| 9f26f2334f | |||
| a7818b4ca3 | |||
| 99477bac19 | |||
| 5eacbb5ecf | |||
| 8b5698a839 | |||
| ad5e77028d | |||
| e1973e4da6 | |||
| 8194798a37 | |||
| 16e5413a90 | |||
| 6065cccbd7 | |||
| 9a5dc980f0 | |||
| 23fa9f09dc | |||
| f1c9877686 | |||
| 6ad49b704d | |||
| 60cd6e551a | |||
| 74445149b7 | |||
| 2e05f79c72 | |||
| 13df4af860 | |||
| 6bd1bebe33 | |||
| 99fd875dbb | |||
| 17d7e54b7a | |||
| 498c1626a1 | |||
| 6180f61d08 | |||
| 3e4d8b260c | |||
| fa9e5dd70f | |||
| b9397c029f | |||
| 7e34d42fda | |||
| 96807bf77e | |||
| 7a6911c694 | |||
| 05b22d7cb7 | |||
| 6b5f7e0bcd | |||
| 858bf986d9 | |||
| 2cc81a5b07 | |||
| 52e3e1b4a1 | |||
| d27611d035 | |||
| f771db6034 | |||
| 4f3b5d75a2 | |||
| a1f62a3e51 | |||
| de0ee3a61c | |||
| b48dd8fa15 | |||
| 3355eb389c | |||
| b2683d0429 | |||
| 7e484a0f90 | |||
| 77abaed60e | |||
| d10770bc49 | |||
| 1fee4b719b | |||
| 1dce3dccdc | |||
| 3babf8a749 | |||
| 29c9f2d1be | |||
| 459b0f287c | |||
| 7535e15337 | |||
| 68dac0dd28 | |||
| f442cedff2 | |||
| 63e005b790 | |||
| 814861e59c | |||
| dd62ceb133 | |||
| e335225807 | |||
| 3e54685a7e | |||
| f481197d6e | |||
| 053c05c1a7 | |||
| 8bdbc4995c | |||
| bc2336e46d | |||
| 544e82c01d | |||
| 44507d41c4 | |||
| ee3026fa7c | |||
| 5c642805b1 | |||
| 0d06dae6de | |||
| 8a639ceaf8 | |||
| 8c6dc5f690 | |||
| 16b39fd386 | |||
| 075bba95ee | |||
| 6ec9f5827c | |||
| 93941723cc | |||
| fb41fb1dd1 | |||
| 6d5bcde88e | |||
| 1156bbd223 | |||
| bfd4aec4eb | |||
| 63b1151cb7 | |||
| a5dee58223 | |||
| 9784072aab | |||
| f9096b54f5 | |||
| 11e5cf4d86 | |||
| a647d05d3b | |||
| 098c477119 | |||
| 3228ad7892 | |||
| c27ad7cf6a | |||
| a48d4bd5af | |||
| 09c0825194 | |||
| 28fbf2c1e4 | |||
| af5dc9266f | |||
| b903c8ee2d | |||
| 035eda9aa8 | |||
| 1f7c33d871 | |||
| d046c4ea41 | |||
| 88258baf9d | |||
| 82acfcc4a9 | |||
| ba3d721940 | |||
| 27d6b6e884 | |||
| 2c8d1fb710 | |||
| b5de6445b3 | |||
| f9f68ce969 | |||
| 0ced135ec3 | |||
| 7b1c6e1361 | |||
| e3ba45ae13 | |||
| ac7859fda3 | |||
| fb31ae79d1 | |||
| ff1dfdde68 | |||
| f0b9bd599a | |||
| f3103d8c1a | |||
| d557728fa2 | |||
| d58cb5286e | |||
| 7d4733896e | |||
| 175c7226ed | |||
| c32547ceb8 | |||
| a01c0566c2 | |||
| ca4106945b | |||
| 1386e0f00f | |||
| 290f20b86b | |||
| 52171c87fc | |||
| c474536992 | |||
| 600a989226 | |||
| ea7801fccf | |||
| c03b61f48a | |||
| ca552d5587 | |||
| 278c5538bc | |||
| f39ae0f590 | |||
| b4e0f4c666 | |||
| db66302415 | |||
| 90e9bb0ff6 | |||
| bd11feb136 | |||
| 96e7f742fe | |||
| eb051d51f2 | |||
| 7a1a4773e7 | |||
| 878e650e62 | |||
| a31e7ea163 | |||
| 04aa943920 | |||
| af076b8e27 | |||
| c0a0589b3c | |||
| 509ef84726 | |||
| 5ab813f378 | |||
| 5d61eb879e | |||
| 2d4b1db5f4 | |||
| 58f7b4322d | |||
| 3b5e82fdc1 | |||
| f9cd3fb881 | |||
| 51267f5202 | |||
| ceaa25f31e | |||
| 416254353c | |||
| 7f946c095b | |||
| c2aa69ab0a | |||
| 250988800e | |||
| cacfd6d2e0 | |||
| 8d2721b0c2 | |||
| 36cdc7b4bf | |||
| 4d4d6fc7a4 | |||
| 030f9f9aac | |||
| 9e9a56cbb1 | |||
| b01980e1c5 | |||
| fe0c500dcf | |||
| 8a040d15db | |||
| f90066c090 | |||
| 04eb2e3e14 | |||
| 90fb0d364d | |||
| e6e1cecce3 | |||
| 73aa95a693 | |||
| b9f19095cb | |||
| dcb56d4274 | |||
| bc1821132e | |||
| 2551d6c907 | |||
| adf0880659 | |||
| 5149de3199 | |||
| c71b514d9a | |||
| 9254e52808 | |||
| b8c028a6c1 | |||
| 529e922485 | |||
| 5201012235 | |||
| abe53b8f5d | |||
| 836f3e294b | |||
| 96abef762b | |||
| 2c227f9428 | |||
| 46647687dc | |||
| cb01ef1af1 | |||
| b3b5fcec65 | |||
| 3a4dc47a36 | |||
| 63177b523e | |||
| e1cad027d2 | |||
| c1cc355f4f | |||
| 5ed67f3fc0 | |||
| 57e82d2360 | |||
| 9395ec6cd4 | |||
| 0475bb30f9 | |||
| 6843368c36 | |||
| 335ea2deca | |||
| 96814c1115 | |||
| 6dd9ed848b | |||
| 0c5fc1dfb0 | |||
| 5886bea85d |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -10,6 +10,7 @@ backend-0.1.2-217.zip
|
|||||||
backend-0.1.2-218.zip
|
backend-0.1.2-218.zip
|
||||||
backend-0.1.2.zip
|
backend-0.1.2.zip
|
||||||
postgresql-17.2-3-windows-x64.exe
|
postgresql-17.2-3-windows-x64.exe
|
||||||
|
jsTesting
|
||||||
|
|
||||||
|
|
||||||
# ---> Node
|
# ---> Node
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
{
|
{
|
||||||
"types": [
|
"types": [
|
||||||
{ "type": "feat", "section": "🌟 Enhancements" },
|
{ "type": "feat", "section": "🌟 Enhancements" },
|
||||||
{ "type": "fix", "section": "🐛 Bug fixes" },
|
{ "type": "fix", "section": "🐛 Bug fixes" },
|
||||||
{ "type": "chore", "hidden": false, "section": "📝 Chore" },
|
{ "type": "chore", "hidden": false, "section": "📝 Chore" },
|
||||||
{ "type": "docs", "section": "📚 Documentation" },
|
{ "type": "docs", "section": "📚 Documentation" },
|
||||||
{ "type": "style", "hidden": true },
|
{ "type": "style", "hidden": true },
|
||||||
{ "type": "refactor", "section": "🛠️ Code Refactor" },
|
{ "type": "refactor", "section": "🛠️ Code Refactor" },
|
||||||
{ "type": "perf", "hidden": false, "section": "🚀 Performance" },
|
{ "type": "perf", "hidden": false, "section": "🚀 Performance" },
|
||||||
{ "type": "test", "section": "📝 Testing Code" },
|
{ "type": "test", "section": "📝 Testing Code" },
|
||||||
{ "type": "ci", "hidden": false, "section": "📈 Project changes" },
|
{ "type": "ci", "hidden": true, "section": "📈 Project changes" },
|
||||||
{ "type": "build", "hidden": true, "section": "📈 Project Builds" }
|
{ "type": "build", "hidden": true, "section": "📈 Project Builds" }
|
||||||
],
|
],
|
||||||
"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"
|
||||||
}
|
}
|
||||||
|
|||||||
50
.vscode/settings.json
vendored
50
.vscode/settings.json
vendored
@@ -1,26 +1,28 @@
|
|||||||
{
|
{
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||||
|
"workbench.colorTheme": "Default Dark+",
|
||||||
"editor.formatOnSave": true,
|
"prettier.tabWidth": 4,
|
||||||
"[javascript]": {
|
"terminal.integrated.env.windows": {},
|
||||||
"editor.formatOnSave": true
|
"editor.formatOnSave": true,
|
||||||
},
|
"[javascript]": {
|
||||||
"[javascriptreact]": {
|
"editor.formatOnSave": true
|
||||||
"editor.formatOnSave": true
|
},
|
||||||
},
|
"[javascriptreact]": {
|
||||||
"[typescript]": {
|
"editor.formatOnSave": true
|
||||||
"editor.formatOnSave": true
|
},
|
||||||
},
|
"[typescript]": {
|
||||||
"[typescriptreact]": {
|
"editor.formatOnSave": true
|
||||||
"editor.formatOnSave": true
|
},
|
||||||
},
|
"[typescriptreact]": {
|
||||||
"[json]": {
|
"editor.formatOnSave": true
|
||||||
"editor.formatOnSave": true
|
},
|
||||||
},
|
"[json]": {
|
||||||
"[graphql]": {
|
"editor.formatOnSave": true
|
||||||
"editor.formatOnSave": true
|
},
|
||||||
},
|
"[graphql]": {
|
||||||
"[handlebars]": {
|
"editor.formatOnSave": true
|
||||||
"editor.formatOnSave": true
|
},
|
||||||
}
|
"[handlebars]": {
|
||||||
|
"editor.formatOnSave": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
340
CHANGELOG.md
340
CHANGELOG.md
@@ -1,5 +1,345 @@
|
|||||||
# All CHanges to LST can be found below.
|
# All CHanges to LST can be found below.
|
||||||
|
|
||||||
|
## [2.15.0](https://git.tuffraid.net/cowch/lstV2/compare/v2.14.0...v2.15.0) (2025-04-14)
|
||||||
|
|
||||||
|
|
||||||
|
### 📝 Testing Code
|
||||||
|
|
||||||
|
* **notification:** added framework for managment tab ([ae7ea2b](https://git.tuffraid.net/cowch/lstV2/commits/ae7ea2bb90c2608b14c9c912da8a5c55255ebe6e))
|
||||||
|
* **notifications mgt:** added new mgt for notifications to turn off and on in the ui ([9baeb1c](https://git.tuffraid.net/cowch/lstV2/commits/9baeb1ceffb8827d01dae9e3993b8ff605b46453))
|
||||||
|
* **printers:** added in management tab for printers ([bb20046](https://git.tuffraid.net/cowch/lstV2/commits/bb20046890dbab9fd5bcbcd443322b5f5427c5cf))
|
||||||
|
* **quality:** added in framrwork ([328b61f](https://git.tuffraid.net/cowch/lstV2/commits/328b61f6cc359b15a920e9a721a2ecf2d889df85))
|
||||||
|
|
||||||
|
|
||||||
|
### 🐛 Bug fixes
|
||||||
|
|
||||||
|
* **datamart:** corrected the date grab to be print date vs delivery date ([2a6af06](https://git.tuffraid.net/cowch/lstV2/commits/2a6af066bc43cb0d19d29c0362abcfaca6ab85a7))
|
||||||
|
* **labeling process:** corrected a typo in success ([acd89d9](https://git.tuffraid.net/cowch/lstV2/commits/acd89d926cee5705c4102508385e0d7f977b88fe))
|
||||||
|
|
||||||
|
|
||||||
|
### 🌟 Enhancements
|
||||||
|
|
||||||
|
* **cards:** migrated cards over ([087d14c](https://git.tuffraid.net/cowch/lstV2/commits/087d14c5859650ad4cb8ebfee8d5837b940ef0f3))
|
||||||
|
* **changelog:** added in a place to see the changelogs ([242b90c](https://git.tuffraid.net/cowch/lstV2/commits/242b90c75a93ebaa44ba03640386ac4d398c9b38))
|
||||||
|
* **db cleanup:** added a cleanup for labels this checks daily ([450e5ac](https://git.tuffraid.net/cowch/lstV2/commits/450e5acd341e5e3793e65da461f5021de875cd77))
|
||||||
|
* **exports:** added in a button to export the lanes to cycle count ([2578570](https://git.tuffraid.net/cowch/lstV2/commits/25785703db4d7989ab54bd47dda16f38a4407be3))
|
||||||
|
|
||||||
|
|
||||||
|
### 🛠️ Code Refactor
|
||||||
|
|
||||||
|
* **addcards:** changes the way it looks ([a0afb30](https://git.tuffraid.net/cowch/lstV2/commits/a0afb305fc9e575305d5c9185ad576a04c5c921b))
|
||||||
|
* **cards:** allow for changes to the existing card and corrected the display of current stats ([d4edeb1](https://git.tuffraid.net/cowch/lstV2/commits/d4edeb15d9ff6f5fc1814528524f6e6084e3c7e0))
|
||||||
|
* **label logs:** changed to tanstack table ([1bc7949](https://git.tuffraid.net/cowch/lstV2/commits/1bc7949f30d1cd9d4bc7d37941e0be35797afc1e))
|
||||||
|
* **modules:** removed a console log ([17773e9](https://git.tuffraid.net/cowch/lstV2/commits/17773e9a23f93d85797f62310a306d6353b3f835))
|
||||||
|
* **ocp logs:** changed table data to tanstack ([1a5d066](https://git.tuffraid.net/cowch/lstV2/commits/1a5d066eb46faf67aebfea17f323f8b6a8be490d))
|
||||||
|
* **ocplogs:** removed imports not needed ([a751bb6](https://git.tuffraid.net/cowch/lstV2/commits/a751bb6a50a46556b1131427e2888b58de3c9b3d))
|
||||||
|
|
||||||
|
## [2.14.0](https://git.tuffraid.net/cowch/lstV2/compare/v2.13.0...v2.14.0) (2025-04-13)
|
||||||
|
|
||||||
|
|
||||||
|
### 🛠️ Code Refactor
|
||||||
|
|
||||||
|
* **auth:** added module and submodule access to the user ([efc630f](https://git.tuffraid.net/cowch/lstV2/commits/efc630f5f8dba2583f57fac74f596905240ff6e8))
|
||||||
|
* **database:** removed the createAt as it was a duplicate ([ca0b027](https://git.tuffraid.net/cowch/lstV2/commits/ca0b027e67d3d0f78846f7b7364faed5f1be2ed0))
|
||||||
|
* **formatting:** formatting due to new default settings ([b5b57fe](https://git.tuffraid.net/cowch/lstV2/commits/b5b57fe3bf20ca9bc9b8ed87b22f2980bbd1b6f9))
|
||||||
|
* **ocp:** added default time in for each printer to allow different delays ([85e3d46](https://git.tuffraid.net/cowch/lstV2/commits/85e3d46b2e6e2bd80a5fe9ee3ce855bd7f0c6436))
|
||||||
|
* **ocp:** change the way logs are brought in and other changes to clean the code up ([2e2699a](https://git.tuffraid.net/cowch/lstV2/commits/2e2699ab3c3786f36206629f069cfbd293c2dc29))
|
||||||
|
* **serverpage:** added in linke to server by clicking the name ([ded074a](https://git.tuffraid.net/cowch/lstV2/commits/ded074a1ce5cbe0e018c6201d1d9903a1fade97b))
|
||||||
|
|
||||||
|
|
||||||
|
### 🐛 Bug fixes
|
||||||
|
|
||||||
|
* **database:** corrected spelling in the silo adjustment id ([b589bf9](https://git.tuffraid.net/cowch/lstV2/commits/b589bf972409f242b0cb6d2e3fb34f65417cc8bb))
|
||||||
|
* **labeling:** if label fails we want to stop the process and post the why ([92d251c](https://git.tuffraid.net/cowch/lstV2/commits/92d251c122618f27d01b84c861848ea5ff9d81cc))
|
||||||
|
* **lots:** if no sql it crashs due to lots returning a non error ([dd6895f](https://git.tuffraid.net/cowch/lstV2/commits/dd6895fac26d051e5f91094c4ca97fe59c924774))
|
||||||
|
* **ocp:** removed the auto labeler from cycleing due to causuing delay in printing ([95c869d](https://git.tuffraid.net/cowch/lstV2/commits/95c869d667901cc51c8fe3b35d59d3bc2ea085a5))
|
||||||
|
* **submodules:** spelling crrections ([31fbfa4](https://git.tuffraid.net/cowch/lstV2/commits/31fbfa4eb3652dce011eb359497453489b1e29fa))
|
||||||
|
|
||||||
|
|
||||||
|
### 📝 Testing Code
|
||||||
|
|
||||||
|
* **auth:** more and more auth setup ([b630bae](https://git.tuffraid.net/cowch/lstV2/commits/b630bae50d43602212c230b58248ba5f93743f0b))
|
||||||
|
* **auth:** more permission testing ([9deedd8](https://git.tuffraid.net/cowch/lstV2/commits/9deedd86e5964bfff37d85f63a990ff0f7d8a0b9))
|
||||||
|
* **auth:** testing auth stuff ([d8edfaf](https://git.tuffraid.net/cowch/lstV2/commits/d8edfaf05f25c1009fbd9b44ece0bdd1b2d2ae84))
|
||||||
|
* **front end:** added in card test but removing ([3241cf8](https://git.tuffraid.net/cowch/lstV2/commits/3241cf810afed96e8b2dda13603205d8bcbca0b6))
|
||||||
|
* **logger:** trying to understand why debug is not actually showing in the console ([4effb25](https://git.tuffraid.net/cowch/lstV2/commits/4effb25e9d180d3e55cc9dfd12fdfd2b18d7e8bd))
|
||||||
|
* **ppoo:** added inn query for ppoo ([7532c89](https://git.tuffraid.net/cowch/lstV2/commits/7532c89ae2b3bc5397e6f601d4332d93344dc56d))
|
||||||
|
* **reporting:** more reporting tables for different reports ([9325e58](https://git.tuffraid.net/cowch/lstV2/commits/9325e58551729acfda9042cf5fb0daacb1f901f1))
|
||||||
|
* **silo:** backend silo stuff ([b4a4dfc](https://git.tuffraid.net/cowch/lstV2/commits/b4a4dfcb75193a928e493e7a493d056d91a70cf7))
|
||||||
|
* **silos:** more base line silo data to be implemented ([4371fcc](https://git.tuffraid.net/cowch/lstV2/commits/4371fcc028d2636387fb02a7d78a2375aa196e1c))
|
||||||
|
* **test code:** new test folder for testing stuff ([525de7d](https://git.tuffraid.net/cowch/lstV2/commits/525de7dab219dee55c62baedd74338520150cb2a))
|
||||||
|
|
||||||
|
|
||||||
|
### 🌟 Enhancements
|
||||||
|
|
||||||
|
* **cyclecountcheck:** added i cycle count check this is in mem right now ([6665b77](https://git.tuffraid.net/cowch/lstV2/commits/6665b77e092553eaa17a267914cf85ddb0264f81))
|
||||||
|
* **datamart:** delivery by date ranged added in, includes inhouse ([d96cd44](https://git.tuffraid.net/cowch/lstV2/commits/d96cd4416ee1d30521e8e14eeb3df079f635bebd))
|
||||||
|
* **ocp page:** changed to resizable panels as its kinda customizable ([17b6c0a](https://git.tuffraid.net/cowch/lstV2/commits/17b6c0ac66041e2f5e9d21d8a929436fbd0b4272))
|
||||||
|
* **ocp:** completly moved ocp to lst ([51cc4aa](https://git.tuffraid.net/cowch/lstV2/commits/51cc4aa3701db036477f8577ea4fedcd414a60f5))
|
||||||
|
* **ocp:** printer cycling backend and frontend done :) ([dc5ee5b](https://git.tuffraid.net/cowch/lstV2/commits/dc5ee5b97aeba66518daaf74f4e74799cfa01ca4))
|
||||||
|
* **silo adjustments:** added in email if % wrong ([95bebbd](https://git.tuffraid.net/cowch/lstV2/commits/95bebbde2bb6c59e41253fc71ddf9cc2f8f95402))
|
||||||
|
* **silo:** added in charts and historical data ([bad390e](https://git.tuffraid.net/cowch/lstV2/commits/bad390ec17948ba80118662127bab21a3f3ce6e2))
|
||||||
|
* **silo:** adjustments completed :D ([75f94ea](https://git.tuffraid.net/cowch/lstV2/commits/75f94eae14fe5afd76a843231658f268a09031e2))
|
||||||
|
|
||||||
|
## [2.13.0](https://git.tuffraid.net/cowch/lstV2/compare/v2.12.0...v2.13.0) (2025-04-05)
|
||||||
|
|
||||||
|
|
||||||
|
### 📝 Chore
|
||||||
|
|
||||||
|
* **release:** bump build number to 148 ([2cc81a5](https://git.tuffraid.net/cowch/lstV2/commits/2cc81a5b07e6a31b6c7612bc8393b3e0614442fd))
|
||||||
|
|
||||||
|
|
||||||
|
### 🐛 Bug fixes
|
||||||
|
|
||||||
|
* **database:** correction to the printer modules ([8194798](https://git.tuffraid.net/cowch/lstV2/commits/8194798a3764d44abd7c1aef452ae2f4c8c100e9))
|
||||||
|
* **datamart:** added some fixed some ([5eacbb5](https://git.tuffraid.net/cowch/lstV2/commits/5eacbb5ecfe23ed9ac023649864d2d0a506dc657))
|
||||||
|
* **tcp:** added in a catch if ocme is not active and we dont have a zebra camera ([b9397c0](https://git.tuffraid.net/cowch/lstV2/commits/b9397c029f3c597d755c5b3ab3027dda2dfc0ef2))
|
||||||
|
|
||||||
|
|
||||||
|
### 🛠️ Code Refactor
|
||||||
|
|
||||||
|
* **materials:** moved for better sturcture ([99477ba](https://git.tuffraid.net/cowch/lstV2/commits/99477bac1974da3a0937b4244815a839416eaf40))
|
||||||
|
|
||||||
|
|
||||||
|
### 📝 Testing Code
|
||||||
|
|
||||||
|
* **frontend:** work on the frontend to have better admin ([ad5e770](https://git.tuffraid.net/cowch/lstV2/commits/ad5e77028d59c31405df6cc17fc0c8084dddad5a))
|
||||||
|
* **ocp:** working on more migrations ([9f26f23](https://git.tuffraid.net/cowch/lstV2/commits/9f26f2334f0bcae3ca26acd240ed9b638fe88b03))
|
||||||
|
|
||||||
|
|
||||||
|
### 🌟 Enhancements
|
||||||
|
|
||||||
|
* **notificaitons:** fixed and corrections to get them working properly ([a7818b4](https://git.tuffraid.net/cowch/lstV2/commits/a7818b4ca3bf2df530e3e7df8ec389bf4f5ebc5a))
|
||||||
|
* **siloadjustments:** added email for comments :D ([f1abe7b](https://git.tuffraid.net/cowch/lstV2/commits/f1abe7b33d7b390ee54bc0fa5bd4c39c156f4f05))
|
||||||
|
* **submodules and login redirect:** submodules added and login redirect ([85577b2](https://git.tuffraid.net/cowch/lstV2/commits/85577b291f60744749abfd815efd6feceb393478))
|
||||||
|
* **submodules:** to help with submodules of course ([e1973e4](https://git.tuffraid.net/cowch/lstV2/commits/e1973e4da659948e6d49f6f5d162a8b2fb8e512d))
|
||||||
|
* **update all:** added a new function to update all servers in a row. easier to walk away ([8b5698a](https://git.tuffraid.net/cowch/lstV2/commits/8b5698a8391260fcc400117562668434bbc9e8af))
|
||||||
|
|
||||||
|
## [2.12.0](https://git.tuffraid.net/cowch/lstV2/compare/v2.11.0...v2.12.0) (2025-04-03)
|
||||||
|
|
||||||
|
|
||||||
|
### 📝 Chore
|
||||||
|
|
||||||
|
* **release:** bump build number to 126 ([1156bbd](https://git.tuffraid.net/cowch/lstV2/commits/1156bbd223d5631e22d961963fca952709d1cf12))
|
||||||
|
* **release:** bump build number to 127 ([6d5bcde](https://git.tuffraid.net/cowch/lstV2/commits/6d5bcde88e9960a0565906edd270db294a0a9927))
|
||||||
|
* **release:** bump build number to 128 ([fb41fb1](https://git.tuffraid.net/cowch/lstV2/commits/fb41fb1dd180a2cfe523fa41990e929d0d3ce0fd))
|
||||||
|
* **release:** bump build number to 129 ([9394172](https://git.tuffraid.net/cowch/lstV2/commits/93941723ccb83c530591d5fedec1904d2a3a06f8))
|
||||||
|
* **release:** bump build number to 130 ([6ec9f58](https://git.tuffraid.net/cowch/lstV2/commits/6ec9f5827c98e355d32b78bed5fb757ae4c257b7))
|
||||||
|
* **release:** bump build number to 131 ([075bba9](https://git.tuffraid.net/cowch/lstV2/commits/075bba95ee86c2592101f7a72345e58affd2e24f))
|
||||||
|
* **release:** bump build number to 132 ([16b39fd](https://git.tuffraid.net/cowch/lstV2/commits/16b39fd386ad89867495c346e7a59162f88f6e73))
|
||||||
|
* **release:** bump build number to 133 ([8c6dc5f](https://git.tuffraid.net/cowch/lstV2/commits/8c6dc5f690c5517781435833cd5fd62dd912f377))
|
||||||
|
* **release:** bump build number to 134 ([8a639ce](https://git.tuffraid.net/cowch/lstV2/commits/8a639ceaf8b192d76f2823f9f141176403c0f688))
|
||||||
|
* **release:** bump build number to 135 ([0d06dae](https://git.tuffraid.net/cowch/lstV2/commits/0d06dae6de83a42f216c9ccdefbfebd5cce84a05))
|
||||||
|
* **release:** bump build number to 136 ([3e54685](https://git.tuffraid.net/cowch/lstV2/commits/3e54685a7e45258d53e54448b74a61752d607c9f))
|
||||||
|
* **release:** bump build number to 137 ([f442ced](https://git.tuffraid.net/cowch/lstV2/commits/f442cedff2e0b0487d7eff292fe30ff3b5f75bae))
|
||||||
|
* **release:** bump build number to 138 ([68dac0d](https://git.tuffraid.net/cowch/lstV2/commits/68dac0dd28e954301b1d04f37ab9c28c9a741050))
|
||||||
|
* **release:** bump build number to 139 ([7535e15](https://git.tuffraid.net/cowch/lstV2/commits/7535e15337ddd4a2dd61c0e9917fbbb3933d0d1c))
|
||||||
|
* **release:** bump build number to 140 ([459b0f2](https://git.tuffraid.net/cowch/lstV2/commits/459b0f287c4f02fcb81c0a5041f1d61472e85f86))
|
||||||
|
* **release:** bump build number to 141 ([29c9f2d](https://git.tuffraid.net/cowch/lstV2/commits/29c9f2d1be41205f2178fd54155001d31fc24e92))
|
||||||
|
* **release:** bump build number to 142 ([3babf8a](https://git.tuffraid.net/cowch/lstV2/commits/3babf8a7495f6204a4599619b66f9d01c99896b4))
|
||||||
|
* **release:** bump build number to 143 ([1dce3dc](https://git.tuffraid.net/cowch/lstV2/commits/1dce3dccdcc1a0921bf429e101d3426038f4fb8c))
|
||||||
|
* **release:** bump build number to 144 ([1fee4b7](https://git.tuffraid.net/cowch/lstV2/commits/1fee4b719bbda65574f474f29234a1d483d376cf))
|
||||||
|
* **release:** bump build number to 145 ([d10770b](https://git.tuffraid.net/cowch/lstV2/commits/d10770bc49793c58458b5c2e29967731c29d0105))
|
||||||
|
* **release:** bump build number to 146 ([77abaed](https://git.tuffraid.net/cowch/lstV2/commits/77abaed60ea236dad589bd66ba9337548b9c69a3))
|
||||||
|
* **release:** bump build number to 147 ([7e484a0](https://git.tuffraid.net/cowch/lstV2/commits/7e484a0f90f34addab780d019684d2321446081b))
|
||||||
|
|
||||||
|
|
||||||
|
### 📝 Testing Code
|
||||||
|
|
||||||
|
* **services:** testing remove restart and stop ([3355eb3](https://git.tuffraid.net/cowch/lstV2/commits/3355eb389ca81481ba25e057d0fb1f9dbc55fea1))
|
||||||
|
|
||||||
|
|
||||||
|
### 🛠️ Code Refactor
|
||||||
|
|
||||||
|
* **compile:** changes to keep the last 20 builds ([bc2336e](https://git.tuffraid.net/cowch/lstV2/commits/bc2336e46dd264c3f6006ccec4494a92879a087a))
|
||||||
|
* **ocme:** crashing for no reason added ?? ([4f3b5d7](https://git.tuffraid.net/cowch/lstV2/commits/4f3b5d75a28b3b19a8685f0282bb80caf7562135))
|
||||||
|
* **ocp:** more work on perfecting dyco and labeling ([8bdbc49](https://git.tuffraid.net/cowch/lstV2/commits/8bdbc4995c7c2251b263b94c9a377750a8ee0818))
|
||||||
|
|
||||||
|
|
||||||
|
### 🐛 Bug fixes
|
||||||
|
|
||||||
|
* **ocme:** cycle count typos ([ee3026f](https://git.tuffraid.net/cowch/lstV2/commits/ee3026fa7cfa290e973cce97a90b7f4bdc0d2a64))
|
||||||
|
* **ocp:** delivery changes to happen after bookin is done ([f771db6](https://git.tuffraid.net/cowch/lstV2/commits/f771db603483317c30182753f53d5ca55b5e4ec4))
|
||||||
|
* **perms:** fixed the location for the test update ([053c05c](https://git.tuffraid.net/cowch/lstV2/commits/053c05c1a797160364e999fdc4bfb2e276ccadd0))
|
||||||
|
* **sendmail:** if server not installed just stop ([de0ee3a](https://git.tuffraid.net/cowch/lstV2/commits/de0ee3a61c3eeb379b4c8b88990251943cd0b609))
|
||||||
|
* **ti intergraion:** chagnes to the special instructions ([a1f62a3](https://git.tuffraid.net/cowch/lstV2/commits/a1f62a3e5122a635fbe475919f33ee93b1f7a458))
|
||||||
|
* **update server missing migrate:** missing ([544e82c](https://git.tuffraid.net/cowch/lstV2/commits/544e82c01dce1204667fbf068cc5e92b772bf413))
|
||||||
|
* **updater:** fixed the iowa2 server so it has the correct port ([dd62ceb](https://git.tuffraid.net/cowch/lstV2/commits/dd62ceb133e924f0dcc1d666c1bdf7af61c67fdb))
|
||||||
|
|
||||||
|
|
||||||
|
### 🌟 Enhancements
|
||||||
|
|
||||||
|
* **datamart:** initial get active query migrated ([44507d4](https://git.tuffraid.net/cowch/lstV2/commits/44507d41c42f07cf3ab4825a848821dde4cf892d))
|
||||||
|
* **datamart:** total inv migrated over ([b2683d0](https://git.tuffraid.net/cowch/lstV2/commits/b2683d042921b6adc7ebf274bd079d3bd28aa2eb))
|
||||||
|
* **new server:** added mcd to the server setup ([f481197](https://git.tuffraid.net/cowch/lstV2/commits/f481197d6e0fe0280fde4b4223094c0af274bcbe))
|
||||||
|
* **notifications:** migrated all from v1 ([5c64280](https://git.tuffraid.net/cowch/lstV2/commits/5c642805b1db87ba5cbdde31d2579709c476aa1f))
|
||||||
|
* **ocp:** added dual printing back in ([814861e](https://git.tuffraid.net/cowch/lstV2/commits/814861e59cfefa8e5f07fa0ec1231b4b55c6f694))
|
||||||
|
* **servers:** added in jci lima sherman ([63e005b](https://git.tuffraid.net/cowch/lstV2/commits/63e005b790571e25a8c2a9bac1bccef2141cde92))
|
||||||
|
* **servers:** all servers in v2 meow ([d27611d](https://git.tuffraid.net/cowch/lstV2/commits/d27611d035f5b0ff5e5bc8ae262550d9c75b9c8c))
|
||||||
|
|
||||||
|
## [2.11.0](https://git.tuffraid.net/cowch/lstV2/compare/v2.10.0...v2.11.0) (2025-03-30)
|
||||||
|
|
||||||
|
|
||||||
|
### 🌟 Enhancements
|
||||||
|
|
||||||
|
* **auth:** admin user updates added ([a48d4bd](https://git.tuffraid.net/cowch/lstV2/commits/a48d4bd5afb53d9242a8ba13fef5dab2e2d0e4fe))
|
||||||
|
* **lst:** script added for the test server to readd the permissions once it boots up ([3228ad7](https://git.tuffraid.net/cowch/lstV2/commits/3228ad789206a2fd477060fa6849850af52523b1))
|
||||||
|
* **rfid:** work on the readers and there functions ([b5de644](https://git.tuffraid.net/cowch/lstV2/commits/b5de6445b382e7f7d7c8ce5893138a1a86a56eb2))
|
||||||
|
* **updater:** added in a delete function for the server side ([0ced135](https://git.tuffraid.net/cowch/lstV2/commits/0ced135ec38590fd599e9a45542768b3790eb3db))
|
||||||
|
|
||||||
|
|
||||||
|
### 📝 Chore
|
||||||
|
|
||||||
|
* **release:** bump build number to 100 ([c474536](https://git.tuffraid.net/cowch/lstV2/commits/c474536992659b7ca789a5841441f1634de7a6dc))
|
||||||
|
* **release:** bump build number to 101 ([52171c8](https://git.tuffraid.net/cowch/lstV2/commits/52171c87fc4b5f15d964e6695dd4d9c2710ab961))
|
||||||
|
* **release:** bump build number to 102 ([290f20b](https://git.tuffraid.net/cowch/lstV2/commits/290f20b86b81fa82458c0317215dd614f3de73c2))
|
||||||
|
* **release:** bump build number to 103 ([1386e0f](https://git.tuffraid.net/cowch/lstV2/commits/1386e0f00f54a54f5b7645f2c1c23ebdd3228e59))
|
||||||
|
* **release:** bump build number to 104 ([ca41069](https://git.tuffraid.net/cowch/lstV2/commits/ca4106945b2c09ee495821c8c2452b5254e4df37))
|
||||||
|
* **release:** bump build number to 105 ([a01c056](https://git.tuffraid.net/cowch/lstV2/commits/a01c0566c2413e2ba68106e26eb9dc09c415ba92))
|
||||||
|
* **release:** bump build number to 106 ([c32547c](https://git.tuffraid.net/cowch/lstV2/commits/c32547ceb831c510797da8c3d99745bd2a843a1b))
|
||||||
|
* **release:** bump build number to 107 ([175c722](https://git.tuffraid.net/cowch/lstV2/commits/175c7226eda3cdd3d63febf6e058171c72d0cb5e))
|
||||||
|
* **release:** bump build number to 108 ([7d47338](https://git.tuffraid.net/cowch/lstV2/commits/7d4733896e5f9578c60133cb5c871139e1ac332c))
|
||||||
|
* **release:** bump build number to 109 ([d58cb52](https://git.tuffraid.net/cowch/lstV2/commits/d58cb5286e85f49e327134f2b957c56fdd1a319a))
|
||||||
|
* **release:** bump build number to 110 ([d557728](https://git.tuffraid.net/cowch/lstV2/commits/d557728fa25c33a95ae99559ddc4ce7b2f7a0cad))
|
||||||
|
* **release:** bump build number to 111 ([f3103d8](https://git.tuffraid.net/cowch/lstV2/commits/f3103d8c1a027d3364540b9044a298346bce1ead))
|
||||||
|
* **release:** bump build number to 112 ([f0b9bd5](https://git.tuffraid.net/cowch/lstV2/commits/f0b9bd599a9da86b36dd952b8d3dc47116add380))
|
||||||
|
* **release:** bump build number to 113 ([ff1dfdd](https://git.tuffraid.net/cowch/lstV2/commits/ff1dfdde68335907e8e24f0f011cc611d5de3b0c))
|
||||||
|
* **release:** bump build number to 114 ([fb31ae7](https://git.tuffraid.net/cowch/lstV2/commits/fb31ae79d125c6b672608b56b02d9c7239250d19))
|
||||||
|
* **release:** bump build number to 115 ([ac7859f](https://git.tuffraid.net/cowch/lstV2/commits/ac7859fda34606874a05f8665fe7478cf79d7037))
|
||||||
|
* **release:** bump build number to 116 ([88258ba](https://git.tuffraid.net/cowch/lstV2/commits/88258baf9d71cba38f987851e62363563f28d6ae))
|
||||||
|
* **release:** bump build number to 116 ([82acfcc](https://git.tuffraid.net/cowch/lstV2/commits/82acfcc4a9effbdf5fe8debd4617b3cfca01c0ea))
|
||||||
|
* **release:** bump build number to 117 ([d046c4e](https://git.tuffraid.net/cowch/lstV2/commits/d046c4ea41d7b16f7fb109ae1ab728edd1dbcb97))
|
||||||
|
* **release:** bump build number to 118 ([1f7c33d](https://git.tuffraid.net/cowch/lstV2/commits/1f7c33d871ce408440739bfad16165aa0dd2f982))
|
||||||
|
* **release:** bump build number to 119 ([035eda9](https://git.tuffraid.net/cowch/lstV2/commits/035eda9aa8212443c1147d420fb30fdb09b3ff35))
|
||||||
|
* **release:** bump build number to 120 ([b903c8e](https://git.tuffraid.net/cowch/lstV2/commits/b903c8ee2d9f5c0cb63404f232f235d2f9ddeb81))
|
||||||
|
* **release:** bump build number to 121 ([af5dc92](https://git.tuffraid.net/cowch/lstV2/commits/af5dc9266f5a75c0065615f1526a2ee726b66a02))
|
||||||
|
* **release:** bump build number to 122 ([28fbf2c](https://git.tuffraid.net/cowch/lstV2/commits/28fbf2c1e43996c50eca7d3b7145bd7dec31f1de))
|
||||||
|
* **release:** bump build number to 123 ([09c0825](https://git.tuffraid.net/cowch/lstV2/commits/09c082519467c85240c8ed89123cb260c0011514))
|
||||||
|
* **release:** bump build number to 124 ([098c477](https://git.tuffraid.net/cowch/lstV2/commits/098c477119c5accb0146f7bd125f80197bb44210))
|
||||||
|
* **release:** bump build number to 125 ([a647d05](https://git.tuffraid.net/cowch/lstV2/commits/a647d05d3b8aa0ec3cd8fa1dc05fbed02476769a))
|
||||||
|
* **release:** bump build number to 93 ([b4e0f4c](https://git.tuffraid.net/cowch/lstV2/commits/b4e0f4c66687d8957fa81076687d0504582812aa))
|
||||||
|
* **release:** bump build number to 94 ([f39ae0f](https://git.tuffraid.net/cowch/lstV2/commits/f39ae0f590c17e4fc4b278296f86562c572bc6d2))
|
||||||
|
* **release:** bump build number to 95 ([278c553](https://git.tuffraid.net/cowch/lstV2/commits/278c5538bcea651f06c11f5be9f4948e328261c1))
|
||||||
|
* **release:** bump build number to 96 ([ca552d5](https://git.tuffraid.net/cowch/lstV2/commits/ca552d55878bc52e01186b09b6721af24faa445b))
|
||||||
|
* **release:** bump build number to 97 ([c03b61f](https://git.tuffraid.net/cowch/lstV2/commits/c03b61f48a32cef3e03f3da8d0f70edbcecd0e59))
|
||||||
|
* **release:** bump build number to 98 ([ea7801f](https://git.tuffraid.net/cowch/lstV2/commits/ea7801fccf7ecf176804fd10fac6db91321402d7))
|
||||||
|
* **release:** bump build number to 99 ([600a989](https://git.tuffraid.net/cowch/lstV2/commits/600a98922630f0694971e110db2f8bf997571e36))
|
||||||
|
|
||||||
|
|
||||||
|
### 🛠️ Code Refactor
|
||||||
|
|
||||||
|
* **format changes:** changes to the file formats to match across computers ([9784072](https://git.tuffraid.net/cowch/lstV2/commits/9784072aab3245d52b9a8d0d6a3a5a7716e61e0c))
|
||||||
|
* **logger:** changed log level to be in the env file vs hardcoded ([f9f68ce](https://git.tuffraid.net/cowch/lstV2/commits/f9f68ce969e6d87a23c1be21fd9877d2dfa6f6cc))
|
||||||
|
* **lst:** added huston backin ([11e5cf4](https://git.tuffraid.net/cowch/lstV2/commits/11e5cf4d865f93d65d870bff4bde96288c04db24))
|
||||||
|
* **lst:** added in a removal of old files so we can keep the server clean ([c27ad7c](https://git.tuffraid.net/cowch/lstV2/commits/c27ad7cf6a5ea2ee636c1b25a66773b07a897a3e))
|
||||||
|
* **ocme:** added new error in posting where we know when the pallet is not instock ([27d6b6e](https://git.tuffraid.net/cowch/lstV2/commits/27d6b6e88423ee201e30bbcc3747126c8567801c))
|
||||||
|
* **ocp:** finished the dashboard and move logs and labels to a tab style ([7b1c6e1](https://git.tuffraid.net/cowch/lstV2/commits/7b1c6e1361fcc93729c250db29e828d6d07ca387))
|
||||||
|
* **ocp:** lots of work for rfid and dyco contorl ([ba3d721](https://git.tuffraid.net/cowch/lstV2/commits/ba3d721940e800b61aeba6f3c81d9af40be01c9c))
|
||||||
|
* **server:** removed console logs ([a5dee58](https://git.tuffraid.net/cowch/lstV2/commits/a5dee582236d3c1ab581b63fd463439a4d9e8176))
|
||||||
|
|
||||||
|
|
||||||
|
### 🐛 Bug fixes
|
||||||
|
|
||||||
|
* **admin auth:** added in role change for v1 ([f9096b5](https://git.tuffraid.net/cowch/lstV2/commits/f9096b54f5902d19226e9e5728ffa4c64d8062f9))
|
||||||
|
* **logger:** changes to get the most recent verse aged ([2c8d1fb](https://git.tuffraid.net/cowch/lstV2/commits/2c8d1fb71045dcd241e62b4ee2f1c03ae3690e5b))
|
||||||
|
* **misc:** work on ocp to improve the errors that were missed and better logging ([63b1151](https://git.tuffraid.net/cowch/lstV2/commits/63b1151cb7e1d81b080c28dbec569c851fa1b48a))
|
||||||
|
* **ocme:** fixed to make sure we can always just update a runnning nunmber ([e3ba45a](https://git.tuffraid.net/cowch/lstV2/commits/e3ba45ae13ddc21525c6113bf0f6dca2d2965637))
|
||||||
|
|
||||||
|
## [2.10.0](https://git.tuffraid.net/cowch/lstV2/compare/v2.9.0...v2.10.0) (2025-03-27)
|
||||||
|
|
||||||
|
|
||||||
|
### 📝 Testing Code
|
||||||
|
|
||||||
|
* **ocme:** lots of changes to get it working in production ([6dd9ed8](https://git.tuffraid.net/cowch/lstV2/commits/6dd9ed848bc7d4e8a62778cfe36f89e077187157))
|
||||||
|
|
||||||
|
|
||||||
|
### 📈 Project changes
|
||||||
|
|
||||||
|
* **lst:** changes made to the settings file to work across all pvs ([5149de3](https://git.tuffraid.net/cowch/lstV2/commits/5149de3199d3aaf349b8a4c99d5db83f8d04ae49))
|
||||||
|
|
||||||
|
|
||||||
|
### 🐛 Bug fixes
|
||||||
|
|
||||||
|
* **logistics:** correction to the lane grab ([2d4b1db](https://git.tuffraid.net/cowch/lstV2/commits/2d4b1db5f4697770aee8829764bd85643893d3e8))
|
||||||
|
* **lst:** missing , in versionRc ([c35726b](https://git.tuffraid.net/cowch/lstV2/commits/c35726bf5ccd6565abda37c6618a34e975e70d41))
|
||||||
|
* **ocme:** corrections to posting data for the response was added ([dcb56d4](https://git.tuffraid.net/cowch/lstV2/commits/dcb56d427458c774b462e78daba6fee4afefd525))
|
||||||
|
* **ocme:** fixed some import errors ([b01980e](https://git.tuffraid.net/cowch/lstV2/commits/b01980e1c5a8833b25ea557a2da07b74560526e3))
|
||||||
|
* **ocme:** fixed the camera routes ([51267f5](https://git.tuffraid.net/cowch/lstV2/commits/51267f5202ceebe1c31c819395e1588d47657c38))
|
||||||
|
* **servers:** fixed the weird conflict import that happened ([8a040d1](https://git.tuffraid.net/cowch/lstV2/commits/8a040d15dbf5de5fbb9949b7834c39b93b145aa7))
|
||||||
|
|
||||||
|
|
||||||
|
### 📝 Chore
|
||||||
|
|
||||||
|
* bump build number to 50 ([9bdca33](https://git.tuffraid.net/cowch/lstV2/commits/9bdca3317c7c213f9c5853222eafe1ab028b5f64))
|
||||||
|
* **release:** bump build number to 52 ([5886bea](https://git.tuffraid.net/cowch/lstV2/commits/5886bea85da30fe43635e05de1e9bc4f5789fa64))
|
||||||
|
* **release:** bump build number to 55 ([0c5fc1d](https://git.tuffraid.net/cowch/lstV2/commits/0c5fc1dfb0a8bee5cf7414733a555fe1b5888b8e))
|
||||||
|
* **release:** bump build number to 56 ([335ea2d](https://git.tuffraid.net/cowch/lstV2/commits/335ea2deca54dacda2117849104bf4c24faee3e8))
|
||||||
|
* **release:** bump build number to 57 ([6843368](https://git.tuffraid.net/cowch/lstV2/commits/6843368c3682bb56e5ce4aafbb18367e96a6016e))
|
||||||
|
* **release:** bump build number to 58 ([0475bb3](https://git.tuffraid.net/cowch/lstV2/commits/0475bb30f9d6d4e2d132b15b24d9ab225d8de3b9))
|
||||||
|
* **release:** bump build number to 59 ([9395ec6](https://git.tuffraid.net/cowch/lstV2/commits/9395ec6cd4483f52fcca949a95a4ceecaa843f65))
|
||||||
|
* **release:** bump build number to 60 ([57e82d2](https://git.tuffraid.net/cowch/lstV2/commits/57e82d23603622c301c7e6d636f9cec07d44e0b2))
|
||||||
|
* **release:** bump build number to 61 ([5ed67f3](https://git.tuffraid.net/cowch/lstV2/commits/5ed67f3fc0f99ca5344da8b73fd005184b89670b))
|
||||||
|
* **release:** bump build number to 62 ([c1cc355](https://git.tuffraid.net/cowch/lstV2/commits/c1cc355f4f4e74c3897cada64d961b28d24c07b2))
|
||||||
|
* **release:** bump build number to 63 ([e1cad02](https://git.tuffraid.net/cowch/lstV2/commits/e1cad027d2714ddf3289e31b5c3bbb96306f1f56))
|
||||||
|
* **release:** bump build number to 64 ([63177b5](https://git.tuffraid.net/cowch/lstV2/commits/63177b523e2dd1fabefe52f52dd3c6b3fcff9bcf))
|
||||||
|
* **release:** bump build number to 65 ([3a4dc47](https://git.tuffraid.net/cowch/lstV2/commits/3a4dc47a368bb20f622b7e4647337c5e68150db9))
|
||||||
|
* **release:** bump build number to 66 ([b3b5fce](https://git.tuffraid.net/cowch/lstV2/commits/b3b5fcec651e2bc585ecd4be03be4288867b214f))
|
||||||
|
* **release:** bump build number to 67 ([cb01ef1](https://git.tuffraid.net/cowch/lstV2/commits/cb01ef1af17e9c83753e09a1528e6140a4104273))
|
||||||
|
* **release:** bump build number to 68 ([4664768](https://git.tuffraid.net/cowch/lstV2/commits/46647687dc9938ecf6e72a63f15afc0e29bebcc4))
|
||||||
|
* **release:** bump build number to 69 ([2c227f9](https://git.tuffraid.net/cowch/lstV2/commits/2c227f94287a6ce9c06b0a41772085ba1f4f0cd3))
|
||||||
|
* **release:** bump build number to 70 ([96abef7](https://git.tuffraid.net/cowch/lstV2/commits/96abef762b77361c857642a33acfb69c0bc00666))
|
||||||
|
* **release:** bump build number to 71 ([836f3e2](https://git.tuffraid.net/cowch/lstV2/commits/836f3e294b4d92673388023503e409592ef95ba3))
|
||||||
|
* **release:** bump build number to 72 ([abe53b8](https://git.tuffraid.net/cowch/lstV2/commits/abe53b8f5d9bfbf517c7f56c5d4df2e4586aedbd))
|
||||||
|
* **release:** bump build number to 73 ([5201012](https://git.tuffraid.net/cowch/lstV2/commits/5201012235181975cb89aee8dbc644ca4aa42210))
|
||||||
|
* **release:** bump build number to 74 ([529e922](https://git.tuffraid.net/cowch/lstV2/commits/529e922485303251349c081ad8b2e9bee08dd420))
|
||||||
|
* **release:** bump build number to 75 ([b8c028a](https://git.tuffraid.net/cowch/lstV2/commits/b8c028a6c1fa54afeb049fd42e666bc40690aa4e))
|
||||||
|
* **release:** bump build number to 76 ([9254e52](https://git.tuffraid.net/cowch/lstV2/commits/9254e528086b95ada8c9dc4468f4fbb5b39fbd68))
|
||||||
|
* **release:** bump build number to 77 ([4d4d6fc](https://git.tuffraid.net/cowch/lstV2/commits/4d4d6fc7a4885b4b1652ac125a2b39b8325b0d6e))
|
||||||
|
* **release:** bump build number to 78 ([36cdc7b](https://git.tuffraid.net/cowch/lstV2/commits/36cdc7b4bf3bf90a785bab4d9892e65f84cb162a))
|
||||||
|
* **release:** bump build number to 79 ([8d2721b](https://git.tuffraid.net/cowch/lstV2/commits/8d2721b0c2f6255affcd9ec08427e1b4e6771107))
|
||||||
|
* **release:** bump build number to 80 ([cacfd6d](https://git.tuffraid.net/cowch/lstV2/commits/cacfd6d2e0e11ab7dbc5cb443a58df7bf8d2b8bb))
|
||||||
|
* **release:** bump build number to 81 ([2509888](https://git.tuffraid.net/cowch/lstV2/commits/250988800e1429a1f46005ae54a2a07d31fac3a8))
|
||||||
|
* **release:** bump build number to 82 ([c2aa69a](https://git.tuffraid.net/cowch/lstV2/commits/c2aa69ab0a2f925944abd1b78af6a8698249bff8))
|
||||||
|
* **release:** bump build number to 83 ([7f946c0](https://git.tuffraid.net/cowch/lstV2/commits/7f946c095b8c0208c97bd1bb2c33cf466a04d125))
|
||||||
|
* **release:** bump build number to 84 ([4162543](https://git.tuffraid.net/cowch/lstV2/commits/416254353cd0a926aaf14c343db2ad18f025b230))
|
||||||
|
* **release:** bump build number to 85 ([5d61eb8](https://git.tuffraid.net/cowch/lstV2/commits/5d61eb879e102939df56928cd8d57eda561aabca))
|
||||||
|
* **release:** bump build number to 86 ([5ab813f](https://git.tuffraid.net/cowch/lstV2/commits/5ab813f37894136549de0a05e5b4e2491220d16d))
|
||||||
|
* **release:** bump build number to 87 ([509ef84](https://git.tuffraid.net/cowch/lstV2/commits/509ef8472688ba655c524a1068c3721559f5da11))
|
||||||
|
* **release:** bump build number to 88 ([c0a0589](https://git.tuffraid.net/cowch/lstV2/commits/c0a0589b3c860ae8202a5dd230c18a3463cce857))
|
||||||
|
* **release:** bump build number to 89 ([af076b8](https://git.tuffraid.net/cowch/lstV2/commits/af076b8e27b599c479e4e51f38487cf4cb3cfa34))
|
||||||
|
* **release:** bump build number to 90 ([04aa943](https://git.tuffraid.net/cowch/lstV2/commits/04aa9439205f12bfe10b3fdf76a211a7b8178ac1))
|
||||||
|
* **release:** bump build number to 91 ([a31e7ea](https://git.tuffraid.net/cowch/lstV2/commits/a31e7ea1634fd6b10e22dff4ba93157c2be711ac))
|
||||||
|
* **release:** bump build number to 92 ([878e650](https://git.tuffraid.net/cowch/lstV2/commits/878e650e6237345d825632dff0387a89c7eee088))
|
||||||
|
|
||||||
|
|
||||||
|
### 🌟 Enhancements
|
||||||
|
|
||||||
|
* **logistics:** added in return material by lane name and gets lane id ([58f7b43](https://git.tuffraid.net/cowch/lstV2/commits/58f7b4322d3e523620f827a580ff5534b0be5f6c))
|
||||||
|
* **notify:** intial nofity system added to monitor crashes and rfid wrapper ([eb051d5](https://git.tuffraid.net/cowch/lstV2/commits/eb051d51f21b1ad617851fa3f4a1b8ba2f4fe4ac))
|
||||||
|
* **ocme:** manual camera trigger for the wrapper added ([bc18211](https://git.tuffraid.net/cowch/lstV2/commits/bc1821132e30be6b3a36bae63ce52fd4007f74dd))
|
||||||
|
* **ocp:** add lots with scroll view was added ([9e9a56c](https://git.tuffraid.net/cowch/lstV2/commits/9e9a56cbb15782770daf7e4ab08b31ad23df6c27))
|
||||||
|
* **ocp:** added in printers get and add ([f90066c](https://git.tuffraid.net/cowch/lstV2/commits/f90066c09020ebac03a93059c8e41f8531812c8a))
|
||||||
|
* **ocp:** added labeling logs in ([ceaa25f](https://git.tuffraid.net/cowch/lstV2/commits/ceaa25f31e6da526abd0350881e21984c66b455a))
|
||||||
|
* **ocp:** added wrappercard into the mix ([3b5e82f](https://git.tuffraid.net/cowch/lstV2/commits/3b5e82fdc122824b4f59f00f2ed59b90813694ba))
|
||||||
|
* **ocp:** create and book in plus dyco controller implemented ([7a1a477](https://git.tuffraid.net/cowch/lstV2/commits/7a1a4773e71cab93f36071530dbb5561e7592ec7))
|
||||||
|
* **ocp:** prodlink check added ([f9cd3fb](https://git.tuffraid.net/cowch/lstV2/commits/f9cd3fb8815635fdd0736b573dec86d14b24a6a7))
|
||||||
|
* **server:** clearn up code ([fe0c500](https://git.tuffraid.net/cowch/lstV2/commits/fe0c500dcfe317b3f67d67474fda7cf6872f3f37))
|
||||||
|
|
||||||
|
|
||||||
|
### 🛠️ Code Refactor
|
||||||
|
|
||||||
|
* **frontend:** prettier change to formatting ([c71b514](https://git.tuffraid.net/cowch/lstV2/commits/c71b514d9add69c63e608b22bd8a936fa770b167))
|
||||||
|
* **ocme:** clean up on the getInfo endpoint ([b9f1909](https://git.tuffraid.net/cowch/lstV2/commits/b9f19095cbd86569b58bec99575d924db997e385))
|
||||||
|
* **ocme:** cleaup on pickedup ([73aa95a](https://git.tuffraid.net/cowch/lstV2/commits/73aa95a6937129a36f6ece10ef8d6fd5f01a2b27))
|
||||||
|
* **ocme:** corrections to endpoints to work with ocnme as intneeded ([e6e1cec](https://git.tuffraid.net/cowch/lstV2/commits/e6e1cecce33b3c8cd94cf6372601c92f268b12a5))
|
||||||
|
* **ocme:** removed some info logs as ocme calls alot ([96e7f74](https://git.tuffraid.net/cowch/lstV2/commits/96e7f742fe68cc98de3039bd3dbfb2d27f6d7204))
|
||||||
|
* **ocp:** moved printers to there own folder to keep everything clean ([030f9f9](https://git.tuffraid.net/cowch/lstV2/commits/030f9f9aacdfcca1298a26be4442f5629626ba79))
|
||||||
|
* **rfid:** refactored station 3 (lines) and complete logic ([bd11feb](https://git.tuffraid.net/cowch/lstV2/commits/bd11feb1365ffb058283eb9384684c199ef9fd21))
|
||||||
|
* **rfid:** refactored the way the wrapper works to indlude backup dyco plan ([90e9bb0](https://git.tuffraid.net/cowch/lstV2/commits/90e9bb0ff6a2f598b055fae931a0d3c78f93e868))
|
||||||
|
* **server:** changed to log only when in dev, and removed the redirect of the url ([adf0880](https://git.tuffraid.net/cowch/lstV2/commits/adf08806593fdcd3a3d9d0a6d07f0262501e21ad))
|
||||||
|
* **tcpserver:** just the tcp server doing something ([04eb2e3](https://git.tuffraid.net/cowch/lstV2/commits/04eb2e3e145ba99b330ab627fcd9bae436e17fcf))
|
||||||
|
* **updateserver:** removed ocme from starting back up as it was migrated ([2551d6c](https://git.tuffraid.net/cowch/lstV2/commits/2551d6c9074a0338224d81e690600a7a4b9c9777))
|
||||||
|
|
||||||
## [2.9.0](https://git.tuffraid.net/cowch/lstV2/compare/v2.8.0...v2.9.0) (2025-03-23)
|
## [2.9.0](https://git.tuffraid.net/cowch/lstV2/compare/v2.8.0...v2.9.0) (2025-03-23)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import {drizzle} from "drizzle-orm/postgres-js";
|
import { drizzle } from "drizzle-orm/postgres-js";
|
||||||
import postgres from "postgres";
|
import postgres from "postgres";
|
||||||
import dotenv from "dotenv";
|
import dotenv from "dotenv";
|
||||||
|
|
||||||
@@ -6,6 +6,17 @@ dotenv.config();
|
|||||||
|
|
||||||
const database = process.env.DATABASE_URL || "";
|
const database = process.env.DATABASE_URL || "";
|
||||||
|
|
||||||
const queryClient = postgres(database);
|
const queryClient = postgres(database, {
|
||||||
|
max: 10,
|
||||||
|
idle_timeout: 60,
|
||||||
|
connect_timeout: 10,
|
||||||
|
max_lifetime: 1000 * 60 * 5,
|
||||||
|
onnotice: (notice) => {
|
||||||
|
console.log("PG NOTICE:", notice.message);
|
||||||
|
},
|
||||||
|
// debug: (...args) => {
|
||||||
|
// console.log("QUERY DEBUG:", ...args);
|
||||||
|
// },
|
||||||
|
});
|
||||||
|
|
||||||
export const db = drizzle({client: queryClient});
|
export const db = drizzle({ client: queryClient });
|
||||||
|
|||||||
17
database/migrations/0026_daily_the_twelve.sql
Normal file
17
database/migrations/0026_daily_the_twelve.sql
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
CREATE TABLE "printers" (
|
||||||
|
"printer_id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||||
|
"humanReadableId" text,
|
||||||
|
"name" text NOT NULL,
|
||||||
|
"ipAddress" text,
|
||||||
|
"port" numeric NOT NULL,
|
||||||
|
"status" text,
|
||||||
|
"statusText" text NOT NULL,
|
||||||
|
"lastTimePrinted" text,
|
||||||
|
"assigned" boolean DEFAULT false NOT NULL,
|
||||||
|
"remark" text,
|
||||||
|
"monitorState" boolean DEFAULT false NOT NULL,
|
||||||
|
"add_Date" timestamp DEFAULT now(),
|
||||||
|
"upd_date" timestamp DEFAULT now()
|
||||||
|
);
|
||||||
|
--> statement-breakpoint
|
||||||
|
CREATE UNIQUE INDEX "humanReadableId" ON "printers" USING btree ("name");
|
||||||
3
database/migrations/0027_needy_sleepwalker.sql
Normal file
3
database/migrations/0027_needy_sleepwalker.sql
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
ALTER TABLE "printers" ALTER COLUMN "statusText" DROP NOT NULL;--> statement-breakpoint
|
||||||
|
ALTER TABLE "printers" ALTER COLUMN "assigned" DROP NOT NULL;--> statement-breakpoint
|
||||||
|
ALTER TABLE "printers" ALTER COLUMN "monitorState" DROP NOT NULL;
|
||||||
1
database/migrations/0028_fast_wong.sql
Normal file
1
database/migrations/0028_fast_wong.sql
Normal file
@@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE "printers" ALTER COLUMN "port" DROP NOT NULL;
|
||||||
2
database/migrations/0029_giant_blue_blade.sql
Normal file
2
database/migrations/0029_giant_blue_blade.sql
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
DROP INDEX "humanReadableId";--> statement-breakpoint
|
||||||
|
CREATE UNIQUE INDEX "humanReadableId" ON "printers" USING btree ("humanReadableId");
|
||||||
4
database/migrations/0030_conscious_cable.sql
Normal file
4
database/migrations/0030_conscious_cable.sql
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
CREATE TABLE "prodlabels" (
|
||||||
|
"label_id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||||
|
"runningNr" integer NOT NULL
|
||||||
|
);
|
||||||
7
database/migrations/0031_loud_alex_power.sql
Normal file
7
database/migrations/0031_loud_alex_power.sql
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
ALTER TABLE "prodlabels" ADD COLUMN "printerID" integer;--> statement-breakpoint
|
||||||
|
ALTER TABLE "prodlabels" ADD COLUMN "printerName" text;--> statement-breakpoint
|
||||||
|
ALTER TABLE "prodlabels" ADD COLUMN "line" integer;--> statement-breakpoint
|
||||||
|
ALTER TABLE "prodlabels" ADD COLUMN "status" text;--> statement-breakpoint
|
||||||
|
ALTER TABLE "prodlabels" ADD COLUMN "add_date" timestamp;--> statement-breakpoint
|
||||||
|
ALTER TABLE "prodlabels" ADD COLUMN "upd_date" timestamp;--> statement-breakpoint
|
||||||
|
CREATE UNIQUE INDEX "runningNr" ON "prodlabels" USING btree ("runningNr");
|
||||||
4
database/migrations/0032_tough_iron_monger.sql
Normal file
4
database/migrations/0032_tough_iron_monger.sql
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
ALTER TABLE "prodlabels" ALTER COLUMN "add_date" SET DEFAULT now();--> statement-breakpoint
|
||||||
|
ALTER TABLE "prodlabels" ALTER COLUMN "upd_date" SET DEFAULT now();--> statement-breakpoint
|
||||||
|
ALTER TABLE "prodlabels" ADD COLUMN "add_user" text DEFAULT 'lst';--> statement-breakpoint
|
||||||
|
CREATE UNIQUE INDEX "ocme_runningNr" ON "ocmeData" USING btree ("runningNr");
|
||||||
13
database/migrations/0033_flimsy_salo.sql
Normal file
13
database/migrations/0033_flimsy_salo.sql
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
CREATE TABLE "notifications" (
|
||||||
|
"notify_id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||||
|
"name" text NOT NULL,
|
||||||
|
"description" text NOT NULL,
|
||||||
|
"checkInterval" text DEFAULT '1',
|
||||||
|
"timeType" text DEFAULT 'hour',
|
||||||
|
"emails" text,
|
||||||
|
"active" boolean DEFAULT false,
|
||||||
|
"lastRan" timestamp DEFAULT now(),
|
||||||
|
"notifiySettings" jsonb DEFAULT '{}'::jsonb
|
||||||
|
);
|
||||||
|
--> statement-breakpoint
|
||||||
|
CREATE UNIQUE INDEX "notify_name" ON "notifications" USING btree ("name");
|
||||||
2
database/migrations/0034_massive_penance.sql
Normal file
2
database/migrations/0034_massive_penance.sql
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE "printers" ALTER COLUMN "lastTimePrinted" SET DATA TYPE timestamp;--> statement-breakpoint
|
||||||
|
ALTER TABLE "printers" ADD COLUMN "printDelay" numeric;
|
||||||
2
database/migrations/0035_even_adam_warlock.sql
Normal file
2
database/migrations/0035_even_adam_warlock.sql
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE "printers" ALTER COLUMN "lastTimePrinted" SET DEFAULT now();--> statement-breakpoint
|
||||||
|
ALTER TABLE "printers" ALTER COLUMN "lastTimePrinted" SET NOT NULL;
|
||||||
1
database/migrations/0036_fixed_spacker_dave.sql
Normal file
1
database/migrations/0036_fixed_spacker_dave.sql
Normal file
@@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE "printers" ALTER COLUMN "lastTimePrinted" SET DATA TYPE timestamp with time zone;
|
||||||
1
database/migrations/0037_cooing_orphan.sql
Normal file
1
database/migrations/0037_cooing_orphan.sql
Normal file
@@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE "printers" DROP COLUMN "lastTimePrinted";
|
||||||
1
database/migrations/0038_lumpy_kitty_pryde.sql
Normal file
1
database/migrations/0038_lumpy_kitty_pryde.sql
Normal file
@@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE "printers" DROP COLUMN "printDelay";
|
||||||
19
database/migrations/0039_greedy_steve_rogers.sql
Normal file
19
database/migrations/0039_greedy_steve_rogers.sql
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
CREATE TABLE "printerData" (
|
||||||
|
"printer_id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||||
|
"humanReadableId" text,
|
||||||
|
"name" text NOT NULL,
|
||||||
|
"ipAddress" text,
|
||||||
|
"port" numeric,
|
||||||
|
"status" text,
|
||||||
|
"statusText" text,
|
||||||
|
"lastTimePrinted" timestamp DEFAULT now() NOT NULL,
|
||||||
|
"assigned" boolean DEFAULT false,
|
||||||
|
"remark" text,
|
||||||
|
"printDelay" numeric,
|
||||||
|
"monitorState" boolean DEFAULT false,
|
||||||
|
"add_Date" timestamp DEFAULT now(),
|
||||||
|
"upd_date" timestamp DEFAULT now()
|
||||||
|
);
|
||||||
|
--> statement-breakpoint
|
||||||
|
DROP TABLE "printers" CASCADE;--> statement-breakpoint
|
||||||
|
CREATE UNIQUE INDEX "humanReadableId" ON "printerData" USING btree ("humanReadableId");
|
||||||
17
database/migrations/0040_luxuriant_aqueduct.sql
Normal file
17
database/migrations/0040_luxuriant_aqueduct.sql
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
CREATE TABLE "subModules" (
|
||||||
|
"submodule_id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||||
|
"moduleName" text NOT NULL,
|
||||||
|
"name" text NOT NULL,
|
||||||
|
"description" text,
|
||||||
|
"link" text NOT NULL,
|
||||||
|
"active" boolean DEFAULT false,
|
||||||
|
"roles" jsonb DEFAULT '["systemAdmin"]'::jsonb NOT NULL,
|
||||||
|
"subSubModule" jsonb DEFAULT '[]'::jsonb,
|
||||||
|
"add_User" text DEFAULT 'LST_System' NOT NULL,
|
||||||
|
"add_Date" timestamp DEFAULT now(),
|
||||||
|
"upd_User" text DEFAULT 'LST_System' NOT NULL,
|
||||||
|
"upd_date" timestamp DEFAULT now()
|
||||||
|
);
|
||||||
|
--> statement-breakpoint
|
||||||
|
ALTER TABLE "subModules" ADD CONSTRAINT "subModules_moduleName_modules_name_fk" FOREIGN KEY ("moduleName") REFERENCES "public"."modules"("name") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||||
|
CREATE UNIQUE INDEX "subModule_name" ON "subModules" USING btree ("name");
|
||||||
1
database/migrations/0041_wise_molten_man.sql
Normal file
1
database/migrations/0041_wise_molten_man.sql
Normal file
@@ -0,0 +1 @@
|
|||||||
|
DROP INDEX "subModule_name";
|
||||||
3
database/migrations/0042_big_power_pack.sql
Normal file
3
database/migrations/0042_big_power_pack.sql
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
ALTER TABLE "subModules" DROP CONSTRAINT "subModules_moduleName_modules_name_fk";
|
||||||
|
--> statement-breakpoint
|
||||||
|
ALTER TABLE "subModules" ALTER COLUMN "moduleName" DROP NOT NULL;
|
||||||
12
database/migrations/0043_free_winter_soldier.sql
Normal file
12
database/migrations/0043_free_winter_soldier.sql
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
CREATE TABLE "siloAdjustments" (
|
||||||
|
"lsiloAdjust_id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||||
|
"level" integer,
|
||||||
|
"locationID" integer,
|
||||||
|
"currentStockLevel" numeric,
|
||||||
|
"newLevel" numeric,
|
||||||
|
"comments" text DEFAULT '',
|
||||||
|
"dateAdjusted" timestamp DEFAULT now(),
|
||||||
|
"lastDateAdjusted" timestamp DEFAULT now(),
|
||||||
|
"statusMessage" text DEFAULT '',
|
||||||
|
"add_user" text DEFAULT 'LST_Serivce'
|
||||||
|
);
|
||||||
5
database/migrations/0044_hot_smasher.sql
Normal file
5
database/migrations/0044_hot_smasher.sql
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
ALTER TABLE "siloAdjustments" ADD COLUMN "comment" text DEFAULT '';--> statement-breakpoint
|
||||||
|
ALTER TABLE "siloAdjustments" ADD COLUMN "commentAddedBy" text;--> statement-breakpoint
|
||||||
|
ALTER TABLE "siloAdjustments" ADD COLUMN "commentDate" text;--> statement-breakpoint
|
||||||
|
ALTER TABLE "siloAdjustments" DROP COLUMN "comments";--> statement-breakpoint
|
||||||
|
ALTER TABLE "siloAdjustments" DROP COLUMN "statusMessage";
|
||||||
1
database/migrations/0045_heavy_ravenous.sql
Normal file
1
database/migrations/0045_heavy_ravenous.sql
Normal file
@@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE "siloAdjustments" ADD COLUMN "commentKey" text;
|
||||||
1
database/migrations/0046_keen_firebird.sql
Normal file
1
database/migrations/0046_keen_firebird.sql
Normal file
@@ -0,0 +1 @@
|
|||||||
|
CREATE UNIQUE INDEX "subModule_name" ON "subModules" USING btree ("name");
|
||||||
1
database/migrations/0047_silky_starbolt.sql
Normal file
1
database/migrations/0047_silky_starbolt.sql
Normal file
@@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE "subModules" ADD COLUMN "icon" text;
|
||||||
2
database/migrations/0048_tearful_bushwacker.sql
Normal file
2
database/migrations/0048_tearful_bushwacker.sql
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE "siloAdjustments" RENAME COLUMN "lsiloAdjust_id" TO "siloAdjust_id";--> statement-breakpoint
|
||||||
|
ALTER TABLE "printerData" ALTER COLUMN "printDelay" SET DEFAULT '90';
|
||||||
23
database/migrations/0049_certain_tarot.sql
Normal file
23
database/migrations/0049_certain_tarot.sql
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
CREATE TABLE "qualityRequest" (
|
||||||
|
"request_id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||||
|
"article" numeric,
|
||||||
|
"description" text,
|
||||||
|
"runningNr" text,
|
||||||
|
"lotNr" numeric,
|
||||||
|
"warehouseAtRequest" text,
|
||||||
|
"locationAtRequest" text,
|
||||||
|
"warehouseMovedTo" text,
|
||||||
|
"locationMovedTo" text,
|
||||||
|
"durationToMove" numeric,
|
||||||
|
"locationDropOff" text,
|
||||||
|
"palletStatus" numeric,
|
||||||
|
"palletStatusText" text,
|
||||||
|
"palletRequest" numeric,
|
||||||
|
"add_date" timestamp DEFAULT now(),
|
||||||
|
"add_user" text DEFAULT 'LST',
|
||||||
|
"upd_date" timestamp DEFAULT now(),
|
||||||
|
"upd_user" text DEFAULT 'LST'
|
||||||
|
);
|
||||||
|
--> statement-breakpoint
|
||||||
|
ALTER TABLE "rfidReaders" ADD COLUMN "lastTagScanned" text;--> statement-breakpoint
|
||||||
|
ALTER TABLE "logs" DROP COLUMN "checkedAt";
|
||||||
3
database/migrations/0050_flat_nuke.sql
Normal file
3
database/migrations/0050_flat_nuke.sql
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
ALTER TABLE "qualityRequest" ALTER COLUMN "durationToMove" SET DATA TYPE integer;--> statement-breakpoint
|
||||||
|
ALTER TABLE "qualityRequest" ALTER COLUMN "palletStatus" SET DATA TYPE integer;--> statement-breakpoint
|
||||||
|
ALTER TABLE "qualityRequest" ALTER COLUMN "palletRequest" SET DATA TYPE integer;
|
||||||
10
database/migrations/0051_oval_warpath.sql
Normal file
10
database/migrations/0051_oval_warpath.sql
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
CREATE TABLE "ocmeCycleCounts" (
|
||||||
|
"ocme_id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||||
|
"laneId" integer,
|
||||||
|
"warehouseName" numeric NOT NULL,
|
||||||
|
"laneName" numeric NOT NULL,
|
||||||
|
"good" boolean DEFAULT false,
|
||||||
|
"cycleCount" jsonb DEFAULT '[]'::jsonb,
|
||||||
|
"add_User" text DEFAULT 'LST_System' NOT NULL,
|
||||||
|
"add_Date" timestamp DEFAULT now()
|
||||||
|
);
|
||||||
3
database/migrations/0052_dark_human_torch.sql
Normal file
3
database/migrations/0052_dark_human_torch.sql
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
ALTER TABLE "ocmeCycleCounts" ALTER COLUMN "laneId" SET NOT NULL;--> statement-breakpoint
|
||||||
|
ALTER TABLE "ocmeCycleCounts" ALTER COLUMN "warehouseName" SET DATA TYPE text;--> statement-breakpoint
|
||||||
|
ALTER TABLE "ocmeCycleCounts" ALTER COLUMN "laneName" SET DATA TYPE text;
|
||||||
1168
database/migrations/meta/0026_snapshot.json
Normal file
1168
database/migrations/meta/0026_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1168
database/migrations/meta/0027_snapshot.json
Normal file
1168
database/migrations/meta/0027_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1168
database/migrations/meta/0028_snapshot.json
Normal file
1168
database/migrations/meta/0028_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1168
database/migrations/meta/0029_snapshot.json
Normal file
1168
database/migrations/meta/0029_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1194
database/migrations/meta/0030_snapshot.json
Normal file
1194
database/migrations/meta/0030_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1246
database/migrations/meta/0031_snapshot.json
Normal file
1246
database/migrations/meta/0031_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1271
database/migrations/meta/0032_snapshot.json
Normal file
1271
database/migrations/meta/0032_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1360
database/migrations/meta/0033_snapshot.json
Normal file
1360
database/migrations/meta/0033_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1366
database/migrations/meta/0034_snapshot.json
Normal file
1366
database/migrations/meta/0034_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1367
database/migrations/meta/0035_snapshot.json
Normal file
1367
database/migrations/meta/0035_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1367
database/migrations/meta/0036_snapshot.json
Normal file
1367
database/migrations/meta/0036_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1360
database/migrations/meta/0037_snapshot.json
Normal file
1360
database/migrations/meta/0037_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1354
database/migrations/meta/0038_snapshot.json
Normal file
1354
database/migrations/meta/0038_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1367
database/migrations/meta/0039_snapshot.json
Normal file
1367
database/migrations/meta/0039_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1490
database/migrations/meta/0040_snapshot.json
Normal file
1490
database/migrations/meta/0040_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1474
database/migrations/meta/0041_snapshot.json
Normal file
1474
database/migrations/meta/0041_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1460
database/migrations/meta/0042_snapshot.json
Normal file
1460
database/migrations/meta/0042_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1539
database/migrations/meta/0043_snapshot.json
Normal file
1539
database/migrations/meta/0043_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1544
database/migrations/meta/0044_snapshot.json
Normal file
1544
database/migrations/meta/0044_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1550
database/migrations/meta/0045_snapshot.json
Normal file
1550
database/migrations/meta/0045_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1566
database/migrations/meta/0046_snapshot.json
Normal file
1566
database/migrations/meta/0046_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1572
database/migrations/meta/0047_snapshot.json
Normal file
1572
database/migrations/meta/0047_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1573
database/migrations/meta/0048_snapshot.json
Normal file
1573
database/migrations/meta/0048_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1699
database/migrations/meta/0049_snapshot.json
Normal file
1699
database/migrations/meta/0049_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1699
database/migrations/meta/0050_snapshot.json
Normal file
1699
database/migrations/meta/0050_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1765
database/migrations/meta/0051_snapshot.json
Normal file
1765
database/migrations/meta/0051_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1765
database/migrations/meta/0052_snapshot.json
Normal file
1765
database/migrations/meta/0052_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -183,6 +183,195 @@
|
|||||||
"when": 1742655504936,
|
"when": 1742655504936,
|
||||||
"tag": "0025_amusing_sugar_man",
|
"tag": "0025_amusing_sugar_man",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 26,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1742914066219,
|
||||||
|
"tag": "0026_daily_the_twelve",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 27,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1742917145140,
|
||||||
|
"tag": "0027_needy_sleepwalker",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 28,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1742917676211,
|
||||||
|
"tag": "0028_fast_wong",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 29,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1742917978318,
|
||||||
|
"tag": "0029_giant_blue_blade",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 30,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1742938986653,
|
||||||
|
"tag": "0030_conscious_cable",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 31,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1742939306614,
|
||||||
|
"tag": "0031_loud_alex_power",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 32,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1743124980863,
|
||||||
|
"tag": "0032_tough_iron_monger",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 33,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1743424730855,
|
||||||
|
"tag": "0033_flimsy_salo",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 34,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1743720994399,
|
||||||
|
"tag": "0034_massive_penance",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 35,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1743721140937,
|
||||||
|
"tag": "0035_even_adam_warlock",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 36,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1743721251498,
|
||||||
|
"tag": "0036_fixed_spacker_dave",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 37,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1743721424503,
|
||||||
|
"tag": "0037_cooing_orphan",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 38,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1743729665453,
|
||||||
|
"tag": "0038_lumpy_kitty_pryde",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 39,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1743771209867,
|
||||||
|
"tag": "0039_greedy_steve_rogers",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 40,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1743776921664,
|
||||||
|
"tag": "0040_luxuriant_aqueduct",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 41,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1743778410407,
|
||||||
|
"tag": "0041_wise_molten_man",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 42,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1743778477759,
|
||||||
|
"tag": "0042_big_power_pack",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 43,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1743809547351,
|
||||||
|
"tag": "0043_free_winter_soldier",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 44,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1743811709366,
|
||||||
|
"tag": "0044_hot_smasher",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 45,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1743819367359,
|
||||||
|
"tag": "0045_heavy_ravenous",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 46,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1743821039322,
|
||||||
|
"tag": "0046_keen_firebird",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 47,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1743822056329,
|
||||||
|
"tag": "0047_silky_starbolt",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 48,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1743946411873,
|
||||||
|
"tag": "0048_tearful_bushwacker",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 49,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1744649552936,
|
||||||
|
"tag": "0049_certain_tarot",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 50,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1744681925049,
|
||||||
|
"tag": "0050_flat_nuke",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 51,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1744684445081,
|
||||||
|
"tag": "0051_oval_warpath",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 52,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1744685129838,
|
||||||
|
"tag": "0052_dark_human_torch",
|
||||||
|
"breakpoints": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,15 @@
|
|||||||
import {text, pgTable, numeric, index, timestamp, boolean, uuid, uniqueIndex} from "drizzle-orm/pg-core";
|
import {
|
||||||
import {createInsertSchema, createSelectSchema} from "drizzle-zod";
|
text,
|
||||||
import {z} from "zod";
|
pgTable,
|
||||||
|
numeric,
|
||||||
|
index,
|
||||||
|
timestamp,
|
||||||
|
boolean,
|
||||||
|
uuid,
|
||||||
|
uniqueIndex,
|
||||||
|
} from "drizzle-orm/pg-core";
|
||||||
|
import { createInsertSchema, createSelectSchema } from "drizzle-zod";
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
export const logs = pgTable(
|
export const logs = pgTable(
|
||||||
"logs",
|
"logs",
|
||||||
@@ -11,7 +20,7 @@ export const logs = pgTable(
|
|||||||
service: text("service").notNull().default("system"),
|
service: text("service").notNull().default("system"),
|
||||||
message: text("message").notNull(),
|
message: text("message").notNull(),
|
||||||
checked: boolean("checked").default(false),
|
checked: boolean("checked").default(false),
|
||||||
checkedAt: timestamp("checkedAt"),
|
//checkedAt: timestamp("checkedAt"),
|
||||||
created_at: timestamp("add_Date").defaultNow(),
|
created_at: timestamp("add_Date").defaultNow(),
|
||||||
},
|
},
|
||||||
(table) => [
|
(table) => [
|
||||||
|
|||||||
36
database/schema/notifications.ts
Normal file
36
database/schema/notifications.ts
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import {
|
||||||
|
boolean,
|
||||||
|
jsonb,
|
||||||
|
pgTable,
|
||||||
|
text,
|
||||||
|
timestamp,
|
||||||
|
uniqueIndex,
|
||||||
|
uuid,
|
||||||
|
} from "drizzle-orm/pg-core";
|
||||||
|
import { createSelectSchema } from "drizzle-zod";
|
||||||
|
|
||||||
|
export const notifications = pgTable(
|
||||||
|
"notifications",
|
||||||
|
{
|
||||||
|
notify_id: uuid("notify_id").defaultRandom().primaryKey(),
|
||||||
|
name: text("name").notNull(),
|
||||||
|
description: text("description").notNull(),
|
||||||
|
checkInterval: text("checkInterval").default("1"),
|
||||||
|
timeType: text("timeType").default("hour"),
|
||||||
|
emails: text("emails"),
|
||||||
|
active: boolean("active").default(false),
|
||||||
|
lastRan: timestamp("lastRan").defaultNow(),
|
||||||
|
notifiySettings: jsonb("notifiySettings").default({}),
|
||||||
|
},
|
||||||
|
(table) => [
|
||||||
|
// uniqueIndex('emailUniqueIndex').on(sql`lower(${table.email})`),
|
||||||
|
uniqueIndex("notify_name").on(table.name),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Schema for inserting a user - can be used to validate API requests
|
||||||
|
// export const insertRolesSchema = createInsertSchema(roles, {
|
||||||
|
// name: z.string().min(3, {message: "Role name must be more than 3 letters"}),
|
||||||
|
// });
|
||||||
|
// Schema for selecting a Expenses - can be used to validate API responses
|
||||||
|
export const selectNotificationsSchema = createSelectSchema(notifications);
|
||||||
@@ -1,6 +1,15 @@
|
|||||||
import {text, pgTable, numeric, index, timestamp, boolean, uuid, uniqueIndex} from "drizzle-orm/pg-core";
|
import {
|
||||||
import {createInsertSchema, createSelectSchema} from "drizzle-zod";
|
text,
|
||||||
import {z} from "zod";
|
pgTable,
|
||||||
|
numeric,
|
||||||
|
index,
|
||||||
|
timestamp,
|
||||||
|
boolean,
|
||||||
|
uuid,
|
||||||
|
uniqueIndex,
|
||||||
|
} from "drizzle-orm/pg-core";
|
||||||
|
import { createInsertSchema, createSelectSchema } from "drizzle-zod";
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
export const ocmeData = pgTable(
|
export const ocmeData = pgTable(
|
||||||
"ocmeData",
|
"ocmeData",
|
||||||
@@ -20,6 +29,7 @@ export const ocmeData = pgTable(
|
|||||||
(table) => [
|
(table) => [
|
||||||
// uniqueIndex('emailUniqueIndex').on(sql`lower(${table.email})`),
|
// uniqueIndex('emailUniqueIndex').on(sql`lower(${table.email})`),
|
||||||
// uniqueIndex("role_name").on(table.name),
|
// uniqueIndex("role_name").on(table.name),
|
||||||
|
uniqueIndex("ocme_runningNr").on(table.runningNr),
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
37
database/schema/ocmeCycleCounts.ts
Normal file
37
database/schema/ocmeCycleCounts.ts
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import {
|
||||||
|
text,
|
||||||
|
pgTable,
|
||||||
|
numeric,
|
||||||
|
timestamp,
|
||||||
|
boolean,
|
||||||
|
uuid,
|
||||||
|
integer,
|
||||||
|
jsonb,
|
||||||
|
} from "drizzle-orm/pg-core";
|
||||||
|
import { createSelectSchema } from "drizzle-zod";
|
||||||
|
|
||||||
|
export const ocmeCycleCounts = pgTable(
|
||||||
|
"ocmeCycleCounts",
|
||||||
|
{
|
||||||
|
ocme_id: uuid("ocme_id").defaultRandom().primaryKey(),
|
||||||
|
laneId: integer("laneId").notNull(),
|
||||||
|
warehouseName: text("warehouseName").notNull(),
|
||||||
|
laneName: text("laneName").notNull(),
|
||||||
|
good: boolean("good").default(false),
|
||||||
|
cycleCount: jsonb("cycleCount").default([]),
|
||||||
|
add_User: text("add_User").default("LST_System").notNull(),
|
||||||
|
add_Date: timestamp("add_Date").defaultNow(),
|
||||||
|
},
|
||||||
|
(table) => [
|
||||||
|
// uniqueIndex('emailUniqueIndex').on(sql`lower(${table.email})`),
|
||||||
|
// uniqueIndex("role_name").on(table.name),
|
||||||
|
//uniqueIndex("ocme_runningNr").on(table.runningNr),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Schema for inserting a user - can be used to validate API requests
|
||||||
|
// export const insertRolesSchema = createInsertSchema(roles, {
|
||||||
|
// name: z.string().min(3, {message: "Role name must be more than 3 letters"}),
|
||||||
|
// });
|
||||||
|
// Schema for selecting a Expenses - can be used to validate API responses
|
||||||
|
export const selectRolesSchema = createSelectSchema(ocmeCycleCounts);
|
||||||
43
database/schema/printers.ts
Normal file
43
database/schema/printers.ts
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import {
|
||||||
|
text,
|
||||||
|
pgTable,
|
||||||
|
numeric,
|
||||||
|
index,
|
||||||
|
timestamp,
|
||||||
|
boolean,
|
||||||
|
uuid,
|
||||||
|
uniqueIndex,
|
||||||
|
} from "drizzle-orm/pg-core";
|
||||||
|
import { createInsertSchema, createSelectSchema } from "drizzle-zod";
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
export const printerData = pgTable(
|
||||||
|
"printerData",
|
||||||
|
{
|
||||||
|
printer_id: uuid("printer_id").defaultRandom().primaryKey(),
|
||||||
|
humanReadableId: text("humanReadableId"),
|
||||||
|
name: text("name").notNull(),
|
||||||
|
ipAddress: text("ipAddress"),
|
||||||
|
port: numeric("port"),
|
||||||
|
status: text("status"),
|
||||||
|
statusText: text("statusText"),
|
||||||
|
lastTimePrinted: timestamp("lastTimePrinted").notNull().defaultNow(),
|
||||||
|
assigned: boolean("assigned").default(false),
|
||||||
|
remark: text("remark"),
|
||||||
|
printDelay: numeric("printDelay").default("90"),
|
||||||
|
monitorState: boolean("monitorState").default(false),
|
||||||
|
add_Date: timestamp("add_Date").defaultNow(),
|
||||||
|
upd_date: timestamp("upd_date").defaultNow(),
|
||||||
|
},
|
||||||
|
(table) => [
|
||||||
|
//uniqueIndex("emailUniqueIndex").on(sql`lower(${table.email})`),
|
||||||
|
uniqueIndex("humanReadableId").on(table.humanReadableId),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Schema for inserting a user - can be used to validate API requests
|
||||||
|
// export const insertRolesSchema = createInsertSchema(roles, {
|
||||||
|
// name: z.string().min(3, {message: "Role name must be more than 3 letters"}),
|
||||||
|
// });
|
||||||
|
// Schema for selecting a Expenses - can be used to validate API responses
|
||||||
|
export const selectRolesSchema = createSelectSchema(printerData);
|
||||||
30
database/schema/prodLabels.ts
Normal file
30
database/schema/prodLabels.ts
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import {
|
||||||
|
integer,
|
||||||
|
pgTable,
|
||||||
|
uuid,
|
||||||
|
uniqueIndex,
|
||||||
|
text,
|
||||||
|
timestamp,
|
||||||
|
} from "drizzle-orm/pg-core";
|
||||||
|
import { createSelectSchema } from "drizzle-zod";
|
||||||
|
|
||||||
|
export const prodlabels = pgTable(
|
||||||
|
"prodlabels",
|
||||||
|
{
|
||||||
|
label_id: uuid("label_id").defaultRandom().primaryKey(),
|
||||||
|
printerID: integer("printerID"),
|
||||||
|
printerName: text("printerName"),
|
||||||
|
line: integer("line"),
|
||||||
|
runningNr: integer("runningNr").notNull(),
|
||||||
|
status: text("status"),
|
||||||
|
add_user: text("add_user").default("lst"),
|
||||||
|
add_date: timestamp("add_date").defaultNow(),
|
||||||
|
upd_date: timestamp("upd_date").defaultNow(),
|
||||||
|
},
|
||||||
|
(table) => [
|
||||||
|
//uniqueIndex("emailUniqueIndex").on(sql`lower(${table.email})`),
|
||||||
|
uniqueIndex("runningNr").on(table.runningNr),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
export const prodlabelsSchema = createSelectSchema(prodlabels);
|
||||||
48
database/schema/qualityRequest.ts
Normal file
48
database/schema/qualityRequest.ts
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
import {
|
||||||
|
text,
|
||||||
|
pgTable,
|
||||||
|
numeric,
|
||||||
|
index,
|
||||||
|
timestamp,
|
||||||
|
boolean,
|
||||||
|
uuid,
|
||||||
|
uniqueIndex,
|
||||||
|
integer,
|
||||||
|
} from "drizzle-orm/pg-core";
|
||||||
|
import { createInsertSchema, createSelectSchema } from "drizzle-zod";
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
export const qualityRequest = pgTable(
|
||||||
|
"qualityRequest",
|
||||||
|
{
|
||||||
|
request_id: uuid("request_id").defaultRandom().primaryKey(),
|
||||||
|
article: numeric("article"),
|
||||||
|
description: text("description"),
|
||||||
|
runningNr: text("runningNr"),
|
||||||
|
lotNr: numeric("lotNr"),
|
||||||
|
warehouseAtRequest: text("warehouseAtRequest"),
|
||||||
|
locationAtRequest: text("locationAtRequest"),
|
||||||
|
warehouseMovedTo: text("warehouseMovedTo"),
|
||||||
|
locationMovedTo: text("locationMovedTo"),
|
||||||
|
durationToMove: integer("durationToMove"),
|
||||||
|
locationDropOff: text("locationDropOff"),
|
||||||
|
palletStatus: integer("palletStatus"),
|
||||||
|
palletStatusText: text("palletStatusText"),
|
||||||
|
palletRequest: integer("palletRequest"),
|
||||||
|
add_date: timestamp("add_date").defaultNow(),
|
||||||
|
add_user: text("add_user").default("LST"),
|
||||||
|
upd_date: timestamp("upd_date").defaultNow(),
|
||||||
|
upd_user: text("upd_user").default("LST"),
|
||||||
|
},
|
||||||
|
(table) => [
|
||||||
|
// uniqueIndex('emailUniqueIndex').on(sql`lower(${table.email})`),
|
||||||
|
// uniqueIndex("role_name").on(table.name),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Schema for inserting a user - can be used to validate API requests
|
||||||
|
// export const insertRolesSchema = createInsertSchema(roles, {
|
||||||
|
// name: z.string().min(3, {message: "Role name must be more than 3 letters"}),
|
||||||
|
// });
|
||||||
|
// Schema for selecting a Expenses - can be used to validate API responses
|
||||||
|
export const selectRolesSchema = createSelectSchema(qualityRequest);
|
||||||
@@ -1,6 +1,16 @@
|
|||||||
import {text, pgTable, numeric, index, timestamp, boolean, uuid, uniqueIndex, jsonb} from "drizzle-orm/pg-core";
|
import {
|
||||||
import {createInsertSchema, createSelectSchema} from "drizzle-zod";
|
text,
|
||||||
import {z} from "zod";
|
pgTable,
|
||||||
|
numeric,
|
||||||
|
index,
|
||||||
|
timestamp,
|
||||||
|
boolean,
|
||||||
|
uuid,
|
||||||
|
uniqueIndex,
|
||||||
|
jsonb,
|
||||||
|
} from "drizzle-orm/pg-core";
|
||||||
|
import { createInsertSchema, createSelectSchema } from "drizzle-zod";
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
export const rfidReaders = pgTable(
|
export const rfidReaders = pgTable(
|
||||||
"rfidReaders",
|
"rfidReaders",
|
||||||
@@ -12,6 +22,7 @@ export const rfidReaders = pgTable(
|
|||||||
lastTrigger: timestamp("lastTrigger").defaultNow(),
|
lastTrigger: timestamp("lastTrigger").defaultNow(),
|
||||||
lastTriggerGood: boolean("lastTiggerGood").default(true),
|
lastTriggerGood: boolean("lastTiggerGood").default(true),
|
||||||
active: boolean("active").default(true),
|
active: boolean("active").default(true),
|
||||||
|
lastTagScanned: text("lastTagScanned"),
|
||||||
},
|
},
|
||||||
(table) => [
|
(table) => [
|
||||||
// uniqueIndex('emailUniqueIndex').on(sql`lower(${table.email})`),
|
// uniqueIndex('emailUniqueIndex').on(sql`lower(${table.email})`),
|
||||||
|
|||||||
@@ -1,7 +1,14 @@
|
|||||||
import {text, pgTable, timestamp, uuid, uniqueIndex, jsonb} from "drizzle-orm/pg-core";
|
import {
|
||||||
import {createSelectSchema} from "drizzle-zod";
|
text,
|
||||||
import {z} from "zod";
|
pgTable,
|
||||||
import {modules} from "./modules.js";
|
timestamp,
|
||||||
|
uuid,
|
||||||
|
uniqueIndex,
|
||||||
|
jsonb,
|
||||||
|
} from "drizzle-orm/pg-core";
|
||||||
|
import { createSelectSchema } from "drizzle-zod";
|
||||||
|
import { z } from "zod";
|
||||||
|
import { modules } from "./modules.js";
|
||||||
|
|
||||||
export const settings = pgTable(
|
export const settings = pgTable(
|
||||||
"settings",
|
"settings",
|
||||||
|
|||||||
39
database/schema/siloAdjustments.ts
Normal file
39
database/schema/siloAdjustments.ts
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
import {
|
||||||
|
text,
|
||||||
|
pgTable,
|
||||||
|
numeric,
|
||||||
|
timestamp,
|
||||||
|
uuid,
|
||||||
|
integer,
|
||||||
|
} from "drizzle-orm/pg-core";
|
||||||
|
import { createInsertSchema, createSelectSchema } from "drizzle-zod";
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
export const siloAdjustments = pgTable(
|
||||||
|
"siloAdjustments",
|
||||||
|
{
|
||||||
|
siloAdjust_id: uuid("siloAdjust_id").defaultRandom().primaryKey(),
|
||||||
|
warehouseID: integer("level"),
|
||||||
|
locationID: integer("locationID"),
|
||||||
|
currentStockLevel: numeric("currentStockLevel"),
|
||||||
|
newLevel: numeric("newLevel"),
|
||||||
|
comment: text("comment").default(""),
|
||||||
|
dateAdjusted: timestamp("dateAdjusted").defaultNow(),
|
||||||
|
lastDateAdjusted: timestamp("lastDateAdjusted").defaultNow(),
|
||||||
|
commentAddedBy: text("commentAddedBy"),
|
||||||
|
commentDate: text("commentDate"),
|
||||||
|
commentKey: text("commentKey"),
|
||||||
|
add_user: text("add_user").default("LST_Serivce"),
|
||||||
|
},
|
||||||
|
(table) => [
|
||||||
|
// uniqueIndex('emailUniqueIndex').on(sql`lower(${table.email})`),
|
||||||
|
// uniqueIndex("role_name").on(table.name),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Schema for inserting a user - can be used to validate API requests
|
||||||
|
// export const insertRolesSchema = createInsertSchema(roles, {
|
||||||
|
// name: z.string().min(3, {message: "Role name must be more than 3 letters"}),
|
||||||
|
// });
|
||||||
|
// Schema for selecting a Expenses - can be used to validate API responses
|
||||||
|
export const selectRolesSchema = createSelectSchema(siloAdjustments);
|
||||||
45
database/schema/subModules.ts
Normal file
45
database/schema/subModules.ts
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import {
|
||||||
|
text,
|
||||||
|
pgTable,
|
||||||
|
timestamp,
|
||||||
|
boolean,
|
||||||
|
uuid,
|
||||||
|
uniqueIndex,
|
||||||
|
jsonb,
|
||||||
|
} from "drizzle-orm/pg-core";
|
||||||
|
import { createSelectSchema } from "drizzle-zod";
|
||||||
|
//import {z} from "zod";
|
||||||
|
|
||||||
|
export const subModules = pgTable(
|
||||||
|
"subModules",
|
||||||
|
{
|
||||||
|
submodule_id: uuid("submodule_id").defaultRandom().primaryKey(),
|
||||||
|
moduleName: text("moduleName"),
|
||||||
|
// .notNull()
|
||||||
|
// .references(() => modules.name),
|
||||||
|
name: text("name").notNull(),
|
||||||
|
description: text("description"),
|
||||||
|
link: text("link").notNull(),
|
||||||
|
active: boolean("active").default(false),
|
||||||
|
roles: jsonb("roles").notNull().default(["systemAdmin"]), // ["view", "technician", "supervisor","manager", "admin","systemAdmin"]
|
||||||
|
icon: text("icon"),
|
||||||
|
subSubModule: jsonb("subSubModule").default([]),
|
||||||
|
add_User: text("add_User").default("LST_System").notNull(),
|
||||||
|
add_Date: timestamp("add_Date").defaultNow(),
|
||||||
|
upd_user: text("upd_User").default("LST_System").notNull(),
|
||||||
|
upd_date: timestamp("upd_date").defaultNow(),
|
||||||
|
},
|
||||||
|
(table) => [
|
||||||
|
// uniqueIndex('emailUniqueIndex').on(sql`lower(${table.email})`),
|
||||||
|
uniqueIndex("subModule_name").on(table.name),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Schema for inserting a user - can be used to validate API requests
|
||||||
|
// export const insertModuleSchema = createInsertSchema(modules, {
|
||||||
|
// name: z.string().min(3, {message: "Module name should be longer than 3 letters"}),
|
||||||
|
// });
|
||||||
|
// Schema for selecting a Expenses - can be used to validate API responses
|
||||||
|
export const selectModuleSchema = createSelectSchema(subModules);
|
||||||
|
|
||||||
|
export type Modules = typeof subModules;
|
||||||
1225
frontend/package-lock.json
generated
1225
frontend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -8,11 +8,12 @@
|
|||||||
"build": "rimraf dist && tsc -b && vite build",
|
"build": "rimraf dist && tsc -b && vite build",
|
||||||
"lint": "eslint .",
|
"lint": "eslint .",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"shad": "npx shadcn@canary add ",
|
"shad": "npx shadcn@latest add ",
|
||||||
"checkupdates": "npm-check-updates"
|
"checkupdates": "npm-check-updates"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@hookform/resolvers": "^4.1.3",
|
"@hookform/resolvers": "^4.1.3",
|
||||||
|
"@radix-ui/react-accordion": "^1.2.3",
|
||||||
"@radix-ui/react-avatar": "^1.1.3",
|
"@radix-ui/react-avatar": "^1.1.3",
|
||||||
"@radix-ui/react-checkbox": "^1.1.4",
|
"@radix-ui/react-checkbox": "^1.1.4",
|
||||||
"@radix-ui/react-collapsible": "^1.1.3",
|
"@radix-ui/react-collapsible": "^1.1.3",
|
||||||
@@ -20,12 +21,14 @@
|
|||||||
"@radix-ui/react-dropdown-menu": "^2.1.6",
|
"@radix-ui/react-dropdown-menu": "^2.1.6",
|
||||||
"@radix-ui/react-label": "^2.1.2",
|
"@radix-ui/react-label": "^2.1.2",
|
||||||
"@radix-ui/react-popover": "^1.1.6",
|
"@radix-ui/react-popover": "^1.1.6",
|
||||||
|
"@radix-ui/react-scroll-area": "^1.2.3",
|
||||||
"@radix-ui/react-select": "^2.1.6",
|
"@radix-ui/react-select": "^2.1.6",
|
||||||
"@radix-ui/react-separator": "^1.1.2",
|
"@radix-ui/react-separator": "^1.1.2",
|
||||||
"@radix-ui/react-slot": "^1.1.2",
|
"@radix-ui/react-slot": "^1.1.2",
|
||||||
"@radix-ui/react-tabs": "^1.1.3",
|
"@radix-ui/react-tabs": "^1.1.3",
|
||||||
"@radix-ui/react-tooltip": "^1.1.8",
|
"@radix-ui/react-tooltip": "^1.1.8",
|
||||||
"@tailwindcss/vite": "^4.0.15",
|
"@tailwindcss/vite": "^4.0.15",
|
||||||
|
"@tanstack/react-form": "^1.2.1",
|
||||||
"@tanstack/react-query": "^5.69.0",
|
"@tanstack/react-query": "^5.69.0",
|
||||||
"@tanstack/react-router": "^1.114.27",
|
"@tanstack/react-router": "^1.114.27",
|
||||||
"@tanstack/react-table": "^8.21.2",
|
"@tanstack/react-table": "^8.21.2",
|
||||||
@@ -38,6 +41,7 @@
|
|||||||
"js-cookie": "^3.0.5",
|
"js-cookie": "^3.0.5",
|
||||||
"jsonwebtoken": "^9.0.2",
|
"jsonwebtoken": "^9.0.2",
|
||||||
"lucide-react": "^0.483.0",
|
"lucide-react": "^0.483.0",
|
||||||
|
"marked": "^15.0.8",
|
||||||
"next-themes": "^0.4.6",
|
"next-themes": "^0.4.6",
|
||||||
"npm-check-updates": "^17.1.16",
|
"npm-check-updates": "^17.1.16",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
@@ -45,6 +49,8 @@
|
|||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"react-grid-layout": "^1.5.1",
|
"react-grid-layout": "^1.5.1",
|
||||||
"react-hook-form": "^7.54.2",
|
"react-hook-form": "^7.54.2",
|
||||||
|
"react-resizable-panels": "^2.1.7",
|
||||||
|
"recharts": "^2.15.2",
|
||||||
"sonner": "^2.0.1",
|
"sonner": "^2.0.1",
|
||||||
"tailwind-merge": "^3.0.2",
|
"tailwind-merge": "^3.0.2",
|
||||||
"tailwindcss": "^4.0.15",
|
"tailwindcss": "^4.0.15",
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
export default function DataMartStats() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
The stats for all the data mart querys out there and whos and when
|
||||||
|
they are last used to understand if we want to keep them or not
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
146
frontend/src/components/admin/modules/ModuleForm.tsx
Normal file
146
frontend/src/components/admin/modules/ModuleForm.tsx
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogDescription,
|
||||||
|
DialogFooter,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
DialogTrigger,
|
||||||
|
} from "@/components/ui/dialog";
|
||||||
|
|
||||||
|
import { Label } from "@/components/ui/label";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
import { useState } from "react";
|
||||||
|
//import { z } from "zod";
|
||||||
|
//import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
import { useQuery } from "@tanstack/react-query";
|
||||||
|
import { useSessionStore } from "@/lib/store/sessionStore";
|
||||||
|
import axios from "axios";
|
||||||
|
import { useForm } from "@tanstack/react-form";
|
||||||
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
|
|
||||||
|
import { getModules } from "@/utils/querys/admin/modules";
|
||||||
|
|
||||||
|
// const FormSchema = z.object({
|
||||||
|
// subModule: z.boolean(),
|
||||||
|
// });
|
||||||
|
export function ChangeModule({ module }: { module: any }) {
|
||||||
|
const { token } = useSessionStore();
|
||||||
|
const { refetch } = useQuery(getModules(token ?? ""));
|
||||||
|
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
const [saving, setSaving] = useState(false);
|
||||||
|
const form = useForm({
|
||||||
|
defaultValues: {
|
||||||
|
active: module.active,
|
||||||
|
},
|
||||||
|
onSubmit: async ({ value }) => {
|
||||||
|
//console.log(value);
|
||||||
|
try {
|
||||||
|
const result = await axios.patch(
|
||||||
|
`/api/server/modules/${module.module_id}`,
|
||||||
|
{ active: value.active },
|
||||||
|
{
|
||||||
|
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) {
|
||||||
|
form.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>{module.name}</DialogTitle>
|
||||||
|
<DialogDescription>
|
||||||
|
Set to active or deactivated.
|
||||||
|
</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
<form
|
||||||
|
onSubmit={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<>
|
||||||
|
<form.Field
|
||||||
|
name="active"
|
||||||
|
// validators={{
|
||||||
|
// // We can choose between form-wide and field-specific validators
|
||||||
|
// onChange: ({ value }) =>
|
||||||
|
// value.length > 3
|
||||||
|
// ? undefined
|
||||||
|
// : "Username must be longer than 3 letters",
|
||||||
|
// }}
|
||||||
|
children={(field) => {
|
||||||
|
return (
|
||||||
|
<div className="m-2 min-w-48 max-w-96 p-2 flex flex-row">
|
||||||
|
<Label htmlFor="active">
|
||||||
|
Active
|
||||||
|
</Label>
|
||||||
|
<Checkbox
|
||||||
|
className="ml-2"
|
||||||
|
name={field.name}
|
||||||
|
onBlur={field.handleBlur}
|
||||||
|
checked={field.state.value}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
field.handleChange(e)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<DialogFooter>
|
||||||
|
<div className="flex justify-end mt-2">
|
||||||
|
<Button
|
||||||
|
type="submit"
|
||||||
|
disabled={saving}
|
||||||
|
onClick={form.handleSubmit}
|
||||||
|
>
|
||||||
|
{saving ? (
|
||||||
|
<>
|
||||||
|
<span>Saving....</span>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<span>Save setting</span>
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</DialogFooter>
|
||||||
|
</form>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
116
frontend/src/components/admin/modules/ModulePage.tsx
Normal file
116
frontend/src/components/admin/modules/ModulePage.tsx
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
import { LstCard } from "@/components/extendedUI/LstCard";
|
||||||
|
import {
|
||||||
|
Table,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableHead,
|
||||||
|
TableHeader,
|
||||||
|
TableRow,
|
||||||
|
} from "@/components/ui/table";
|
||||||
|
import { useSessionStore } from "@/lib/store/sessionStore";
|
||||||
|
import { useModuleStore } from "@/lib/store/useModuleStore";
|
||||||
|
import { useQuery } from "@tanstack/react-query";
|
||||||
|
import { useRouter } from "@tanstack/react-router";
|
||||||
|
|
||||||
|
import { Skeleton } from "@/components/ui/skeleton";
|
||||||
|
import { getModules } from "@/utils/querys/admin/modules";
|
||||||
|
import { ChangeModule } from "./ModuleForm";
|
||||||
|
|
||||||
|
export type Settings = {
|
||||||
|
settings_id?: string;
|
||||||
|
name?: string;
|
||||||
|
value?: string;
|
||||||
|
description?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function ModulesPage() {
|
||||||
|
const { user, token } = useSessionStore();
|
||||||
|
const { modules } = useModuleStore();
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const adminModule = modules.filter((n) => n.name === "admin");
|
||||||
|
const userLevel =
|
||||||
|
user?.roles.filter((r) => r.module_id === adminModule[0].module_id) ||
|
||||||
|
[];
|
||||||
|
|
||||||
|
if (!adminModule[0].roles.includes(userLevel[0]?.role)) {
|
||||||
|
router.navigate({ to: "/" });
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data, isError, error, isLoading } = useQuery(
|
||||||
|
getModules(token ?? "")
|
||||||
|
);
|
||||||
|
|
||||||
|
// if (isLoading) {
|
||||||
|
// return <div>Loading.....</div>;
|
||||||
|
// }
|
||||||
|
if (isError) {
|
||||||
|
return <div>{JSON.stringify(error)}</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<LstCard className="m-2 flex place-content-center w-fit">
|
||||||
|
<Table>
|
||||||
|
<TableHeader>
|
||||||
|
<TableRow>
|
||||||
|
<TableHead>Name</TableHead>
|
||||||
|
<TableHead>Description</TableHead>
|
||||||
|
<TableHead>Module In</TableHead>
|
||||||
|
<TableHead>Roles</TableHead>
|
||||||
|
<TableHead>Active</TableHead>
|
||||||
|
<TableHead>Edit</TableHead>
|
||||||
|
</TableRow>
|
||||||
|
</TableHeader>
|
||||||
|
{isLoading ? (
|
||||||
|
<>
|
||||||
|
<TableBody>
|
||||||
|
{Array(10)
|
||||||
|
.fill(0)
|
||||||
|
.map((_, i) => (
|
||||||
|
<TableRow key={i}>
|
||||||
|
<TableCell className="font-medium">
|
||||||
|
<Skeleton className="h-4" />
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Skeleton className="h-4" />
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Skeleton className="h-4" />
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Skeleton className="h-4" />
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))}
|
||||||
|
</TableBody>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<TableBody>
|
||||||
|
{data?.map((i: any) => (
|
||||||
|
<TableRow key={i.submodule_id}>
|
||||||
|
<TableCell className="font-medium">
|
||||||
|
{i.name}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="font-medium">
|
||||||
|
{i.description}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="font-medium">
|
||||||
|
{i.moduleName}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="font-medium">
|
||||||
|
{JSON.stringify(i.roles)}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="font-medium">
|
||||||
|
{i.active ? "Yes" : "No"}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="font-medium">
|
||||||
|
<ChangeModule module={i} />
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))}
|
||||||
|
</TableBody>
|
||||||
|
)}
|
||||||
|
</Table>
|
||||||
|
</LstCard>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import { getnotifications } from "@/utils/querys/admin/notifications";
|
||||||
|
import { notifyColumns } from "@/utils/tableData/notifications/notifyColumns";
|
||||||
|
import { NotifyTable } from "@/utils/tableData/notifications/notifyData";
|
||||||
|
import { useQuery } from "@tanstack/react-query";
|
||||||
|
|
||||||
|
export default function NotificationMGT() {
|
||||||
|
const { data, isError, isLoading } = useQuery(getnotifications());
|
||||||
|
|
||||||
|
if (isLoading) return <div>Loading adjustmnet data...</div>;
|
||||||
|
if (isError) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<p>There was an error getting the adjustments.</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<NotifyTable columns={notifyColumns} data={data} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
import { LstCard } from "@/components/extendedUI/LstCard";
|
import { LstCard } from "@/components/extendedUI/LstCard";
|
||||||
import { Skeleton } from "@/components/ui/skeleton";
|
import { Skeleton } from "@/components/ui/skeleton";
|
||||||
import {
|
import {
|
||||||
Table,
|
Table,
|
||||||
TableBody,
|
TableBody,
|
||||||
TableCell,
|
TableCell,
|
||||||
TableHead,
|
TableHead,
|
||||||
TableHeader,
|
TableHeader,
|
||||||
TableRow,
|
TableRow,
|
||||||
} from "@/components/ui/table";
|
} 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";
|
||||||
@@ -19,107 +19,172 @@ import { adminUrlCheck } from "@/utils/adminUrlCheck";
|
|||||||
import RestartServer from "./RestartServer";
|
import RestartServer from "./RestartServer";
|
||||||
import StopServer from "./StopServer";
|
import StopServer from "./StopServer";
|
||||||
import StartServer from "./StartServer";
|
import StartServer from "./StartServer";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { getSettings } from "@/utils/querys/settings";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
import axios from "axios";
|
||||||
|
//import { useState } from "react";
|
||||||
|
|
||||||
export type Servers = {
|
export type Servers = {
|
||||||
server_id?: string;
|
server_id?: string;
|
||||||
sName?: string;
|
sName?: string;
|
||||||
serverDNS?: string;
|
serverDNS?: string;
|
||||||
plantToken?: string;
|
plantToken?: string;
|
||||||
idAddress: string;
|
idAddress: string;
|
||||||
lastUpdated: string;
|
lastUpdated: string;
|
||||||
isUpgrading: boolean;
|
isUpgrading: boolean;
|
||||||
|
lstServerPort: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function ServerPage() {
|
export default function ServerPage() {
|
||||||
const { user, token } = useSessionStore();
|
const { user, token } = useSessionStore();
|
||||||
const { modules } = useModuleStore();
|
const { modules } = useModuleStore();
|
||||||
const router = useRouter();
|
//const [upgrading, setUpgrading] = useState(false);
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
const { data, isError, error, isLoading } = useQuery(getServers(token ?? ""));
|
const { data, isError, error, isLoading } = useQuery(
|
||||||
|
getServers(token ?? "")
|
||||||
|
);
|
||||||
|
|
||||||
const adminModule = modules.filter((n) => n.name === "admin");
|
const adminModule = modules.filter((n) => n.name === "admin");
|
||||||
const userLevel =
|
const userLevel =
|
||||||
user?.roles?.filter((r) => r.module_id === adminModule[0].module_id) || [];
|
user?.roles?.filter((r) => r.module_id === adminModule[0].module_id) ||
|
||||||
|
[];
|
||||||
|
|
||||||
if (!adminModule[0]?.roles?.includes(userLevel[0]?.role)) {
|
if (!adminModule[0]?.roles?.includes(userLevel[0]?.role)) {
|
||||||
router.navigate({ to: "/" });
|
router.navigate({ to: "/" });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isError) {
|
if (isError) {
|
||||||
return <div>{JSON.stringify(error)}</div>;
|
return <div>{JSON.stringify(error)}</div>;
|
||||||
}
|
}
|
||||||
|
const { data: set } = useQuery(getSettings(token ?? ""));
|
||||||
|
const upgrade = async () => {
|
||||||
|
let devDir = set.filter((n: any) => n.name === "devDir");
|
||||||
|
toast.success("All Servers was just triggered.");
|
||||||
|
|
||||||
console.log(data);
|
try {
|
||||||
return (
|
const result = await axios.post(
|
||||||
<LstCard className="m-2 flex place-content-center w-dvh">
|
`/api/server/update/localhost`,
|
||||||
<Table>
|
{ devDir: devDir[0].value, all: true },
|
||||||
<TableHeader>
|
{
|
||||||
<TableRow>
|
headers: { Authorization: `Bearer ${token}` },
|
||||||
<TableHead>Name</TableHead>
|
}
|
||||||
<TableHead>Server</TableHead>
|
);
|
||||||
<TableHead>PlantToken</TableHead>
|
|
||||||
<TableHead>IP Address</TableHead>
|
if (result.data.success) {
|
||||||
<TableHead>Date Last updated</TableHead>
|
toast.success(result.data.message);
|
||||||
<TableHead>Update Server</TableHead>
|
}
|
||||||
</TableRow>
|
|
||||||
</TableHeader>
|
if (!result.data.success) {
|
||||||
{isLoading ? (
|
toast.success(result.data.message);
|
||||||
<>
|
}
|
||||||
<TableBody>
|
} catch (error: any) {
|
||||||
{Array(10)
|
toast.error(
|
||||||
.fill(0)
|
`There was an error updating the server: ${error.data.message}`
|
||||||
.map((_, i) => (
|
);
|
||||||
<TableRow key={i}>
|
}
|
||||||
<TableCell className="font-medium">
|
};
|
||||||
<Skeleton className="h-4" />
|
|
||||||
</TableCell>
|
//console.log(data);
|
||||||
<TableCell>
|
return (
|
||||||
<Skeleton className="h-4" />
|
<LstCard className="m-2 flex place-content-center w-dvh">
|
||||||
</TableCell>
|
<div className="flex justify-end m-2">
|
||||||
<TableCell>
|
<Button
|
||||||
<Skeleton className="h-4" />
|
onClick={upgrade}
|
||||||
</TableCell>
|
disabled={data?.some((d: any) => d.isUpgrading)}
|
||||||
<TableCell>
|
>
|
||||||
<Skeleton className="h-4" />
|
Update All Servers
|
||||||
</TableCell>
|
</Button>
|
||||||
</TableRow>
|
</div>
|
||||||
))}
|
<Table>
|
||||||
</TableBody>
|
<TableHeader>
|
||||||
</>
|
<TableRow>
|
||||||
) : (
|
<TableHead>Name</TableHead>
|
||||||
<TableBody>
|
<TableHead>Server</TableHead>
|
||||||
{data?.map((server: Servers) => {
|
<TableHead>PlantToken</TableHead>
|
||||||
const strippedDate = server.lastUpdated.replace("Z", ""); // Remove Z
|
<TableHead>IP Address</TableHead>
|
||||||
const formattedDate = format(strippedDate, "MM/dd/yyyy hh:mm a");
|
<TableHead>Date Last updated</TableHead>
|
||||||
return (
|
<TableHead>Update Server</TableHead>
|
||||||
<TableRow key={server.server_id}>
|
</TableRow>
|
||||||
<TableCell className="font-medium">{server.sName}</TableCell>
|
</TableHeader>
|
||||||
<TableCell className="font-medium">
|
{isLoading ? (
|
||||||
{server.serverDNS}
|
<>
|
||||||
</TableCell>
|
<TableBody>
|
||||||
<TableCell className="font-medium">
|
{Array(10)
|
||||||
{server.plantToken}
|
.fill(0)
|
||||||
</TableCell>
|
.map((_, i) => (
|
||||||
<TableCell className="font-medium">
|
<TableRow key={i}>
|
||||||
{server.idAddress}
|
<TableCell className="font-medium">
|
||||||
</TableCell>
|
<Skeleton className="h-4" />
|
||||||
<TableCell className="font-medium">{formattedDate}</TableCell>
|
</TableCell>
|
||||||
<TableCell className="font-medium">
|
<TableCell>
|
||||||
{adminUrlCheck() && (
|
<Skeleton className="h-4" />
|
||||||
<div className="flex flex-row">
|
</TableCell>
|
||||||
<UpdateServer server={server} token={token as string} />
|
<TableCell>
|
||||||
<StartServer />
|
<Skeleton className="h-4" />
|
||||||
<StopServer />
|
</TableCell>
|
||||||
<RestartServer />
|
<TableCell>
|
||||||
</div>
|
<Skeleton className="h-4" />
|
||||||
)}
|
</TableCell>
|
||||||
</TableCell>
|
</TableRow>
|
||||||
</TableRow>
|
))}
|
||||||
);
|
</TableBody>
|
||||||
})}
|
</>
|
||||||
</TableBody>
|
) : (
|
||||||
)}
|
<TableBody>
|
||||||
</Table>
|
{data?.map((server: Servers) => {
|
||||||
</LstCard>
|
const strippedDate = server.lastUpdated.replace(
|
||||||
);
|
"Z",
|
||||||
|
""
|
||||||
|
); // Remove Z
|
||||||
|
const formattedDate = format(
|
||||||
|
strippedDate,
|
||||||
|
"MM/dd/yyyy hh:mm a"
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<TableRow key={server.server_id}>
|
||||||
|
<TableCell className="font-medium">
|
||||||
|
<a
|
||||||
|
href={`http://${server.serverDNS}:${server.lstServerPort}`}
|
||||||
|
target={"_blank"}
|
||||||
|
>
|
||||||
|
<span>{server.sName}</span>
|
||||||
|
</a>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="font-medium">
|
||||||
|
{server.serverDNS}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="font-medium">
|
||||||
|
{server.plantToken}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="font-medium">
|
||||||
|
{server.idAddress}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="font-medium">
|
||||||
|
{formattedDate}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="font-medium">
|
||||||
|
{adminUrlCheck() && (
|
||||||
|
<div className="flex flex-row">
|
||||||
|
<UpdateServer
|
||||||
|
server={server}
|
||||||
|
token={token as string}
|
||||||
|
/>
|
||||||
|
<StartServer />
|
||||||
|
<StopServer
|
||||||
|
plantData={server}
|
||||||
|
/>
|
||||||
|
<RestartServer />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</TableBody>
|
||||||
|
)}
|
||||||
|
</Table>
|
||||||
|
</LstCard>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,46 @@
|
|||||||
import {Button} from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import {Tooltip, TooltipContent, TooltipProvider, TooltipTrigger} from "@/components/ui/tooltip";
|
import {
|
||||||
import {Octagon} from "lucide-react";
|
Tooltip,
|
||||||
|
TooltipContent,
|
||||||
|
TooltipProvider,
|
||||||
|
TooltipTrigger,
|
||||||
|
} from "@/components/ui/tooltip";
|
||||||
|
import axios from "axios";
|
||||||
|
import { Octagon } from "lucide-react";
|
||||||
|
|
||||||
export default function StopServer() {
|
export default function StopServer(plantData: any) {
|
||||||
|
const token = localStorage.getItem("auth_token");
|
||||||
|
const handleStopServer = async (plant: string) => {
|
||||||
|
let data: any = {
|
||||||
|
processType: "stop",
|
||||||
|
plantToken: plant,
|
||||||
|
};
|
||||||
|
const url: string = window.location.host.split(":")[0];
|
||||||
|
if (url === "localhost") {
|
||||||
|
data = { ...data, remote: "true" };
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const res = await axios.post("/api/server/serviceprocess", data, {
|
||||||
|
headers: { Authorization: `Bearer ${token}` },
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(res);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<TooltipProvider>
|
<TooltipProvider>
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<Button variant={"outline"} size={"icon"}>
|
<Button
|
||||||
|
variant="destructive"
|
||||||
|
size={"icon"}
|
||||||
|
onClick={() =>
|
||||||
|
handleStopServer(plantData.plantToken)
|
||||||
|
}
|
||||||
|
>
|
||||||
<Octagon />
|
<Octagon />
|
||||||
</Button>
|
</Button>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
|
|||||||
@@ -1,23 +1,34 @@
|
|||||||
import {Button} from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import {CircleFadingArrowUp} from "lucide-react";
|
import { CircleFadingArrowUp } from "lucide-react";
|
||||||
import {toast} from "sonner";
|
import { toast } from "sonner";
|
||||||
import {Servers} from "./ServerPage";
|
import { Servers } from "./ServerPage";
|
||||||
import {useQuery} from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
import {getSettings} from "@/utils/querys/settings";
|
import { getSettings } from "@/utils/querys/settings";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import {Tooltip, TooltipContent, TooltipProvider, TooltipTrigger} from "@/components/ui/tooltip";
|
import {
|
||||||
|
Tooltip,
|
||||||
|
TooltipContent,
|
||||||
|
TooltipProvider,
|
||||||
|
TooltipTrigger,
|
||||||
|
} from "@/components/ui/tooltip";
|
||||||
|
|
||||||
export default function UpdateServer({server, token}: {server: Servers; token: string}) {
|
export default function UpdateServer({
|
||||||
const {data} = useQuery(getSettings(token ?? ""));
|
server,
|
||||||
|
token,
|
||||||
|
}: {
|
||||||
|
server: Servers;
|
||||||
|
token: string;
|
||||||
|
}) {
|
||||||
|
const { data } = useQuery(getSettings(token ?? ""));
|
||||||
const upgrade = async () => {
|
const upgrade = async () => {
|
||||||
let devDir = data.filter((n: any) => n.name === "devDir");
|
let devDir = data.filter((n: any) => n.name === "devDir");
|
||||||
toast.success("Server being upgraded in the background please wait.");
|
toast.success("Server being upgraded in the background please wait.");
|
||||||
try {
|
try {
|
||||||
const result = await axios.post(
|
const result = await axios.post(
|
||||||
`/api/server/update/${server.plantToken}`,
|
`/api/server/update/${server.plantToken}`,
|
||||||
{devDir: devDir[0].value},
|
{ devDir: devDir[0].value },
|
||||||
{
|
{
|
||||||
headers: {Authorization: `Bearer ${token}`},
|
headers: { Authorization: `Bearer ${token}` },
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -29,7 +40,9 @@ export default function UpdateServer({server, token}: {server: Servers; token: s
|
|||||||
toast.success(result.data.message);
|
toast.success(result.data.message);
|
||||||
}
|
}
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
toast.error(`There was an error updating the server: ${error.data.message}`);
|
toast.error(
|
||||||
|
`There was an error updating the server: ${error.data.message}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
@@ -37,7 +50,12 @@ export default function UpdateServer({server, token}: {server: Servers; token: s
|
|||||||
<TooltipProvider>
|
<TooltipProvider>
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<Button variant={"outline"} size={"icon"} onClick={upgrade} disabled={server.isUpgrading}>
|
<Button
|
||||||
|
variant={`${server.isUpgrading ? "ghost" : "outline"}`}
|
||||||
|
size={"icon"}
|
||||||
|
onClick={upgrade}
|
||||||
|
disabled={server.isUpgrading}
|
||||||
|
>
|
||||||
<CircleFadingArrowUp />
|
<CircleFadingArrowUp />
|
||||||
</Button>
|
</Button>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
|
|||||||
145
frontend/src/components/admin/supModules/SubModuleForm.tsx
Normal file
145
frontend/src/components/admin/supModules/SubModuleForm.tsx
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogDescription,
|
||||||
|
DialogFooter,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
DialogTrigger,
|
||||||
|
} from "@/components/ui/dialog";
|
||||||
|
|
||||||
|
import { Label } from "@/components/ui/label";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
import { useState } from "react";
|
||||||
|
//import { z } from "zod";
|
||||||
|
//import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
import { useQuery } from "@tanstack/react-query";
|
||||||
|
import { useSessionStore } from "@/lib/store/sessionStore";
|
||||||
|
import axios from "axios";
|
||||||
|
import { useForm } from "@tanstack/react-form";
|
||||||
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
|
import { getSubModules } from "@/utils/querys/admin/subModules";
|
||||||
|
|
||||||
|
// const FormSchema = z.object({
|
||||||
|
// subModule: z.boolean(),
|
||||||
|
// });
|
||||||
|
export function ChangeSubModule({ subModule }: { subModule: any }) {
|
||||||
|
const { token } = useSessionStore();
|
||||||
|
const { refetch } = useQuery(getSubModules(token ?? ""));
|
||||||
|
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
const [saving, setSaving] = useState(false);
|
||||||
|
const form = useForm({
|
||||||
|
defaultValues: {
|
||||||
|
active: subModule.active,
|
||||||
|
},
|
||||||
|
onSubmit: async ({ value }) => {
|
||||||
|
console.log(value);
|
||||||
|
try {
|
||||||
|
const result = await axios.patch(
|
||||||
|
`/api/server/submodules/${subModule.submodule_id}`,
|
||||||
|
{ active: value.active },
|
||||||
|
{
|
||||||
|
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) {
|
||||||
|
form.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>{subModule.name}</DialogTitle>
|
||||||
|
<DialogDescription>
|
||||||
|
Set to active or deactivated.
|
||||||
|
</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
<form
|
||||||
|
onSubmit={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<>
|
||||||
|
<form.Field
|
||||||
|
name="active"
|
||||||
|
// validators={{
|
||||||
|
// // We can choose between form-wide and field-specific validators
|
||||||
|
// onChange: ({ value }) =>
|
||||||
|
// value.length > 3
|
||||||
|
// ? undefined
|
||||||
|
// : "Username must be longer than 3 letters",
|
||||||
|
// }}
|
||||||
|
children={(field) => {
|
||||||
|
return (
|
||||||
|
<div className="m-2 min-w-48 max-w-96 p-2 flex flex-row">
|
||||||
|
<Label htmlFor="active">
|
||||||
|
Active
|
||||||
|
</Label>
|
||||||
|
<Checkbox
|
||||||
|
className="ml-2"
|
||||||
|
name={field.name}
|
||||||
|
onBlur={field.handleBlur}
|
||||||
|
checked={field.state.value}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
field.handleChange(e)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<DialogFooter>
|
||||||
|
<div className="flex justify-end mt-2">
|
||||||
|
<Button
|
||||||
|
type="submit"
|
||||||
|
disabled={saving}
|
||||||
|
onClick={form.handleSubmit}
|
||||||
|
>
|
||||||
|
{saving ? (
|
||||||
|
<>
|
||||||
|
<span>Saving....</span>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<span>Save setting</span>
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</DialogFooter>
|
||||||
|
</form>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
125
frontend/src/components/admin/supModules/SubModulePage.tsx
Normal file
125
frontend/src/components/admin/supModules/SubModulePage.tsx
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
import { LstCard } from "@/components/extendedUI/LstCard";
|
||||||
|
import {
|
||||||
|
Table,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableHead,
|
||||||
|
TableHeader,
|
||||||
|
TableRow,
|
||||||
|
} from "@/components/ui/table";
|
||||||
|
import { useSessionStore } from "@/lib/store/sessionStore";
|
||||||
|
import { useModuleStore } from "@/lib/store/useModuleStore";
|
||||||
|
import { useQuery } from "@tanstack/react-query";
|
||||||
|
import { useRouter } from "@tanstack/react-router";
|
||||||
|
import { ChangeSubModule } from "./SubModuleForm";
|
||||||
|
|
||||||
|
import { Skeleton } from "@/components/ui/skeleton";
|
||||||
|
import { getSubModules } from "@/utils/querys/admin/subModules";
|
||||||
|
|
||||||
|
export type Settings = {
|
||||||
|
settings_id?: string;
|
||||||
|
name?: string;
|
||||||
|
value?: string;
|
||||||
|
description?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function SubModulePage() {
|
||||||
|
const { user, token } = useSessionStore();
|
||||||
|
const { modules } = useModuleStore();
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const adminModule = modules.filter((n) => n.name === "admin");
|
||||||
|
const userLevel =
|
||||||
|
user?.roles.filter((r) => r.module_id === adminModule[0].module_id) ||
|
||||||
|
[];
|
||||||
|
|
||||||
|
if (!adminModule[0].roles.includes(userLevel[0]?.role)) {
|
||||||
|
router.navigate({ to: "/" });
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data, isError, error, isLoading } = useQuery(
|
||||||
|
getSubModules(token ?? "")
|
||||||
|
);
|
||||||
|
|
||||||
|
// if (isLoading) {
|
||||||
|
// return <div>Loading.....</div>;
|
||||||
|
// }
|
||||||
|
if (isError) {
|
||||||
|
return <div>{JSON.stringify(error)}</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<LstCard className="m-2 flex place-content-center w-fit">
|
||||||
|
<Table>
|
||||||
|
<TableHeader>
|
||||||
|
<TableRow>
|
||||||
|
<TableHead>Name</TableHead>
|
||||||
|
<TableHead>Description</TableHead>
|
||||||
|
<TableHead>Module In</TableHead>
|
||||||
|
<TableHead>Roles</TableHead>
|
||||||
|
<TableHead>Active</TableHead>
|
||||||
|
<TableHead>Edit</TableHead>
|
||||||
|
</TableRow>
|
||||||
|
</TableHeader>
|
||||||
|
{isLoading ? (
|
||||||
|
<>
|
||||||
|
<TableBody>
|
||||||
|
{Array(10)
|
||||||
|
.fill(0)
|
||||||
|
.map((_, i) => (
|
||||||
|
<TableRow key={i}>
|
||||||
|
<TableCell className="font-medium">
|
||||||
|
<Skeleton className="h-4" />
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Skeleton className="h-4" />
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Skeleton className="h-4" />
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Skeleton className="h-4" />
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Skeleton className="h-4" />
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Skeleton className="h-4" />
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Skeleton className="h-4" />
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))}
|
||||||
|
</TableBody>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<TableBody>
|
||||||
|
{data?.map((i: any) => (
|
||||||
|
<TableRow key={i.submodule_id}>
|
||||||
|
<TableCell className="font-medium">
|
||||||
|
{i.name}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="font-medium">
|
||||||
|
{i.description}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="font-medium">
|
||||||
|
{i.moduleName}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="font-medium">
|
||||||
|
{JSON.stringify(i.roles)}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="font-medium">
|
||||||
|
{i.active ? "Yes" : "No"}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="font-medium">
|
||||||
|
<ChangeSubModule subModule={i} />
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))}
|
||||||
|
</TableBody>
|
||||||
|
)}
|
||||||
|
</Table>
|
||||||
|
</LstCard>
|
||||||
|
);
|
||||||
|
}
|
||||||
28
frontend/src/components/admin/user/UserPage.tsx
Normal file
28
frontend/src/components/admin/user/UserPage.tsx
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import { getUsers } from "@/utils/querys/admin/users";
|
||||||
|
import { useQuery } from "@tanstack/react-query";
|
||||||
|
import UserCard from "./components/UserCard";
|
||||||
|
|
||||||
|
export default function UserPage() {
|
||||||
|
const { data, isError, error, isLoading } = useQuery(getUsers());
|
||||||
|
|
||||||
|
if (isLoading) return <div className="m-auto">Loading users...</div>;
|
||||||
|
|
||||||
|
if (isError)
|
||||||
|
return (
|
||||||
|
<div className="m-auto">
|
||||||
|
There was an error getting the users.... {JSON.stringify(error)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="m-2 w-dvw">
|
||||||
|
{data.map((u: any) => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<UserCard user={u} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
import ModuleForm from "./ModuleForm";
|
||||||
|
import { getModules } from "@/utils/querys/admin/modules";
|
||||||
|
import { useQuery } from "@tanstack/react-query";
|
||||||
|
//import { getUserRoles } from "@/utils/querys/admin/userRoles";
|
||||||
|
//import { Checkbox } from "@radix-ui/react-checkbox";
|
||||||
|
|
||||||
|
export default function ModuleAccess(data: any) {
|
||||||
|
const token = localStorage.getItem("auth_token");
|
||||||
|
// const { data: userRoles } = useQuery(getUserRoles());
|
||||||
|
const {
|
||||||
|
data: modules,
|
||||||
|
isError,
|
||||||
|
isLoading,
|
||||||
|
} = useQuery(getModules(token ?? ""));
|
||||||
|
|
||||||
|
if (isError) return <div>Error gettings Roles</div>;
|
||||||
|
if (isLoading) return <div>Loading modules</div>;
|
||||||
|
return (
|
||||||
|
<div className="flex flex-row flex-wrap">
|
||||||
|
{modules?.map((m: any) => {
|
||||||
|
return (
|
||||||
|
<div key={m.module_id}>
|
||||||
|
<ModuleForm
|
||||||
|
module={m}
|
||||||
|
user={data.user}
|
||||||
|
refetch={data.refetch}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
119
frontend/src/components/admin/user/components/ModuleForm.tsx
Normal file
119
frontend/src/components/admin/user/components/ModuleForm.tsx
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { Label } from "@/components/ui/label";
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectGroup,
|
||||||
|
SelectItem,
|
||||||
|
SelectLabel,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue,
|
||||||
|
} from "@/components/ui/select";
|
||||||
|
|
||||||
|
import { useForm } from "@tanstack/react-form";
|
||||||
|
|
||||||
|
import axios from "axios";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
|
||||||
|
export default function ModuleForm(props: any) {
|
||||||
|
const token = localStorage.getItem("auth_token");
|
||||||
|
const role =
|
||||||
|
props.user?.moduleRoles?.filter(
|
||||||
|
(m: any) => m.module_id === props.module.module_id
|
||||||
|
)[0]?.role ?? " ";
|
||||||
|
const form = useForm({
|
||||||
|
defaultValues: {
|
||||||
|
role: role,
|
||||||
|
},
|
||||||
|
onSubmit: async ({ value }) => {
|
||||||
|
const data: any = {
|
||||||
|
username: props.user.username,
|
||||||
|
module: props.module.name,
|
||||||
|
role: value.role,
|
||||||
|
};
|
||||||
|
console.log(data);
|
||||||
|
try {
|
||||||
|
const res = await axios.post("/api/auth/setuseraccess", data, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (res.data.success) {
|
||||||
|
toast.success(res.data.message);
|
||||||
|
props.refetch();
|
||||||
|
form.reset();
|
||||||
|
} else {
|
||||||
|
res.data.message;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="">
|
||||||
|
<form
|
||||||
|
onSubmit={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
}}
|
||||||
|
className="flex flex-row"
|
||||||
|
>
|
||||||
|
<form.Field
|
||||||
|
name="role"
|
||||||
|
//listeners={{onChange: ({value})=>{}}}
|
||||||
|
children={(field) => {
|
||||||
|
return (
|
||||||
|
<div className="m-2 min-w-48 max-w-96 p-2">
|
||||||
|
<Label htmlFor={field.name}>
|
||||||
|
Module: {props.module.name}
|
||||||
|
</Label>
|
||||||
|
<Select
|
||||||
|
value={field.state.value}
|
||||||
|
onValueChange={field.handleChange}
|
||||||
|
>
|
||||||
|
<SelectTrigger className="w-[180px]">
|
||||||
|
<SelectValue
|
||||||
|
id={field.name}
|
||||||
|
placeholder="Select Role"
|
||||||
|
/>
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectGroup>
|
||||||
|
<SelectLabel>Roles</SelectLabel>
|
||||||
|
<SelectItem value="viewer">
|
||||||
|
Viewer
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="technician">
|
||||||
|
Technician
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="supervisor">
|
||||||
|
Supervisor
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="manager">
|
||||||
|
Manager
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="tester">
|
||||||
|
Tester
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="admin">
|
||||||
|
Admin
|
||||||
|
</SelectItem>
|
||||||
|
</SelectGroup>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<div className="mt-4">
|
||||||
|
<Button type="submit" onClick={form.handleSubmit}>
|
||||||
|
Save
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import { useGetUserRoles } from "@/lib/store/useGetRoles";
|
||||||
|
import { useSubModuleStore } from "@/lib/store/useSubModuleStore";
|
||||||
|
|
||||||
|
import SubModuleForm from "./SubmoduleForm";
|
||||||
|
//import { Checkbox } from "@radix-ui/react-checkbox";
|
||||||
|
|
||||||
|
export default function UserSubRoles(data: any) {
|
||||||
|
const { userRoles } = useGetUserRoles();
|
||||||
|
const { subModules } = useSubModuleStore();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-row flex-wrap">
|
||||||
|
{subModules?.map((m: any) => {
|
||||||
|
const hasRole: any = userRoles.filter(
|
||||||
|
(r: any) =>
|
||||||
|
r.user_id.includes(data.user.user_id) &&
|
||||||
|
r.module_id === m.module_id
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<div key={m.module_id}>
|
||||||
|
<SubModuleForm
|
||||||
|
i={m}
|
||||||
|
hasRole={hasRole}
|
||||||
|
user={data.user}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
import { LstCard } from "@/components/extendedUI/LstCard";
|
||||||
|
import { Label } from "@/components/ui/label";
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectGroup,
|
||||||
|
SelectItem,
|
||||||
|
SelectLabel,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue,
|
||||||
|
} from "@/components/ui/select";
|
||||||
|
import { useForm } from "@tanstack/react-form";
|
||||||
|
|
||||||
|
export default function SubModuleForm(props: any) {
|
||||||
|
const form = useForm({
|
||||||
|
defaultValues: { role: "" },
|
||||||
|
onSubmit: async ({ value }) => {
|
||||||
|
console.log(value);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="m-2 p-1">
|
||||||
|
<LstCard>
|
||||||
|
<p className="text-center">
|
||||||
|
Module: {props.i.moduleName}, <br />
|
||||||
|
SubModule: {props.i.name}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p className="p-1">
|
||||||
|
Current role:{" "}
|
||||||
|
{props.hasRole[0]?.role
|
||||||
|
? props.hasRole[0].role
|
||||||
|
: "not assigned"}
|
||||||
|
</p>
|
||||||
|
<form
|
||||||
|
onSubmit={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<form.Field
|
||||||
|
name="role"
|
||||||
|
//listeners={{onChange: ({value})=>{}}}
|
||||||
|
children={(field) => {
|
||||||
|
return (
|
||||||
|
<div className="m-2 min-w-48 max-w-96 p-2">
|
||||||
|
<Label htmlFor={field.name}>
|
||||||
|
Select role
|
||||||
|
</Label>
|
||||||
|
<Select
|
||||||
|
value={field.state.value}
|
||||||
|
onValueChange={field.handleChange}
|
||||||
|
>
|
||||||
|
<SelectTrigger className="w-[180px]">
|
||||||
|
<SelectValue
|
||||||
|
id={field.name}
|
||||||
|
placeholder="Select Role"
|
||||||
|
/>
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectGroup>
|
||||||
|
<SelectLabel>Roles</SelectLabel>
|
||||||
|
<SelectItem value="viewer">
|
||||||
|
Viewer
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="technician">
|
||||||
|
Technician
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="supervisor">
|
||||||
|
Supervisor
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="manager">
|
||||||
|
Manager
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="tester">
|
||||||
|
Tester
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="admin">
|
||||||
|
Admin
|
||||||
|
</SelectItem>
|
||||||
|
</SelectGroup>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</form>
|
||||||
|
</LstCard>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
283
frontend/src/components/admin/user/components/UserCard.tsx
Normal file
283
frontend/src/components/admin/user/components/UserCard.tsx
Normal file
@@ -0,0 +1,283 @@
|
|||||||
|
import { LstCard } from "@/components/extendedUI/LstCard";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
import { Label } from "@/components/ui/label";
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectGroup,
|
||||||
|
SelectItem,
|
||||||
|
SelectLabel,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue,
|
||||||
|
} from "@/components/ui/select";
|
||||||
|
|
||||||
|
import { DebugButton } from "@/utils/formStuff/debugButton";
|
||||||
|
import { userFormOptions } from "@/utils/formStuff/options/userformOptions";
|
||||||
|
import { generatePassword } from "@/utils/passwordGen";
|
||||||
|
import { getUsers } from "@/utils/querys/admin/users";
|
||||||
|
import { useForm } from "@tanstack/react-form";
|
||||||
|
import { useQuery } from "@tanstack/react-query";
|
||||||
|
import axios from "axios";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
|
||||||
|
import { CardHeader } from "@/components/ui/card";
|
||||||
|
import ModuleAccess from "./ModuleAccess";
|
||||||
|
|
||||||
|
export default function UserCard(data: any) {
|
||||||
|
const token = localStorage.getItem("auth_token");
|
||||||
|
const { refetch } = useQuery(getUsers());
|
||||||
|
|
||||||
|
//console.log(userRoles);
|
||||||
|
const form = useForm({
|
||||||
|
...userFormOptions(data.user),
|
||||||
|
onSubmit: async ({ value }) => {
|
||||||
|
// Do something with form data
|
||||||
|
|
||||||
|
const userData = { ...value, user_id: data.user.user_id };
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await axios.patch(
|
||||||
|
"/api/auth/updateuser",
|
||||||
|
userData,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (res.data.success) {
|
||||||
|
toast.success(res.data.message);
|
||||||
|
refetch();
|
||||||
|
form.reset();
|
||||||
|
} else {
|
||||||
|
res.data.message;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<div className="flex flex-row">
|
||||||
|
<div className="m-2">
|
||||||
|
<LstCard>
|
||||||
|
<CardHeader>User Profile</CardHeader>
|
||||||
|
<form
|
||||||
|
onSubmit={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<form.Field
|
||||||
|
name="username"
|
||||||
|
validators={{
|
||||||
|
// We can choose between form-wide and field-specific validators
|
||||||
|
onChange: ({ value }) =>
|
||||||
|
value.length > 3
|
||||||
|
? undefined
|
||||||
|
: "Username must be longer than 3 letters",
|
||||||
|
}}
|
||||||
|
children={(field) => {
|
||||||
|
return (
|
||||||
|
<div className="m-2 min-w-48 max-w-96 p-2">
|
||||||
|
<Label htmlFor="username">
|
||||||
|
Username
|
||||||
|
</Label>
|
||||||
|
<Input
|
||||||
|
name={field.name}
|
||||||
|
value={field.state.value}
|
||||||
|
onBlur={field.handleBlur}
|
||||||
|
//type="number"
|
||||||
|
onChange={(e) =>
|
||||||
|
field.handleChange(
|
||||||
|
e.target.value
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
{field.state.meta.errors.length ? (
|
||||||
|
<em>
|
||||||
|
{field.state.meta.errors.join(
|
||||||
|
","
|
||||||
|
)}
|
||||||
|
</em>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<form.Field
|
||||||
|
name="email"
|
||||||
|
validators={{
|
||||||
|
// We can choose between form-wide and field-specific validators
|
||||||
|
onChange: ({ value }) =>
|
||||||
|
value.length > 3
|
||||||
|
? undefined
|
||||||
|
: "You must enter a correct ",
|
||||||
|
}}
|
||||||
|
children={(field) => {
|
||||||
|
return (
|
||||||
|
<div className="m-2 min-w-48 max-w-96 p-2">
|
||||||
|
<Label htmlFor="email">Email</Label>
|
||||||
|
<Input
|
||||||
|
name={field.name}
|
||||||
|
value={field.state.value}
|
||||||
|
onBlur={field.handleBlur}
|
||||||
|
//type="number"
|
||||||
|
onChange={(e) =>
|
||||||
|
field.handleChange(
|
||||||
|
e.target.value
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
{field.state.meta.errors.length ? (
|
||||||
|
<em>
|
||||||
|
{field.state.meta.errors.join(
|
||||||
|
","
|
||||||
|
)}
|
||||||
|
</em>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<form.Field
|
||||||
|
name="role"
|
||||||
|
//listeners={{onChange: ({value})=>{}}}
|
||||||
|
children={(field) => {
|
||||||
|
return (
|
||||||
|
<div className="m-2 min-w-48 max-w-96 p-2">
|
||||||
|
<Label htmlFor={field.name}>
|
||||||
|
Select role
|
||||||
|
</Label>
|
||||||
|
<Select
|
||||||
|
value={field.state.value}
|
||||||
|
onValueChange={field.handleChange}
|
||||||
|
>
|
||||||
|
<SelectTrigger className="w-[180px]">
|
||||||
|
<SelectValue
|
||||||
|
id={field.name}
|
||||||
|
placeholder="Select Role"
|
||||||
|
/>
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectGroup>
|
||||||
|
<SelectLabel>
|
||||||
|
Roles
|
||||||
|
</SelectLabel>
|
||||||
|
<SelectItem value="viewer">
|
||||||
|
Viewer
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="operator">
|
||||||
|
Operator
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="manager">
|
||||||
|
Manager
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="admin">
|
||||||
|
Admin
|
||||||
|
</SelectItem>
|
||||||
|
</SelectGroup>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<form.Field
|
||||||
|
name="password"
|
||||||
|
validators={{
|
||||||
|
onChangeAsyncDebounceMs: 500,
|
||||||
|
onChangeAsync: ({ value }) => {
|
||||||
|
if (
|
||||||
|
window.location.pathname.includes(
|
||||||
|
"/users"
|
||||||
|
) &&
|
||||||
|
value.length === 0
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (value.length < 4) {
|
||||||
|
return "Password must be at least 4 characters long.";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!/[A-Z]/.test(value)) {
|
||||||
|
return "Password must contain at least one uppercase letter.";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!/[a-z]/.test(value)) {
|
||||||
|
return "Password must contain at least one lower case letter.";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!/[0-9]/.test(value)) {
|
||||||
|
return "Password must contain at least one number.";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
!/[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/.test(
|
||||||
|
value
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return "Password must contain at least one special character.";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
children={(field) => {
|
||||||
|
return (
|
||||||
|
<div className="m-2 p-2">
|
||||||
|
<Label htmlFor="password">
|
||||||
|
Change Password
|
||||||
|
</Label>
|
||||||
|
<div className="mt-2 flex flex-row">
|
||||||
|
<Input
|
||||||
|
className="min-w-48 max-w-96"
|
||||||
|
name={field.name}
|
||||||
|
value={field.state.value}
|
||||||
|
onBlur={field.handleBlur}
|
||||||
|
//type="number"
|
||||||
|
onChange={(e) =>
|
||||||
|
field.handleChange(
|
||||||
|
e.target.value
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
className="ml-2"
|
||||||
|
onClick={() =>
|
||||||
|
field.handleChange(
|
||||||
|
generatePassword(8)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Random password
|
||||||
|
</Button>
|
||||||
|
<DebugButton
|
||||||
|
data={form.state.values}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{field.state.meta.errors.length ? (
|
||||||
|
<em>
|
||||||
|
{field.state.meta.errors.join(
|
||||||
|
","
|
||||||
|
)}
|
||||||
|
</em>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<div className="mt-4 ml-4">
|
||||||
|
<Button onClick={form.handleSubmit}>Save</Button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</LstCard>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<LstCard>
|
||||||
|
<ModuleAccess user={data.user} refetch={refetch} />
|
||||||
|
</LstCard>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@ import { LstCard } from "../extendedUI/LstCard";
|
|||||||
import { CardHeader } from "../ui/card";
|
import { CardHeader } from "../ui/card";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { useRouter } from "@tanstack/react-router";
|
import { useRouter, useSearch } from "@tanstack/react-router";
|
||||||
import { Controller, useForm } from "react-hook-form";
|
import { Controller, useForm } from "react-hook-form";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { Label } from "../ui/label";
|
import { Label } from "../ui/label";
|
||||||
@@ -12,153 +12,160 @@ import { Checkbox } from "../ui/checkbox";
|
|||||||
import { Button } from "../ui/button";
|
import { Button } from "../ui/button";
|
||||||
|
|
||||||
const FormSchema = z.object({
|
const FormSchema = z.object({
|
||||||
username: z.string().min(1, "You must enter a valid username"),
|
username: z.string().min(1, "You must enter a valid username"),
|
||||||
password: z.string().min(4, "You must enter a valid password"),
|
password: z.string().min(4, "You must enter a valid password"),
|
||||||
rememberMe: z.boolean(),
|
rememberMe: z.boolean(),
|
||||||
});
|
});
|
||||||
|
|
||||||
const LoginForm = () => {
|
const LoginForm = () => {
|
||||||
const { setSession } = useSessionStore();
|
const { setSession } = useSessionStore();
|
||||||
const rememeberMe = localStorage.getItem("rememberMe") === "true";
|
const rememeberMe = localStorage.getItem("rememberMe") === "true";
|
||||||
const username = localStorage.getItem("username") || "";
|
const username = localStorage.getItem("username") || "";
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const {
|
const search = useSearch({ from: "/login" });
|
||||||
register,
|
const {
|
||||||
handleSubmit,
|
register,
|
||||||
control,
|
handleSubmit,
|
||||||
formState: { errors },
|
control,
|
||||||
} = useForm<z.infer<typeof FormSchema>>({
|
formState: { errors },
|
||||||
resolver: zodResolver(FormSchema),
|
} = useForm<z.infer<typeof FormSchema>>({
|
||||||
defaultValues: {
|
resolver: zodResolver(FormSchema),
|
||||||
username: username || "",
|
defaultValues: {
|
||||||
password: "",
|
username: username || "",
|
||||||
rememberMe: rememeberMe,
|
password: "",
|
||||||
},
|
rememberMe: rememeberMe,
|
||||||
});
|
|
||||||
|
|
||||||
const onSubmitLogin = async (value: z.infer<typeof FormSchema>) => {
|
|
||||||
// Do something with form data
|
|
||||||
|
|
||||||
// first update the rememberMe incase it was selected
|
|
||||||
if (value.rememberMe) {
|
|
||||||
localStorage.setItem("rememberMe", value.rememberMe.toString());
|
|
||||||
localStorage.setItem("username", value.username);
|
|
||||||
} else {
|
|
||||||
localStorage.removeItem("rememberMe");
|
|
||||||
localStorage.removeItem("username");
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await fetch("/api/auth/login", {
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
});
|
||||||
username: value.username,
|
|
||||||
password: value.password,
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
const data = await response.json();
|
const onSubmitLogin = async (value: z.infer<typeof FormSchema>) => {
|
||||||
|
// Do something with form data
|
||||||
|
|
||||||
// Store token in localStorage
|
// first update the rememberMe incase it was selected
|
||||||
// localStorage.setItem("auth_token", data.data.token);
|
if (value.rememberMe) {
|
||||||
if (data.success) {
|
localStorage.setItem("rememberMe", value.rememberMe.toString());
|
||||||
const prod = btoa(`${value.username.toLowerCase()}:${value.password}`);
|
localStorage.setItem("username", value.username);
|
||||||
const prodUser = { ...data.user, prod: prod };
|
} else {
|
||||||
|
localStorage.removeItem("rememberMe");
|
||||||
|
localStorage.removeItem("username");
|
||||||
|
}
|
||||||
|
|
||||||
setSession(prodUser, data.token);
|
try {
|
||||||
toast.success(`You are logged in as ${data.user.username}`);
|
const response = await fetch("/api/auth/login", {
|
||||||
router.navigate({ to: "/" });
|
method: "POST",
|
||||||
}
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
username: value.username,
|
||||||
|
password: value.password,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
if (!data.success) {
|
const data = await response.json();
|
||||||
toast.error(`${data.message}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
//console.log(data);
|
// Store token in localStorage
|
||||||
} catch (err) {
|
// localStorage.setItem("auth_token", data.data.token);
|
||||||
toast.error("Invalid credentials");
|
if (data.success) {
|
||||||
}
|
const prod = btoa(
|
||||||
};
|
`${value.username.toLowerCase()}:${value.password}`
|
||||||
|
);
|
||||||
|
const prodUser = { ...data.user, prod: prod };
|
||||||
|
|
||||||
return (
|
setSession(prodUser, data.token);
|
||||||
<div className="ml-[25%]">
|
toast.success(`You are logged in as ${data.user.username}`);
|
||||||
<LstCard className="p-3 w-96">
|
|
||||||
<CardHeader>
|
|
||||||
<div>
|
|
||||||
<p className="text-2xl">Login to LST</p>
|
|
||||||
</div>
|
|
||||||
</CardHeader>
|
|
||||||
<hr className="rounded"></hr>
|
|
||||||
<form onSubmit={handleSubmit(onSubmitLogin)}>
|
|
||||||
<div>
|
|
||||||
<Label htmlFor="username" className="m-1">
|
|
||||||
Username
|
|
||||||
</Label>
|
|
||||||
<Input
|
|
||||||
placeholder="smith001"
|
|
||||||
{...register("username")}
|
|
||||||
className={errors.username ? "border-red-500" : ""}
|
|
||||||
aria-invalid={!!errors.username}
|
|
||||||
/>
|
|
||||||
{errors.username && (
|
|
||||||
<p className="text-red-500 text-sm mt-1">
|
|
||||||
{errors.username.message}
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<>
|
|
||||||
<Label htmlFor={"password"} className="m-1">
|
|
||||||
Password
|
|
||||||
</Label>
|
|
||||||
<Input
|
|
||||||
type="password"
|
|
||||||
{...register("password")}
|
|
||||||
className={errors.password ? "border-red-500" : ""}
|
|
||||||
aria-invalid={!!errors.password}
|
|
||||||
/>
|
|
||||||
{errors.password && (
|
|
||||||
<p className="text-red-500 text-sm mt-1">
|
|
||||||
{errors.password.message}
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
</div>
|
|
||||||
<div className="flex justify-between pt-2">
|
|
||||||
<div className="flex">
|
|
||||||
<Controller
|
|
||||||
render={({ field }) => (
|
|
||||||
<>
|
|
||||||
<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}
|
|
||||||
name="rememberMe"
|
|
||||||
defaultValue={rememeberMe}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex justify-end">
|
console.log(search.redirect ? search.redirect : "oops");
|
||||||
<Button type="submit">Submit</Button>
|
router.history.push(search.redirect ? search.redirect : "/");
|
||||||
</div>
|
}
|
||||||
</div>
|
|
||||||
</form>
|
if (!data.success) {
|
||||||
</LstCard>
|
toast.error(`${data.message}`);
|
||||||
</div>
|
}
|
||||||
);
|
|
||||||
|
//console.log(data);
|
||||||
|
} catch (err) {
|
||||||
|
toast.error("Invalid credentials");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="ml-[25%]">
|
||||||
|
<LstCard className="p-3 w-96">
|
||||||
|
<CardHeader>
|
||||||
|
<div>
|
||||||
|
<p className="text-2xl">Login to LST</p>
|
||||||
|
</div>
|
||||||
|
</CardHeader>
|
||||||
|
<hr className="rounded"></hr>
|
||||||
|
<form onSubmit={handleSubmit(onSubmitLogin)}>
|
||||||
|
<div>
|
||||||
|
<Label htmlFor="username" className="m-1">
|
||||||
|
Username
|
||||||
|
</Label>
|
||||||
|
<Input
|
||||||
|
placeholder="smith001"
|
||||||
|
{...register("username")}
|
||||||
|
className={errors.username ? "border-red-500" : ""}
|
||||||
|
aria-invalid={!!errors.username}
|
||||||
|
/>
|
||||||
|
{errors.username && (
|
||||||
|
<p className="text-red-500 text-sm mt-1">
|
||||||
|
{errors.username.message}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<>
|
||||||
|
<Label htmlFor={"password"} className="m-1">
|
||||||
|
Password
|
||||||
|
</Label>
|
||||||
|
<Input
|
||||||
|
type="password"
|
||||||
|
{...register("password")}
|
||||||
|
className={
|
||||||
|
errors.password ? "border-red-500" : ""
|
||||||
|
}
|
||||||
|
aria-invalid={!!errors.password}
|
||||||
|
/>
|
||||||
|
{errors.password && (
|
||||||
|
<p className="text-red-500 text-sm mt-1">
|
||||||
|
{errors.password.message}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
</div>
|
||||||
|
<div className="flex justify-between pt-2">
|
||||||
|
<div className="flex">
|
||||||
|
<Controller
|
||||||
|
render={({ field }) => (
|
||||||
|
<>
|
||||||
|
<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}
|
||||||
|
name="rememberMe"
|
||||||
|
defaultValue={rememeberMe}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex justify-end">
|
||||||
|
<Button type="submit">Submit</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</LstCard>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default LoginForm;
|
export default LoginForm;
|
||||||
|
|||||||
33
frontend/src/components/changelog/ChangeLog.tsx
Normal file
33
frontend/src/components/changelog/ChangeLog.tsx
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
// src/components/Changelog.jsx
|
||||||
|
import { marked } from "marked";
|
||||||
|
import changelog from "../../../../CHANGELOG.md?raw"; // assuming changelog.md is in root
|
||||||
|
|
||||||
|
const Changelog = () => {
|
||||||
|
const html: any = marked.parse(changelog);
|
||||||
|
const recentChanges = html.split("<h2>")[1];
|
||||||
|
// const [htmlContent, setHtmlContent] = useState("");
|
||||||
|
|
||||||
|
// useEffect(() => {
|
||||||
|
// fetch("/changelog.md")
|
||||||
|
// .then((res) => res.text())
|
||||||
|
// .then((md) => {
|
||||||
|
// const versionBlocks = md.split(/^##\s+/gm); // Split on headings
|
||||||
|
// if (versionBlocks.length > 1) {
|
||||||
|
// const latestBlock = `## ${versionBlocks[1]}`;
|
||||||
|
// const html: any = marked.parse(latestBlock, {
|
||||||
|
// breaks: true,
|
||||||
|
// gfm: true,
|
||||||
|
// });
|
||||||
|
// setHtmlContent(html);
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// }, []);
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="prose m-3"
|
||||||
|
dangerouslySetInnerHTML={{ __html: `<h2>${recentChanges}` }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Changelog;
|
||||||
47
frontend/src/components/dashboard/AddCards.tsx
Normal file
47
frontend/src/components/dashboard/AddCards.tsx
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogDescription,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
DialogTrigger,
|
||||||
|
} from "@/components/ui/dialog";
|
||||||
|
import Cards from "./Cards";
|
||||||
|
//import { toast } from "sonner";
|
||||||
|
|
||||||
|
export function AddCards() {
|
||||||
|
return (
|
||||||
|
<Dialog>
|
||||||
|
<DialogTrigger asChild>
|
||||||
|
<Button variant="outline">Add Cards</Button>
|
||||||
|
</DialogTrigger>
|
||||||
|
<DialogContent className="min-w-fit ">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>Cards</DialogTitle>
|
||||||
|
<DialogDescription>
|
||||||
|
Manage Cards and there settings.
|
||||||
|
</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
|
||||||
|
<div className="flex flex-row">
|
||||||
|
<div className="">
|
||||||
|
<Cards name={"ppoo"} inventory />
|
||||||
|
<Cards name={"inv-empty"} rowType={"empty"} />
|
||||||
|
<Cards name={"inv-fg"} rowType={"fg"} />
|
||||||
|
</div>
|
||||||
|
<div className="">
|
||||||
|
<Cards name={"inv-materials"} rowType={"materials"} />
|
||||||
|
<Cards name={"inv-packaging"} rowType={"packaging"} />
|
||||||
|
<Cards name={"inv-waste"} rowType={"waste"} />
|
||||||
|
<Cards name={"openOrder"} inventory />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* <DialogFooter>
|
||||||
|
<Button type="submit">Save changes</Button>
|
||||||
|
</DialogFooter> */}
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
}
|
||||||
185
frontend/src/components/dashboard/Cards.tsx
Normal file
185
frontend/src/components/dashboard/Cards.tsx
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
import { useCardStore } from "@/lib/store/useCardStore";
|
||||||
|
import { useForm } from "@tanstack/react-form";
|
||||||
|
import { Label } from "../ui/label";
|
||||||
|
import { Checkbox } from "../ui/checkbox";
|
||||||
|
import { Input } from "../ui/input";
|
||||||
|
// import {
|
||||||
|
// Select,
|
||||||
|
// SelectContent,
|
||||||
|
// SelectGroup,
|
||||||
|
// SelectItem,
|
||||||
|
// SelectLabel,
|
||||||
|
// SelectTrigger,
|
||||||
|
// SelectValue,
|
||||||
|
// } from "../ui/select";
|
||||||
|
import { Button } from "../ui/button";
|
||||||
|
|
||||||
|
export default function Cards(card: any) {
|
||||||
|
const { addCard, removeCard, cards } = useCardStore();
|
||||||
|
let existing: any = cards.filter((n: any) => n.name === card.name);
|
||||||
|
|
||||||
|
//console.log(existing);
|
||||||
|
const form = useForm({
|
||||||
|
defaultValues: {
|
||||||
|
name: existing[0]?.name || card.name,
|
||||||
|
rowType: existing[0]?.type ?? card.rowType,
|
||||||
|
age: existing[0]?.age ?? 90,
|
||||||
|
active: existing[0]?.active ?? false,
|
||||||
|
},
|
||||||
|
onSubmit: async ({ value }) => {
|
||||||
|
console.log(value);
|
||||||
|
const testCard: any = cards.filter(
|
||||||
|
(i: any) => i.name === value.name
|
||||||
|
);
|
||||||
|
|
||||||
|
if (value.active) {
|
||||||
|
const newCard = {
|
||||||
|
name: `${value.name}`,
|
||||||
|
rowType: value.rowType,
|
||||||
|
age: value.age ?? 90,
|
||||||
|
active: value.active,
|
||||||
|
};
|
||||||
|
if (testCard.length > 0) {
|
||||||
|
removeCard(value.name);
|
||||||
|
addCard(newCard);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// change the name for a type card
|
||||||
|
|
||||||
|
addCard(newCard);
|
||||||
|
} else {
|
||||||
|
removeCard(value.name);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<div className="border-solid border-2 m-2">
|
||||||
|
<p>{card.name}</p>
|
||||||
|
<form
|
||||||
|
onSubmit={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
}}
|
||||||
|
className="flex flex-row"
|
||||||
|
>
|
||||||
|
<form.Field
|
||||||
|
name="active"
|
||||||
|
// validators={{
|
||||||
|
// // We can choose between form-wide and field-specific validators
|
||||||
|
// onChange: ({ value }) =>
|
||||||
|
// value.length > 3
|
||||||
|
// ? undefined
|
||||||
|
// : "Username must be longer than 3 letters",
|
||||||
|
// }}
|
||||||
|
children={(field) => {
|
||||||
|
return (
|
||||||
|
<div className="m-2 p-2 flex flex-row">
|
||||||
|
<div>
|
||||||
|
<Label htmlFor="active">
|
||||||
|
<span>Active</span>
|
||||||
|
</Label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Checkbox
|
||||||
|
className="ml-2"
|
||||||
|
name={field.name}
|
||||||
|
onBlur={field.handleBlur}
|
||||||
|
checked={field.state.value}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
field.handleChange(e)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{!card.inventory && (
|
||||||
|
<>
|
||||||
|
<form.Field
|
||||||
|
name="age"
|
||||||
|
// validators={{
|
||||||
|
// // We can choose between form-wide and field-specific validators
|
||||||
|
// onChange: ({ value }) =>
|
||||||
|
// value.length > 3
|
||||||
|
// ? undefined
|
||||||
|
// : "Username must be longer than 3 letters",
|
||||||
|
// }}
|
||||||
|
children={(field) => {
|
||||||
|
return (
|
||||||
|
<div className="m-2 min-w-48 p-2">
|
||||||
|
<Label htmlFor="active" className="">
|
||||||
|
Age
|
||||||
|
</Label>
|
||||||
|
<Input
|
||||||
|
name={field.name}
|
||||||
|
onBlur={field.handleBlur}
|
||||||
|
value={field.state.value}
|
||||||
|
type="number"
|
||||||
|
onChange={(e) =>
|
||||||
|
field.handleChange(
|
||||||
|
e.target.value
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* <form.Field
|
||||||
|
name="rowType"
|
||||||
|
//listeners={{onChange: ({value})=>{}}}
|
||||||
|
children={(field) => {
|
||||||
|
return (
|
||||||
|
<div className="m-2 min-w-48 max-w-96 p-2">
|
||||||
|
<Label htmlFor={field.name}>
|
||||||
|
Row Type
|
||||||
|
</Label>
|
||||||
|
<Select
|
||||||
|
value={field.state.value}
|
||||||
|
onValueChange={field.handleChange}
|
||||||
|
>
|
||||||
|
<SelectTrigger className="w-[180px]">
|
||||||
|
<SelectValue
|
||||||
|
id={field.name}
|
||||||
|
placeholder="Select Role"
|
||||||
|
/>
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectGroup>
|
||||||
|
<SelectLabel>
|
||||||
|
Row Type
|
||||||
|
</SelectLabel>
|
||||||
|
<SelectItem value="empty">
|
||||||
|
Empty
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="fg">
|
||||||
|
Finished Goods
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="materials">
|
||||||
|
Materials
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="waste">
|
||||||
|
Waste
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="packaging">
|
||||||
|
Packaging
|
||||||
|
</SelectItem>
|
||||||
|
</SelectGroup>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/> */}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
<div className="mt-7">
|
||||||
|
<Button type="submit" onClick={() => form.handleSubmit()}>
|
||||||
|
Save Card
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
83
frontend/src/components/dashboard/DashBoard.tsx
Normal file
83
frontend/src/components/dashboard/DashBoard.tsx
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
import { useCardStore } from "@/lib/store/useCardStore";
|
||||||
|
import INVCheckCard from "../logistics/warehouse/InventoryCard";
|
||||||
|
import PPOO from "../logistics/warehouse/PPOOCard";
|
||||||
|
import OpenOrders from "../logistics/warehouse/openOrders";
|
||||||
|
|
||||||
|
const componentsMap: any = {
|
||||||
|
ppoo: PPOO,
|
||||||
|
inv: INVCheckCard,
|
||||||
|
openOrder: OpenOrders,
|
||||||
|
//QualityRequest,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function DashBoard() {
|
||||||
|
const { cards } = useCardStore();
|
||||||
|
|
||||||
|
//console.log(cards);
|
||||||
|
return (
|
||||||
|
<div className="ml-5 w-11/12 h-9/10 grid grid-cols-12 gap-1">
|
||||||
|
{cards.map((a: any) => {
|
||||||
|
const name = a.name; //.filter((c) => c.i === card.i)[0].i || "name";
|
||||||
|
|
||||||
|
const Component = componentsMap[name.split("-")[0]];
|
||||||
|
if (name === "openOrder") {
|
||||||
|
return (
|
||||||
|
<div key={a.name} className="col-span-6">
|
||||||
|
<Component age={a.age} type={a.rowType} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<div key={a.name} className="col-span-3">
|
||||||
|
<Component age={a.age} type={a.rowType} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
// return (
|
||||||
|
// <div className="ml-5 w-11/12 h-9/10 grid grid-cols-12 gap-1">
|
||||||
|
// <div className="col-span-3">
|
||||||
|
// <PPOO />
|
||||||
|
// </div>
|
||||||
|
// <div className="col-span-3">
|
||||||
|
// <INVCheckCard age={90} type={"empty"} />
|
||||||
|
// </div>
|
||||||
|
// <div className="col-span-3">
|
||||||
|
// <INVCheckCard age={75} type={"fg"} />
|
||||||
|
// </div>
|
||||||
|
// <div className="col-span-3">
|
||||||
|
// <INVCheckCard age={30} type={"materials"} />
|
||||||
|
// </div>
|
||||||
|
// <div className="col-span-3">
|
||||||
|
// <INVCheckCard age={7} type={"waste"} />
|
||||||
|
// </div>
|
||||||
|
// <div className="col-span-3">
|
||||||
|
// <INVCheckCard age={7} type={"packaging"} />
|
||||||
|
// </div>
|
||||||
|
// </div>
|
||||||
|
// );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
<div className="col-span-3">
|
||||||
|
<PPOO />
|
||||||
|
</div>
|
||||||
|
<div className="col-span-3">
|
||||||
|
<INVCheckCard age={30} type={"empty"} />
|
||||||
|
</div>
|
||||||
|
<div className="col-span-3">
|
||||||
|
<INVCheckCard age={30} type={"fg"} />
|
||||||
|
</div>
|
||||||
|
<div className="col-span-3">
|
||||||
|
<INVCheckCard age={30} type={"materials"} />
|
||||||
|
</div>
|
||||||
|
<div className="col-span-3">
|
||||||
|
<INVCheckCard age={30} type={"waste"} />
|
||||||
|
</div>
|
||||||
|
<div className="col-span-3">
|
||||||
|
<INVCheckCard age={30} type={"packaging"} />
|
||||||
|
</div>
|
||||||
|
*/
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import {ReactNode} from "react";
|
import { ReactNode } from "react";
|
||||||
import {Card} from "../ui/card";
|
import { Card } from "../ui/card";
|
||||||
|
|
||||||
interface LstCardProps {
|
interface LstCardProps {
|
||||||
children?: ReactNode;
|
children?: ReactNode;
|
||||||
@@ -7,12 +7,17 @@ interface LstCardProps {
|
|||||||
style?: React.CSSProperties;
|
style?: React.CSSProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function LstCard({children, className = "", style = {}}: LstCardProps) {
|
export function LstCard({
|
||||||
|
children,
|
||||||
|
className = "",
|
||||||
|
style = {},
|
||||||
|
}: LstCardProps) {
|
||||||
return (
|
return (
|
||||||
<div className="m-auto">
|
<Card
|
||||||
<Card className={`border-solid border-1 border-[#00659c] ${className}`} style={style}>
|
className={`border-solid border-1 border-[#00659c] ${className}`}
|
||||||
{children}
|
style={style}
|
||||||
</Card>
|
>
|
||||||
</div>
|
{children}
|
||||||
|
</Card>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,24 @@
|
|||||||
import {Sidebar, SidebarContent, SidebarFooter, SidebarTrigger} from "../ui/sidebar";
|
import {
|
||||||
import {ProductionSideBar} from "./side-components/production";
|
Sidebar,
|
||||||
import {Header} from "./side-components/header";
|
SidebarContent,
|
||||||
import {LogisticsSideBar} from "./side-components/logistics";
|
SidebarFooter,
|
||||||
import {QualitySideBar} from "./side-components/quality";
|
SidebarTrigger,
|
||||||
import {ForkliftSideBar} from "./side-components/forklift";
|
} from "../ui/sidebar";
|
||||||
import {EomSideBar} from "./side-components/eom";
|
import { ProductionSideBar } from "./side-components/production";
|
||||||
import {AdminSideBar} from "./side-components/admin";
|
import { Header } from "./side-components/header";
|
||||||
import {useSessionStore} from "../../lib/store/sessionStore";
|
import { LogisticsSideBar } from "./side-components/logistics";
|
||||||
import {hasAccess} from "../../utils/userAccess";
|
import { QualitySideBar } from "./side-components/quality";
|
||||||
import {moduleActive} from "../../utils/moduleActive";
|
import { ForkliftSideBar } from "./side-components/forklift";
|
||||||
import {useModuleStore} from "../../lib/store/useModuleStore";
|
import { EomSideBar } from "./side-components/eom";
|
||||||
|
import { AdminSideBar } from "./side-components/admin";
|
||||||
|
import { useSessionStore } from "../../lib/store/sessionStore";
|
||||||
|
import { hasAccess } from "../../utils/userAccess";
|
||||||
|
import { moduleActive } from "../../utils/moduleActive";
|
||||||
|
import { useModuleStore } from "../../lib/store/useModuleStore";
|
||||||
|
|
||||||
export function AppSidebar() {
|
export function AppSidebar() {
|
||||||
const {user} = useSessionStore();
|
const { user } = useSessionStore();
|
||||||
const {modules} = useModuleStore();
|
const { modules } = useModuleStore();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Sidebar collapsible="icon">
|
<Sidebar collapsible="icon">
|
||||||
@@ -22,19 +27,31 @@ export function AppSidebar() {
|
|||||||
{moduleActive("production") && (
|
{moduleActive("production") && (
|
||||||
<ProductionSideBar
|
<ProductionSideBar
|
||||||
user={user}
|
user={user}
|
||||||
moduleID={modules.filter((n) => n.name === "production")[0].module_id as string}
|
moduleID={
|
||||||
|
modules.filter((n) => n.name === "production")[0]
|
||||||
|
.module_id as string
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{moduleActive("logistics") && (
|
{moduleActive("logistics") && (
|
||||||
<LogisticsSideBar
|
<LogisticsSideBar
|
||||||
user={user}
|
user={user}
|
||||||
moduleID={modules.filter((n) => n.name === "logistics")[0].module_id as string}
|
moduleID={
|
||||||
|
modules.filter((n) => n.name === "logistics")[0]
|
||||||
|
.module_id as string
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{moduleActive("forklift") && hasAccess(user, "forklift", modules) && <ForkliftSideBar />}
|
{moduleActive("forklift") &&
|
||||||
{moduleActive("eom") && hasAccess(user, "eom", modules) && <EomSideBar />}
|
hasAccess(user, "forklift", modules) && <ForkliftSideBar />}
|
||||||
{moduleActive("quality") && hasAccess(user, "quality", modules) && <QualitySideBar />}
|
{moduleActive("eom") && hasAccess(user, "eom", modules) && (
|
||||||
{moduleActive("admin") && hasAccess(user, "admin", modules) && <AdminSideBar />}
|
<EomSideBar />
|
||||||
|
)}
|
||||||
|
{moduleActive("quality") &&
|
||||||
|
hasAccess(user, "quality", modules) && <QualitySideBar />}
|
||||||
|
{moduleActive("admin") && hasAccess(user, "admin", modules) && (
|
||||||
|
<AdminSideBar />
|
||||||
|
)}
|
||||||
</SidebarContent>
|
</SidebarContent>
|
||||||
<SidebarFooter>
|
<SidebarFooter>
|
||||||
<SidebarTrigger />
|
<SidebarTrigger />
|
||||||
|
|||||||
@@ -1,4 +1,15 @@
|
|||||||
import {Atom, Logs, Minus, Plus, Server, Settings, ShieldCheck, Users, Webhook} from "lucide-react";
|
import {
|
||||||
|
AlignJustify,
|
||||||
|
Atom,
|
||||||
|
Logs,
|
||||||
|
Minus,
|
||||||
|
Plus,
|
||||||
|
Server,
|
||||||
|
Settings,
|
||||||
|
ShieldCheck,
|
||||||
|
Users,
|
||||||
|
Webhook,
|
||||||
|
} from "lucide-react";
|
||||||
import {
|
import {
|
||||||
SidebarGroup,
|
SidebarGroup,
|
||||||
SidebarGroupContent,
|
SidebarGroupContent,
|
||||||
@@ -10,79 +21,131 @@ import {
|
|||||||
SidebarMenuSubButton,
|
SidebarMenuSubButton,
|
||||||
SidebarMenuSubItem,
|
SidebarMenuSubItem,
|
||||||
} from "../../ui/sidebar";
|
} from "../../ui/sidebar";
|
||||||
import {Collapsible, CollapsibleContent, CollapsibleTrigger} from "../../ui/collapsible";
|
import {
|
||||||
|
Collapsible,
|
||||||
|
CollapsibleContent,
|
||||||
|
CollapsibleTrigger,
|
||||||
|
} from "../../ui/collapsible";
|
||||||
|
import { useSubModuleStore } from "@/lib/store/useSubModuleStore";
|
||||||
|
|
||||||
const items = [
|
const iconMap: any = {
|
||||||
{
|
ShieldCheck: ShieldCheck,
|
||||||
title: "Servers",
|
AlignJustify: AlignJustify,
|
||||||
url: "/servers",
|
Settings: Settings,
|
||||||
icon: Server,
|
Atom: Atom,
|
||||||
isActive: false,
|
Logs: Logs,
|
||||||
},
|
Users: Users,
|
||||||
];
|
Webhook: Webhook,
|
||||||
const data = {
|
Server: Server,
|
||||||
navMain: [
|
|
||||||
{
|
|
||||||
title: "Admin",
|
|
||||||
url: "#",
|
|
||||||
icon: ShieldCheck,
|
|
||||||
items: [
|
|
||||||
{
|
|
||||||
title: "Settings",
|
|
||||||
url: "/settings",
|
|
||||||
icon: Settings,
|
|
||||||
isActive: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Modules",
|
|
||||||
url: "/modules",
|
|
||||||
icon: Settings,
|
|
||||||
isActive: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Swagger",
|
|
||||||
url: "#",
|
|
||||||
icon: Webhook,
|
|
||||||
isActive: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Logs",
|
|
||||||
url: "#",
|
|
||||||
icon: Logs,
|
|
||||||
isActive: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Users",
|
|
||||||
url: "#",
|
|
||||||
icon: Users,
|
|
||||||
isActive: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "UCD",
|
|
||||||
url: "https://ucd.alpla.net:8443/",
|
|
||||||
icon: Atom,
|
|
||||||
isActive: false,
|
|
||||||
newWindow: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Lst Api",
|
|
||||||
url: "/api/docs",
|
|
||||||
icon: Webhook,
|
|
||||||
isActive: false,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export function AdminSideBar() {
|
export function AdminSideBar() {
|
||||||
|
const { subModules } = useSubModuleStore();
|
||||||
|
|
||||||
|
const items = subModules.filter((m) => m.moduleName === "admin");
|
||||||
return (
|
return (
|
||||||
<SidebarGroup>
|
<SidebarGroup>
|
||||||
<SidebarGroupLabel>Admin section</SidebarGroupLabel>
|
<SidebarGroupLabel>Admin section</SidebarGroupLabel>
|
||||||
<SidebarGroupContent>
|
<SidebarGroupContent>
|
||||||
<SidebarMenu>
|
{items.map((item: any, index) => {
|
||||||
|
const Icon = iconMap[item.icon] || AlignJustify;
|
||||||
|
// drop down menu setup
|
||||||
|
return (
|
||||||
|
<SidebarMenu key={item.name}>
|
||||||
|
{item.link === "#" ? (
|
||||||
|
<Collapsible
|
||||||
|
key={item.name}
|
||||||
|
defaultOpen={index === 1}
|
||||||
|
className="group/collapsible"
|
||||||
|
>
|
||||||
|
<SidebarMenuItem>
|
||||||
|
<CollapsibleTrigger asChild>
|
||||||
|
<SidebarMenuButton>
|
||||||
|
<Icon />
|
||||||
|
{item.name}{" "}
|
||||||
|
<Plus className="ml-auto group-data-[state=open]/collapsible:hidden" />
|
||||||
|
<Minus className="ml-auto group-data-[state=closed]/collapsible:hidden" />
|
||||||
|
</SidebarMenuButton>
|
||||||
|
</CollapsibleTrigger>
|
||||||
|
{item.subSubModule?.length > 0 ? (
|
||||||
|
<CollapsibleContent>
|
||||||
|
<SidebarMenuSub>
|
||||||
|
{item.subSubModule.map(
|
||||||
|
(i: any) => {
|
||||||
|
const SubIcon =
|
||||||
|
iconMap[
|
||||||
|
i.icon
|
||||||
|
] ||
|
||||||
|
AlignJustify;
|
||||||
|
return (
|
||||||
|
<SidebarMenuSubItem
|
||||||
|
key={i.name}
|
||||||
|
>
|
||||||
|
{i.isActive && (
|
||||||
|
<SidebarMenuSubButton
|
||||||
|
asChild
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
href={
|
||||||
|
i.link
|
||||||
|
}
|
||||||
|
target={
|
||||||
|
i.newWindow
|
||||||
|
? "_blank"
|
||||||
|
: "_self"
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<SubIcon />
|
||||||
|
<span>
|
||||||
|
{
|
||||||
|
i.name
|
||||||
|
}
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
</SidebarMenuSubButton>
|
||||||
|
)}
|
||||||
|
</SidebarMenuSubItem>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
</SidebarMenuSub>
|
||||||
|
</CollapsibleContent>
|
||||||
|
) : null}
|
||||||
|
</SidebarMenuItem>
|
||||||
|
</Collapsible>
|
||||||
|
) : (
|
||||||
|
<SidebarMenu>
|
||||||
|
{items.map((item) => {
|
||||||
|
if (item.link === "#") return;
|
||||||
|
return (
|
||||||
|
<SidebarMenuItem key={item.name}>
|
||||||
|
<SidebarMenuButton asChild>
|
||||||
|
<a href={item.link}>
|
||||||
|
<Icon />
|
||||||
|
<span>{item.name}</span>
|
||||||
|
</a>
|
||||||
|
</SidebarMenuButton>
|
||||||
|
</SidebarMenuItem>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</SidebarMenu>
|
||||||
|
)}
|
||||||
|
</SidebarMenu>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</SidebarGroupContent>
|
||||||
|
</SidebarGroup>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
/* <SidebarMenu>
|
||||||
{data.navMain.map((item, index) => (
|
{data.navMain.map((item, index) => (
|
||||||
<Collapsible key={item.title} defaultOpen={index === 1} className="group/collapsible">
|
<Collapsible
|
||||||
|
key={item.title}
|
||||||
|
defaultOpen={index === 1}
|
||||||
|
className="group/collapsible"
|
||||||
|
>
|
||||||
<SidebarMenuItem>
|
<SidebarMenuItem>
|
||||||
<CollapsibleTrigger asChild>
|
<CollapsibleTrigger asChild>
|
||||||
<SidebarMenuButton>
|
<SidebarMenuButton>
|
||||||
@@ -96,15 +159,25 @@ export function AdminSideBar() {
|
|||||||
<CollapsibleContent>
|
<CollapsibleContent>
|
||||||
<SidebarMenuSub>
|
<SidebarMenuSub>
|
||||||
{item.items.map((item) => (
|
{item.items.map((item) => (
|
||||||
<SidebarMenuSubItem key={item.title}>
|
<SidebarMenuSubItem
|
||||||
|
key={item.title}
|
||||||
|
>
|
||||||
{item.isActive && (
|
{item.isActive && (
|
||||||
<SidebarMenuSubButton asChild>
|
<SidebarMenuSubButton
|
||||||
|
asChild
|
||||||
|
>
|
||||||
<a
|
<a
|
||||||
href={item.url}
|
href={item.url}
|
||||||
target={item.newWindow ? "_blank" : "_self"}
|
target={
|
||||||
|
item.newWindow
|
||||||
|
? "_blank"
|
||||||
|
: "_self"
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<item.icon />
|
<item.icon />
|
||||||
<span>{item.title}</span>
|
<span>
|
||||||
|
{item.title}
|
||||||
|
</span>
|
||||||
</a>
|
</a>
|
||||||
</SidebarMenuSubButton>
|
</SidebarMenuSubButton>
|
||||||
)}
|
)}
|
||||||
@@ -128,8 +201,5 @@ export function AdminSideBar() {
|
|||||||
</SidebarMenuButton>
|
</SidebarMenuButton>
|
||||||
</SidebarMenuItem>
|
</SidebarMenuItem>
|
||||||
))}
|
))}
|
||||||
</SidebarMenu>
|
</SidebarMenu> */
|
||||||
</SidebarGroupContent>
|
|
||||||
</SidebarGroup>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import {Cylinder, Package, Truck} from "lucide-react";
|
import { Cylinder, Package, Truck } from "lucide-react";
|
||||||
import {
|
import {
|
||||||
SidebarGroup,
|
SidebarGroup,
|
||||||
SidebarGroupContent,
|
SidebarGroupContent,
|
||||||
@@ -7,80 +7,54 @@ import {
|
|||||||
SidebarMenuButton,
|
SidebarMenuButton,
|
||||||
SidebarMenuItem,
|
SidebarMenuItem,
|
||||||
} from "../../ui/sidebar";
|
} from "../../ui/sidebar";
|
||||||
import {hasPageAccess} from "@/utils/userAccess";
|
import { hasPageAccess } from "@/utils/userAccess";
|
||||||
import {User} from "@/types/users";
|
import { User } from "@/types/users";
|
||||||
// this will need to be moved to a links section the db to make it more easy to remove and add
|
import { useSubModuleStore } from "@/lib/store/useSubModuleStore";
|
||||||
const items = [
|
|
||||||
{
|
const iconMap: any = {
|
||||||
title: "Silo Adjustments",
|
Package: Package,
|
||||||
url: "#",
|
Truck: Truck,
|
||||||
icon: Cylinder,
|
Cylinder: Cylinder,
|
||||||
role: ["admin", "systemAdmin"],
|
};
|
||||||
module: "logistics",
|
|
||||||
active: true,
|
export function LogisticsSideBar({
|
||||||
},
|
user,
|
||||||
{
|
moduleID,
|
||||||
title: "Bulk orders",
|
}: {
|
||||||
url: "#",
|
user: User | null;
|
||||||
icon: Truck,
|
moduleID: string;
|
||||||
role: ["systemAdmin"],
|
}) {
|
||||||
module: "logistics",
|
const { subModules } = useSubModuleStore();
|
||||||
active: true,
|
|
||||||
},
|
const items = subModules.filter((m) => m.moduleName === "logistics");
|
||||||
{
|
|
||||||
title: "Forecast",
|
|
||||||
url: "#",
|
|
||||||
icon: Truck,
|
|
||||||
role: ["systemAdmin"],
|
|
||||||
module: "logistics",
|
|
||||||
active: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Ocme cycle counts",
|
|
||||||
url: "#",
|
|
||||||
icon: Package,
|
|
||||||
role: ["technician", "supervisor", "manager", "admin", "systemAdmin"],
|
|
||||||
module: "logistics",
|
|
||||||
active: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Material Helper",
|
|
||||||
url: "/materialHelper/consumption",
|
|
||||||
icon: Package,
|
|
||||||
role: ["technician", "supervisor", "manager", "admin", "systemAdmin"],
|
|
||||||
module: "logistics",
|
|
||||||
active: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Ocme Cyclecount",
|
|
||||||
url: "/cyclecount",
|
|
||||||
icon: Package,
|
|
||||||
role: ["technician", "supervisor", "manager", "admin", "systemAdmin"],
|
|
||||||
module: "logistics",
|
|
||||||
active: true,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export function LogisticsSideBar({user, moduleID}: {user: User | null; moduleID: string}) {
|
|
||||||
return (
|
return (
|
||||||
<SidebarGroup>
|
<SidebarGroup>
|
||||||
<SidebarGroupLabel>Logistics</SidebarGroupLabel>
|
<SidebarGroupLabel>Logistics</SidebarGroupLabel>
|
||||||
<SidebarGroupContent>
|
<SidebarGroupContent>
|
||||||
<SidebarMenu>
|
<SidebarMenu>
|
||||||
{items.map((item) => (
|
{items.map((item) => {
|
||||||
<SidebarMenuItem key={item.title}>
|
const Icon = iconMap[item.icon];
|
||||||
<>
|
return (
|
||||||
{hasPageAccess(user, item.role, moduleID) && item.active && (
|
<SidebarMenuItem key={item.submodule_id}>
|
||||||
<SidebarMenuButton asChild>
|
<>
|
||||||
<a href={item.url}>
|
{hasPageAccess(
|
||||||
<item.icon />
|
user,
|
||||||
<span>{item.title}</span>
|
item.roles,
|
||||||
</a>
|
moduleID
|
||||||
</SidebarMenuButton>
|
) &&
|
||||||
)}
|
item.active && (
|
||||||
</>
|
<SidebarMenuButton asChild>
|
||||||
</SidebarMenuItem>
|
<a href={item.link}>
|
||||||
))}
|
<Icon />
|
||||||
|
<span>{item.name}</span>
|
||||||
|
</a>
|
||||||
|
</SidebarMenuButton>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
</SidebarMenuItem>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</SidebarMenu>
|
</SidebarMenu>
|
||||||
</SidebarGroupContent>
|
</SidebarGroupContent>
|
||||||
</SidebarGroup>
|
</SidebarGroup>
|
||||||
|
|||||||
113
frontend/src/components/logistics/siloAdjustments/ChartData.tsx
Normal file
113
frontend/src/components/logistics/siloAdjustments/ChartData.tsx
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
import { Area, AreaChart, CartesianGrid, XAxis } from "recharts";
|
||||||
|
|
||||||
|
import { CardContent } from "@/components/ui/card";
|
||||||
|
|
||||||
|
import {
|
||||||
|
ChartConfig,
|
||||||
|
ChartContainer,
|
||||||
|
ChartTooltip,
|
||||||
|
ChartTooltipContent,
|
||||||
|
} from "@/components/ui/chart";
|
||||||
|
import { useQuery } from "@tanstack/react-query";
|
||||||
|
import { getAdjustments } from "@/utils/querys/logistics/siloAdjustments/getAdjustments";
|
||||||
|
import { LstCard } from "@/components/extendedUI/LstCard";
|
||||||
|
import { format } from "date-fns";
|
||||||
|
|
||||||
|
export default function ChartData(props: any) {
|
||||||
|
const { data, isError, isLoading } = useQuery(getAdjustments());
|
||||||
|
const chartConfig = {
|
||||||
|
stock: {
|
||||||
|
label: "Stock",
|
||||||
|
color: "rgb(255, 99, 132)",
|
||||||
|
},
|
||||||
|
actual: {
|
||||||
|
label: "Actual",
|
||||||
|
color: "rgb(53, 162, 235)",
|
||||||
|
},
|
||||||
|
} satisfies ChartConfig;
|
||||||
|
|
||||||
|
if (isLoading) return <div>Loading chart data</div>;
|
||||||
|
if (isError) return <div>Error in loading chart data</div>;
|
||||||
|
|
||||||
|
let adjustments: any = data.filter(
|
||||||
|
(l: any) => l.locationID === props.laneId
|
||||||
|
);
|
||||||
|
adjustments = adjustments.splice(0, 10).map((s: any) => {
|
||||||
|
return {
|
||||||
|
date: format(s.dateAdjusted.replace("Z", ""), "M/d/yyyy hh:mm"),
|
||||||
|
stock: s.currentStockLevel,
|
||||||
|
actual: s.newLevel,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<LstCard className="w-[425px] h-[250px] m-1">
|
||||||
|
<CardContent>
|
||||||
|
{adjustments.length === 0 ? (
|
||||||
|
<span>No silo data has been entered for this silo.</span>
|
||||||
|
) : (
|
||||||
|
<ChartContainer config={chartConfig}>
|
||||||
|
<AreaChart
|
||||||
|
accessibilityLayer
|
||||||
|
data={adjustments}
|
||||||
|
margin={{
|
||||||
|
left: 35,
|
||||||
|
right: 45,
|
||||||
|
bottom: 50,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CartesianGrid vertical={false} />
|
||||||
|
<XAxis
|
||||||
|
dataKey="date"
|
||||||
|
tickLine={false}
|
||||||
|
axisLine={false}
|
||||||
|
tickMargin={14}
|
||||||
|
angle={-45}
|
||||||
|
textAnchor="end"
|
||||||
|
dy={10}
|
||||||
|
tickFormatter={(value) =>
|
||||||
|
format(value, "M/d/yyyy")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<ChartTooltip
|
||||||
|
cursor={false}
|
||||||
|
content={
|
||||||
|
<ChartTooltipContent indicator="dot" />
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<Area
|
||||||
|
dataKey="stock"
|
||||||
|
type="natural"
|
||||||
|
fill="rgba(53, 162, 235, 0.5)"
|
||||||
|
fillOpacity={0.4}
|
||||||
|
stroke="rgba(53, 162, 235, 0.5)"
|
||||||
|
stackId="a"
|
||||||
|
/>
|
||||||
|
<Area
|
||||||
|
dataKey="actual"
|
||||||
|
type="natural"
|
||||||
|
fill="rgba(255, 99, 132, 0.5)"
|
||||||
|
fillOpacity={0.4}
|
||||||
|
stroke="rgba(255, 99, 132, 0.5)"
|
||||||
|
stackId="a"
|
||||||
|
/>
|
||||||
|
</AreaChart>
|
||||||
|
</ChartContainer>
|
||||||
|
)}
|
||||||
|
</CardContent>
|
||||||
|
{/* <CardFooter>
|
||||||
|
<div className="flex w-full items-start gap-2 text-sm">
|
||||||
|
<div className="grid gap-2">
|
||||||
|
<div className="flex items-center gap-2 font-medium leading-none">
|
||||||
|
Trending up by 5.2% this month{" "}
|
||||||
|
<TrendingUp className="h-4 w-4" />
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-2 leading-none text-muted-foreground">
|
||||||
|
January - June 2024
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CardFooter> */}
|
||||||
|
</LstCard>
|
||||||
|
);
|
||||||
|
}
|
||||||
120
frontend/src/components/logistics/siloAdjustments/Comment.tsx
Normal file
120
frontend/src/components/logistics/siloAdjustments/Comment.tsx
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
import { LstCard } from "@/components/extendedUI/LstCard";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { CardContent, CardFooter, CardHeader } from "@/components/ui/card";
|
||||||
|
import { Label } from "@/components/ui/label";
|
||||||
|
import { Textarea } from "@/components/ui/textarea";
|
||||||
|
|
||||||
|
import { useForm } from "@tanstack/react-form";
|
||||||
|
import { useRouter } from "@tanstack/react-router";
|
||||||
|
import axios from "axios";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
|
||||||
|
export default function Comment(data: any) {
|
||||||
|
const token = localStorage.getItem("auth_token");
|
||||||
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const form = useForm({
|
||||||
|
defaultValues: {
|
||||||
|
comment: "",
|
||||||
|
},
|
||||||
|
onSubmit: async ({ value }) => {
|
||||||
|
setIsSubmitting(true);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await axios.post(
|
||||||
|
`/api/logistics/postcomment/${data.id.split("&")[0]}`,
|
||||||
|
{
|
||||||
|
comment: value.comment,
|
||||||
|
key: data.id.split("&")[1],
|
||||||
|
},
|
||||||
|
{ headers: { Authorization: `Bearer ${token}` } }
|
||||||
|
);
|
||||||
|
|
||||||
|
if (res.data.success) {
|
||||||
|
toast.success(res.data.message);
|
||||||
|
form.reset();
|
||||||
|
router.navigate({ to: "/siloAdjustments" });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!res.data.success) {
|
||||||
|
toast.error(res.data.message);
|
||||||
|
form.reset();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
toast.error(`There was an error posting your comment.`);
|
||||||
|
}
|
||||||
|
setIsSubmitting(false);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<div className="">
|
||||||
|
<LstCard>
|
||||||
|
<CardHeader>
|
||||||
|
Please enter your comment for the silo adjust
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<form
|
||||||
|
onSubmit={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<form.Field
|
||||||
|
name="comment"
|
||||||
|
validators={{
|
||||||
|
// We can choose between form-wide and field-specific validators
|
||||||
|
onChange: ({ value }) =>
|
||||||
|
value.length > 10
|
||||||
|
? undefined
|
||||||
|
: "Comment must be longer than 10 characters.",
|
||||||
|
}}
|
||||||
|
children={(field) => {
|
||||||
|
return (
|
||||||
|
<div className="m-2 min-w-48 max-w-96 p-2">
|
||||||
|
<Label
|
||||||
|
htmlFor="comment"
|
||||||
|
className="mb-2"
|
||||||
|
>
|
||||||
|
Comment
|
||||||
|
</Label>
|
||||||
|
<Textarea
|
||||||
|
name={field.name}
|
||||||
|
value={field.state.value}
|
||||||
|
onBlur={field.handleBlur}
|
||||||
|
//type="number"
|
||||||
|
onChange={(e) =>
|
||||||
|
field.handleChange(
|
||||||
|
e.target.value
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
{field.state.meta.errors.length ? (
|
||||||
|
<em>
|
||||||
|
{field.state.meta.errors.join(
|
||||||
|
","
|
||||||
|
)}
|
||||||
|
</em>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</form>
|
||||||
|
</CardContent>
|
||||||
|
<CardFooter>
|
||||||
|
<div className="flex justify-end">
|
||||||
|
<Button
|
||||||
|
onClick={form.handleSubmit}
|
||||||
|
disabled={isSubmitting}
|
||||||
|
>
|
||||||
|
Submit
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</CardFooter>
|
||||||
|
</LstCard>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
import { getAdjustments } from "@/utils/querys/logistics/siloAdjustments/getAdjustments";
|
||||||
|
import { columns } from "@/utils/tableData/siloAdjustmentHist/siloAdjHistColumns";
|
||||||
|
import { SiloTable } from "@/utils/tableData/siloAdjustmentHist/siloData";
|
||||||
|
import { useQuery } from "@tanstack/react-query";
|
||||||
|
|
||||||
|
export default function HistoricalData(props: any) {
|
||||||
|
const { data, isError, isLoading } = useQuery(getAdjustments());
|
||||||
|
|
||||||
|
if (isLoading) return <div>Loading adjustmnet data...</div>;
|
||||||
|
if (isError) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<p>There was an error getting the adjustments.</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
//console.log(data[0].locationID, parseInt(props.laneId));
|
||||||
|
const adjustments: any = data.filter(
|
||||||
|
(l: any) => l.locationID === parseInt(props.laneId)
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<div className="container mx-auto py-10">
|
||||||
|
<SiloTable columns={columns} data={adjustments} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user