Compare commits
214 Commits
dev
...
4effb25e9d
| Author | SHA1 | Date | |
|---|---|---|---|
| 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.zip
|
||||
postgresql-17.2-3-windows-x64.exe
|
||||
jsTesting
|
||||
|
||||
|
||||
# ---> Node
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
{
|
||||
"types": [
|
||||
{ "type": "feat", "section": "🌟 Enhancements" },
|
||||
{ "type": "fix", "section": "🐛 Bug fixes" },
|
||||
{ "type": "chore", "hidden": false, "section": "📝 Chore" },
|
||||
{ "type": "docs", "section": "📚 Documentation" },
|
||||
{ "type": "style", "hidden": true },
|
||||
{ "type": "refactor", "section": "🛠️ Code Refactor" },
|
||||
{ "type": "perf", "hidden": false, "section": "🚀 Performance" },
|
||||
{ "type": "test", "section": "📝 Testing Code" },
|
||||
{ "type": "ci", "hidden": false, "section": "📈 Project changes" },
|
||||
{ "type": "build", "hidden": true, "section": "📈 Project Builds" }
|
||||
],
|
||||
"commitUrlFormat": "https://git.tuffraid.net/cowch/lstV2/commits/{{hash}}",
|
||||
"compareUrlFormat": "https://git.tuffraid.net/cowch/lstV2/compare/{{previousTag}}...{{currentTag}}",
|
||||
"header": "# All CHanges to LST can be found below.\n"
|
||||
"types": [
|
||||
{ "type": "feat", "section": "🌟 Enhancements" },
|
||||
{ "type": "fix", "section": "🐛 Bug fixes" },
|
||||
{ "type": "chore", "hidden": false, "section": "📝 Chore" },
|
||||
{ "type": "docs", "section": "📚 Documentation" },
|
||||
{ "type": "style", "hidden": true },
|
||||
{ "type": "refactor", "section": "🛠️ Code Refactor" },
|
||||
{ "type": "perf", "hidden": false, "section": "🚀 Performance" },
|
||||
{ "type": "test", "section": "📝 Testing Code" },
|
||||
{ "type": "ci", "hidden": true, "section": "📈 Project changes" },
|
||||
{ "type": "build", "hidden": true, "section": "📈 Project Builds" }
|
||||
],
|
||||
"commitUrlFormat": "https://git.tuffraid.net/cowch/lstV2/commits/{{hash}}",
|
||||
"compareUrlFormat": "https://git.tuffraid.net/cowch/lstV2/compare/{{previousTag}}...{{currentTag}}",
|
||||
"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.formatOnSave": true,
|
||||
"[javascript]": {
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"[javascriptreact]": {
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"[typescript]": {
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"[typescriptreact]": {
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"[json]": {
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"[graphql]": {
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"[handlebars]": {
|
||||
"editor.formatOnSave": true
|
||||
}
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"workbench.colorTheme": "Default Dark+",
|
||||
"prettier.tabWidth": 4,
|
||||
"terminal.integrated.env.windows": {},
|
||||
"editor.formatOnSave": true,
|
||||
"[javascript]": {
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"[javascriptreact]": {
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"[typescript]": {
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"[typescriptreact]": {
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"[json]": {
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"[graphql]": {
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"[handlebars]": {
|
||||
"editor.formatOnSave": true
|
||||
}
|
||||
}
|
||||
|
||||
259
CHANGELOG.md
259
CHANGELOG.md
@@ -1,5 +1,264 @@
|
||||
# All CHanges to LST can be found below.
|
||||
|
||||
## [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)
|
||||
|
||||
|
||||
|
||||
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';
|
||||
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
@@ -183,6 +183,167 @@
|
||||
"when": 1742655504936,
|
||||
"tag": "0025_amusing_sugar_man",
|
||||
"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
|
||||
}
|
||||
]
|
||||
}
|
||||
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 {createInsertSchema, createSelectSchema} from "drizzle-zod";
|
||||
import {z} from "zod";
|
||||
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 ocmeData = pgTable(
|
||||
"ocmeData",
|
||||
@@ -20,6 +29,7 @@ export const ocmeData = pgTable(
|
||||
(table) => [
|
||||
// uniqueIndex('emailUniqueIndex').on(sql`lower(${table.email})`),
|
||||
// uniqueIndex("role_name").on(table.name),
|
||||
uniqueIndex("ocme_runningNr").on(table.runningNr),
|
||||
]
|
||||
);
|
||||
|
||||
|
||||
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);
|
||||
@@ -1,7 +1,14 @@
|
||||
import {text, pgTable, timestamp, uuid, uniqueIndex, jsonb} from "drizzle-orm/pg-core";
|
||||
import {createSelectSchema} from "drizzle-zod";
|
||||
import {z} from "zod";
|
||||
import {modules} from "./modules.js";
|
||||
import {
|
||||
text,
|
||||
pgTable,
|
||||
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(
|
||||
"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;
|
||||
817
frontend/package-lock.json
generated
817
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",
|
||||
"lint": "eslint .",
|
||||
"preview": "vite preview",
|
||||
"shad": "npx shadcn@canary add ",
|
||||
"shad": "npx shadcn@latest add ",
|
||||
"checkupdates": "npm-check-updates"
|
||||
},
|
||||
"dependencies": {
|
||||
"@hookform/resolvers": "^4.1.3",
|
||||
"@radix-ui/react-accordion": "^1.2.3",
|
||||
"@radix-ui/react-avatar": "^1.1.3",
|
||||
"@radix-ui/react-checkbox": "^1.1.4",
|
||||
"@radix-ui/react-collapsible": "^1.1.3",
|
||||
@@ -20,12 +21,14 @@
|
||||
"@radix-ui/react-dropdown-menu": "^2.1.6",
|
||||
"@radix-ui/react-label": "^2.1.2",
|
||||
"@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-separator": "^1.1.2",
|
||||
"@radix-ui/react-slot": "^1.1.2",
|
||||
"@radix-ui/react-tabs": "^1.1.3",
|
||||
"@radix-ui/react-tooltip": "^1.1.8",
|
||||
"@tailwindcss/vite": "^4.0.15",
|
||||
"@tanstack/react-form": "^1.2.1",
|
||||
"@tanstack/react-query": "^5.69.0",
|
||||
"@tanstack/react-router": "^1.114.27",
|
||||
"@tanstack/react-table": "^8.21.2",
|
||||
@@ -45,6 +48,7 @@
|
||||
"react-dom": "^19.0.0",
|
||||
"react-grid-layout": "^1.5.1",
|
||||
"react-hook-form": "^7.54.2",
|
||||
"react-resizable-panels": "^2.1.7",
|
||||
"sonner": "^2.0.1",
|
||||
"tailwind-merge": "^3.0.2",
|
||||
"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>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
export default function NotificationMGT() {
|
||||
return (
|
||||
<div>
|
||||
Manage all notifications from here instad of going to the db,
|
||||
locking some items that are auto updated on server restarts
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
import { LstCard } from "@/components/extendedUI/LstCard";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/components/ui/table";
|
||||
import { useSessionStore } from "@/lib/store/sessionStore";
|
||||
import { useModuleStore } from "@/lib/store/useModuleStore";
|
||||
@@ -19,107 +19,166 @@ import { adminUrlCheck } from "@/utils/adminUrlCheck";
|
||||
import RestartServer from "./RestartServer";
|
||||
import StopServer from "./StopServer";
|
||||
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 = {
|
||||
server_id?: string;
|
||||
sName?: string;
|
||||
serverDNS?: string;
|
||||
plantToken?: string;
|
||||
idAddress: string;
|
||||
lastUpdated: string;
|
||||
isUpgrading: boolean;
|
||||
server_id?: string;
|
||||
sName?: string;
|
||||
serverDNS?: string;
|
||||
plantToken?: string;
|
||||
idAddress: string;
|
||||
lastUpdated: string;
|
||||
isUpgrading: boolean;
|
||||
};
|
||||
|
||||
export default function ServerPage() {
|
||||
const { user, token } = useSessionStore();
|
||||
const { modules } = useModuleStore();
|
||||
const router = useRouter();
|
||||
const { user, token } = useSessionStore();
|
||||
const { modules } = useModuleStore();
|
||||
//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 userLevel =
|
||||
user?.roles?.filter((r) => r.module_id === adminModule[0].module_id) || [];
|
||||
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: "/" });
|
||||
}
|
||||
if (!adminModule[0]?.roles?.includes(userLevel[0]?.role)) {
|
||||
router.navigate({ to: "/" });
|
||||
}
|
||||
|
||||
if (isError) {
|
||||
return <div>{JSON.stringify(error)}</div>;
|
||||
}
|
||||
if (isError) {
|
||||
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);
|
||||
return (
|
||||
<LstCard className="m-2 flex place-content-center w-dvh">
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead>Name</TableHead>
|
||||
<TableHead>Server</TableHead>
|
||||
<TableHead>PlantToken</TableHead>
|
||||
<TableHead>IP Address</TableHead>
|
||||
<TableHead>Date Last updated</TableHead>
|
||||
<TableHead>Update Server</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((server: Servers) => {
|
||||
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">{server.sName}</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 />
|
||||
<RestartServer />
|
||||
</div>
|
||||
)}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
);
|
||||
})}
|
||||
</TableBody>
|
||||
)}
|
||||
</Table>
|
||||
</LstCard>
|
||||
);
|
||||
try {
|
||||
const result = await axios.post(
|
||||
`/api/server/update/localhost`,
|
||||
{ devDir: devDir[0].value, all: true },
|
||||
{
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
}
|
||||
);
|
||||
|
||||
if (result.data.success) {
|
||||
toast.success(result.data.message);
|
||||
}
|
||||
|
||||
if (!result.data.success) {
|
||||
toast.success(result.data.message);
|
||||
}
|
||||
} catch (error: any) {
|
||||
toast.error(
|
||||
`There was an error updating the server: ${error.data.message}`
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
//console.log(data);
|
||||
return (
|
||||
<LstCard className="m-2 flex place-content-center w-dvh">
|
||||
<div className="flex justify-end m-2">
|
||||
<Button
|
||||
onClick={upgrade}
|
||||
disabled={data?.some((d: any) => d.isUpgrading)}
|
||||
>
|
||||
Update All Servers
|
||||
</Button>
|
||||
</div>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead>Name</TableHead>
|
||||
<TableHead>Server</TableHead>
|
||||
<TableHead>PlantToken</TableHead>
|
||||
<TableHead>IP Address</TableHead>
|
||||
<TableHead>Date Last updated</TableHead>
|
||||
<TableHead>Update Server</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((server: Servers) => {
|
||||
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">
|
||||
{server.sName}
|
||||
</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 {Tooltip, TooltipContent, TooltipProvider, TooltipTrigger} from "@/components/ui/tooltip";
|
||||
import {Octagon} from "lucide-react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
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 (
|
||||
<div>
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button variant={"outline"} size={"icon"}>
|
||||
<Button
|
||||
variant="destructive"
|
||||
size={"icon"}
|
||||
onClick={() =>
|
||||
handleStopServer(plantData.plantToken)
|
||||
}
|
||||
>
|
||||
<Octagon />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
|
||||
@@ -1,23 +1,34 @@
|
||||
import {Button} from "@/components/ui/button";
|
||||
import {CircleFadingArrowUp} from "lucide-react";
|
||||
import {toast} from "sonner";
|
||||
import {Servers} from "./ServerPage";
|
||||
import {useQuery} from "@tanstack/react-query";
|
||||
import {getSettings} from "@/utils/querys/settings";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { CircleFadingArrowUp } from "lucide-react";
|
||||
import { toast } from "sonner";
|
||||
import { Servers } from "./ServerPage";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { getSettings } from "@/utils/querys/settings";
|
||||
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}) {
|
||||
const {data} = useQuery(getSettings(token ?? ""));
|
||||
export default function UpdateServer({
|
||||
server,
|
||||
token,
|
||||
}: {
|
||||
server: Servers;
|
||||
token: string;
|
||||
}) {
|
||||
const { data } = useQuery(getSettings(token ?? ""));
|
||||
const upgrade = async () => {
|
||||
let devDir = data.filter((n: any) => n.name === "devDir");
|
||||
toast.success("Server being upgraded in the background please wait.");
|
||||
try {
|
||||
const result = await axios.post(
|
||||
`/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);
|
||||
}
|
||||
} 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 (
|
||||
@@ -37,7 +50,12 @@ export default function UpdateServer({server, token}: {server: Servers; token: s
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<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 />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
|
||||
43
frontend/src/components/admin/user/UserPage.tsx
Normal file
43
frontend/src/components/admin/user/UserPage.tsx
Normal file
@@ -0,0 +1,43 @@
|
||||
import {
|
||||
Accordion,
|
||||
AccordionContent,
|
||||
AccordionItem,
|
||||
AccordionTrigger,
|
||||
} from "@/components/ui/accordion";
|
||||
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">
|
||||
<Accordion type="single" collapsible>
|
||||
{data.map((u: any) => {
|
||||
return (
|
||||
<AccordionItem key={u.user_id} value={u.user_id}>
|
||||
<AccordionTrigger>
|
||||
<span>{u.username}</span>
|
||||
</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
<div>
|
||||
<UserCard user={u} />
|
||||
</div>
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
);
|
||||
})}
|
||||
</Accordion>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
285
frontend/src/components/admin/user/components/UserCard.tsx
Normal file
285
frontend/src/components/admin/user/components/UserCard.tsx
Normal file
@@ -0,0 +1,285 @@
|
||||
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 UserRoles from "./UserRoles";
|
||||
import { CardHeader } from "@/components/ui/card";
|
||||
|
||||
export default function UserCard(data: any) {
|
||||
const token = localStorage.getItem("auth_token");
|
||||
const { refetch } = useQuery(getUsers());
|
||||
|
||||
//console.log(modules);
|
||||
//console.log(data.user);
|
||||
//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>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</form>
|
||||
</LstCard>
|
||||
<div>
|
||||
<Button onClick={form.handleSubmit}>Save</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="m-2">
|
||||
<LstCard>
|
||||
<CardHeader>User Module / Role Access</CardHeader>
|
||||
<UserRoles user={data.user} />
|
||||
</LstCard>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
16
frontend/src/components/admin/user/components/UserRoles.tsx
Normal file
16
frontend/src/components/admin/user/components/UserRoles.tsx
Normal file
@@ -0,0 +1,16 @@
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { useModuleStore } from "@/lib/store/useModuleStore";
|
||||
//import { Checkbox } from "@radix-ui/react-checkbox";
|
||||
|
||||
export default function UserRoles(user: any) {
|
||||
const { modules } = useModuleStore();
|
||||
console.log(user);
|
||||
return (
|
||||
<div>
|
||||
{modules?.map((m: any) => {
|
||||
console.log(m);
|
||||
return <Label>{m.name}</Label>;
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -3,7 +3,7 @@ import { LstCard } from "../extendedUI/LstCard";
|
||||
import { CardHeader } from "../ui/card";
|
||||
import { toast } from "sonner";
|
||||
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 { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { Label } from "../ui/label";
|
||||
@@ -12,153 +12,160 @@ import { Checkbox } from "../ui/checkbox";
|
||||
import { Button } from "../ui/button";
|
||||
|
||||
const FormSchema = z.object({
|
||||
username: z.string().min(1, "You must enter a valid username"),
|
||||
password: z.string().min(4, "You must enter a valid password"),
|
||||
rememberMe: z.boolean(),
|
||||
username: z.string().min(1, "You must enter a valid username"),
|
||||
password: z.string().min(4, "You must enter a valid password"),
|
||||
rememberMe: z.boolean(),
|
||||
});
|
||||
|
||||
const LoginForm = () => {
|
||||
const { setSession } = useSessionStore();
|
||||
const rememeberMe = localStorage.getItem("rememberMe") === "true";
|
||||
const username = localStorage.getItem("username") || "";
|
||||
const router = useRouter();
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
control,
|
||||
formState: { errors },
|
||||
} = useForm<z.infer<typeof FormSchema>>({
|
||||
resolver: zodResolver(FormSchema),
|
||||
defaultValues: {
|
||||
username: username || "",
|
||||
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",
|
||||
const { setSession } = useSessionStore();
|
||||
const rememeberMe = localStorage.getItem("rememberMe") === "true";
|
||||
const username = localStorage.getItem("username") || "";
|
||||
const router = useRouter();
|
||||
const search = useSearch({ from: "/login" });
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
control,
|
||||
formState: { errors },
|
||||
} = useForm<z.infer<typeof FormSchema>>({
|
||||
resolver: zodResolver(FormSchema),
|
||||
defaultValues: {
|
||||
username: username || "",
|
||||
password: "",
|
||||
rememberMe: rememeberMe,
|
||||
},
|
||||
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
|
||||
// localStorage.setItem("auth_token", data.data.token);
|
||||
if (data.success) {
|
||||
const prod = btoa(`${value.username.toLowerCase()}:${value.password}`);
|
||||
const prodUser = { ...data.user, prod: prod };
|
||||
// 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");
|
||||
}
|
||||
|
||||
setSession(prodUser, data.token);
|
||||
toast.success(`You are logged in as ${data.user.username}`);
|
||||
router.navigate({ to: "/" });
|
||||
}
|
||||
try {
|
||||
const response = await fetch("/api/auth/login", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
username: value.username,
|
||||
password: value.password,
|
||||
}),
|
||||
});
|
||||
|
||||
if (!data.success) {
|
||||
toast.error(`${data.message}`);
|
||||
}
|
||||
const data = await response.json();
|
||||
|
||||
//console.log(data);
|
||||
} catch (err) {
|
||||
toast.error("Invalid credentials");
|
||||
}
|
||||
};
|
||||
// Store token in localStorage
|
||||
// localStorage.setItem("auth_token", data.data.token);
|
||||
if (data.success) {
|
||||
const prod = btoa(
|
||||
`${value.username.toLowerCase()}:${value.password}`
|
||||
);
|
||||
const prodUser = { ...data.user, prod: prod };
|
||||
|
||||
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>
|
||||
setSession(prodUser, data.token);
|
||||
toast.success(`You are logged in as ${data.user.username}`);
|
||||
|
||||
<div className="flex justify-end">
|
||||
<Button type="submit">Submit</Button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</LstCard>
|
||||
</div>
|
||||
);
|
||||
console.log(search.redirect ? search.redirect : "oops");
|
||||
router.history.push(search.redirect ? search.redirect : "/");
|
||||
}
|
||||
|
||||
if (!data.success) {
|
||||
toast.error(`${data.message}`);
|
||||
}
|
||||
|
||||
//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;
|
||||
|
||||
@@ -1,4 +1,14 @@
|
||||
import {Atom, Logs, Minus, Plus, Server, Settings, ShieldCheck, Users, Webhook} from "lucide-react";
|
||||
import {
|
||||
Atom,
|
||||
Logs,
|
||||
Minus,
|
||||
Plus,
|
||||
Server,
|
||||
Settings,
|
||||
ShieldCheck,
|
||||
Users,
|
||||
Webhook,
|
||||
} from "lucide-react";
|
||||
import {
|
||||
SidebarGroup,
|
||||
SidebarGroupContent,
|
||||
@@ -10,7 +20,11 @@ import {
|
||||
SidebarMenuSubButton,
|
||||
SidebarMenuSubItem,
|
||||
} from "../../ui/sidebar";
|
||||
import {Collapsible, CollapsibleContent, CollapsibleTrigger} from "../../ui/collapsible";
|
||||
import {
|
||||
Collapsible,
|
||||
CollapsibleContent,
|
||||
CollapsibleTrigger,
|
||||
} from "../../ui/collapsible";
|
||||
|
||||
const items = [
|
||||
{
|
||||
@@ -53,9 +67,9 @@ const data = {
|
||||
},
|
||||
{
|
||||
title: "Users",
|
||||
url: "#",
|
||||
url: "/users",
|
||||
icon: Users,
|
||||
isActive: false,
|
||||
isActive: true,
|
||||
},
|
||||
{
|
||||
title: "UCD",
|
||||
@@ -82,7 +96,11 @@ export function AdminSideBar() {
|
||||
<SidebarGroupContent>
|
||||
<SidebarMenu>
|
||||
{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>
|
||||
<CollapsibleTrigger asChild>
|
||||
<SidebarMenuButton>
|
||||
@@ -96,15 +114,25 @@ export function AdminSideBar() {
|
||||
<CollapsibleContent>
|
||||
<SidebarMenuSub>
|
||||
{item.items.map((item) => (
|
||||
<SidebarMenuSubItem key={item.title}>
|
||||
<SidebarMenuSubItem
|
||||
key={item.title}
|
||||
>
|
||||
{item.isActive && (
|
||||
<SidebarMenuSubButton asChild>
|
||||
<SidebarMenuSubButton
|
||||
asChild
|
||||
>
|
||||
<a
|
||||
href={item.url}
|
||||
target={item.newWindow ? "_blank" : "_self"}
|
||||
target={
|
||||
item.newWindow
|
||||
? "_blank"
|
||||
: "_self"
|
||||
}
|
||||
>
|
||||
<item.icon />
|
||||
<span>{item.title}</span>
|
||||
<span>
|
||||
{item.title}
|
||||
</span>
|
||||
</a>
|
||||
</SidebarMenuSubButton>
|
||||
)}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {Cylinder, Package, Truck} from "lucide-react";
|
||||
//import { Cylinder, Package, Truck } from "lucide-react";
|
||||
import {
|
||||
SidebarGroup,
|
||||
SidebarGroupContent,
|
||||
@@ -7,80 +7,107 @@ import {
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
} from "../../ui/sidebar";
|
||||
import {hasPageAccess} from "@/utils/userAccess";
|
||||
import {User} from "@/types/users";
|
||||
import { hasPageAccess } from "@/utils/userAccess";
|
||||
import { User } from "@/types/users";
|
||||
import { useSubModuleStore } from "@/lib/store/useSubModuleStore";
|
||||
// this will need to be moved to a links section the db to make it more easy to remove and add
|
||||
const items = [
|
||||
{
|
||||
title: "Silo Adjustments",
|
||||
url: "#",
|
||||
icon: Cylinder,
|
||||
role: ["admin", "systemAdmin"],
|
||||
module: "logistics",
|
||||
active: true,
|
||||
},
|
||||
{
|
||||
title: "Bulk orders",
|
||||
url: "#",
|
||||
icon: Truck,
|
||||
role: ["systemAdmin"],
|
||||
module: "logistics",
|
||||
active: true,
|
||||
},
|
||||
{
|
||||
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,
|
||||
},
|
||||
];
|
||||
// const items = [
|
||||
// {
|
||||
// title: "Silo Adjustments",
|
||||
// url: "#",
|
||||
// icon: Cylinder,
|
||||
// role: ["admin", "systemAdmin"],
|
||||
// module: "logistics",
|
||||
// active: true,
|
||||
// },
|
||||
// {
|
||||
// name: "Bulk orders",
|
||||
// moduleName: "logistics",
|
||||
// description: "",
|
||||
// link: "#",
|
||||
// icon: Truck,
|
||||
// role: ["systemAdmin"],
|
||||
// active: true,
|
||||
// subSubModule: [],
|
||||
// },
|
||||
// {
|
||||
// name: "Forecast",
|
||||
// moduleName: "logistics",
|
||||
// description: "",
|
||||
// link: "#",
|
||||
// icon: Truck,
|
||||
// role: ["systemAdmin"],
|
||||
// active: true,
|
||||
// subSubModule: [],
|
||||
// },
|
||||
// {
|
||||
// name: "Ocme cycle counts",
|
||||
// moduleName: "logistics",
|
||||
// description: "",
|
||||
// link: "#",
|
||||
// icon: Package,
|
||||
// role: ["technician", "supervisor", "manager", "admin", "systemAdmin"],
|
||||
// active: false,
|
||||
// subSubModule: [],
|
||||
// },
|
||||
// {
|
||||
// name: "Material Helper",
|
||||
// moduleName: "logistics",
|
||||
// description: "",
|
||||
// link: "/materialHelper/consumption",
|
||||
// icon: Package,
|
||||
// role: ["technician", "supervisor", "manager", "admin", "systemAdmin"],
|
||||
// active: true,
|
||||
// subSubModule: [],
|
||||
// },
|
||||
// {
|
||||
// name: "Ocme Cyclecount",
|
||||
// moduleName: "logistics",
|
||||
// description: "",
|
||||
// link: "/cyclecount",
|
||||
// icon: Package,
|
||||
// role: ["technician", "supervisor", "manager", "admin", "systemAdmin"],
|
||||
// active: true,
|
||||
// subSubModule: [],
|
||||
// },
|
||||
// ];
|
||||
|
||||
export function LogisticsSideBar({user, moduleID}: {user: User | null; moduleID: string}) {
|
||||
export function LogisticsSideBar({
|
||||
user,
|
||||
moduleID,
|
||||
}: {
|
||||
user: User | null;
|
||||
moduleID: string;
|
||||
}) {
|
||||
const { subModules } = useSubModuleStore();
|
||||
|
||||
const items = subModules.filter((m) => m.moduleName === "logistics");
|
||||
//console.log(items);
|
||||
return (
|
||||
<SidebarGroup>
|
||||
<SidebarGroupLabel>Logistics</SidebarGroupLabel>
|
||||
<SidebarGroupContent>
|
||||
<SidebarMenu>
|
||||
{items.map((item) => (
|
||||
<SidebarMenuItem key={item.title}>
|
||||
<>
|
||||
{hasPageAccess(user, item.role, moduleID) && item.active && (
|
||||
<SidebarMenuButton asChild>
|
||||
<a href={item.url}>
|
||||
<item.icon />
|
||||
<span>{item.title}</span>
|
||||
</a>
|
||||
</SidebarMenuButton>
|
||||
)}
|
||||
</>
|
||||
</SidebarMenuItem>
|
||||
))}
|
||||
{items.map((item) => {
|
||||
return (
|
||||
<SidebarMenuItem key={item.submodule_id}>
|
||||
<>
|
||||
{hasPageAccess(
|
||||
user,
|
||||
item.roles,
|
||||
moduleID
|
||||
) &&
|
||||
item.active && (
|
||||
<SidebarMenuButton asChild>
|
||||
<a href={item.link}>
|
||||
<span>{item.name}</span>
|
||||
</a>
|
||||
</SidebarMenuButton>
|
||||
)}
|
||||
</>
|
||||
</SidebarMenuItem>
|
||||
);
|
||||
})}
|
||||
</SidebarMenu>
|
||||
</SidebarGroupContent>
|
||||
</SidebarGroup>
|
||||
|
||||
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>
|
||||
);
|
||||
}
|
||||
181
frontend/src/components/logistics/siloAdjustments/SiloCard.tsx
Normal file
181
frontend/src/components/logistics/siloAdjustments/SiloCard.tsx
Normal file
@@ -0,0 +1,181 @@
|
||||
import { LstCard } from "@/components/extendedUI/LstCard";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { CardHeader } from "@/components/ui/card";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "@/components/ui/tooltip";
|
||||
import { getStockSilo } from "@/utils/querys/logistics/siloAdjustments/getStockSilo";
|
||||
import { useForm } from "@tanstack/react-form";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import axios from "axios";
|
||||
import { format } from "date-fns";
|
||||
import { CircleAlert } from "lucide-react";
|
||||
import { useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
|
||||
export default function SiloCard(data: any) {
|
||||
const token = localStorage.getItem("auth_token");
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
const { refetch } = useQuery(getStockSilo());
|
||||
const silo = data.silo;
|
||||
|
||||
const form = useForm({
|
||||
defaultValues: {
|
||||
newLevel: "",
|
||||
},
|
||||
onSubmit: async ({ value }) => {
|
||||
setSubmitting(true);
|
||||
const dataToSubmit = {
|
||||
quantity: parseFloat(value.newLevel),
|
||||
warehouseId: silo.WarehouseID,
|
||||
laneId: silo.LocationID,
|
||||
};
|
||||
|
||||
try {
|
||||
const res = await axios.post(
|
||||
"/api/logistics/createsiloadjustment",
|
||||
dataToSubmit,
|
||||
{ headers: { Authorization: `Bearer ${token}` } }
|
||||
);
|
||||
console.log(res.data);
|
||||
|
||||
if (res.data.success) {
|
||||
toast.success(res.data.message);
|
||||
refetch();
|
||||
form.reset();
|
||||
}
|
||||
if (!res.data.success && res.data.data?.status === 400) {
|
||||
if (res.data.data.status === 400) {
|
||||
toast.error(res.data.data.data.errors[0].message);
|
||||
}
|
||||
} else if (!res.data.success) {
|
||||
toast.error(res.data.message);
|
||||
}
|
||||
setSubmitting(false);
|
||||
} catch (error: any) {
|
||||
//console.log(error);
|
||||
if (error.status === 401) {
|
||||
toast.error(error.response.statusText);
|
||||
setSubmitting(false);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
return (
|
||||
<LstCard>
|
||||
<div className="flex flex-row">
|
||||
<LstCard className="grow m-1 max-w-[400px]">
|
||||
<CardHeader>{silo.Description}</CardHeader>
|
||||
<div className="m-1">
|
||||
<hr className="m-2" />
|
||||
<span>Current Stock: </span>
|
||||
{silo.Stock_Total}
|
||||
<hr className="m-2" />
|
||||
<span>Last date adjusted </span>
|
||||
{format(silo.LastAdjustment, "M/dd/yyyy")}
|
||||
<hr className="m-2" />
|
||||
</div>
|
||||
<div>
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}}
|
||||
>
|
||||
<form.Field
|
||||
name="newLevel"
|
||||
validators={{
|
||||
// We can choose between form-wide and field-specific validators
|
||||
onChange: ({ value }) =>
|
||||
value.length > 1
|
||||
? undefined
|
||||
: "You must enter a value greate than 1",
|
||||
}}
|
||||
children={(field) => {
|
||||
return (
|
||||
<div className="m-2 min-w-48 max-w-96 p-2">
|
||||
<div className="flex flex-row">
|
||||
<Label htmlFor="newLevel">
|
||||
New level
|
||||
</Label>
|
||||
<div>
|
||||
<Disclaimer />
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-row">
|
||||
<Input
|
||||
name={field.name}
|
||||
value={field.state.value}
|
||||
onBlur={field.handleBlur}
|
||||
type="decimal"
|
||||
onChange={(e) =>
|
||||
field.handleChange(
|
||||
e.target.value
|
||||
)
|
||||
}
|
||||
/>
|
||||
<Button
|
||||
className="ml-1"
|
||||
type="submit"
|
||||
onClick={form.handleSubmit}
|
||||
disabled={submitting}
|
||||
>
|
||||
{submitting ? (
|
||||
<span className="w-24">
|
||||
Submitting...
|
||||
</span>
|
||||
) : (
|
||||
<span className="w-24">
|
||||
Submit
|
||||
</span>
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{field.state.meta.errors.length ? (
|
||||
<em>
|
||||
{field.state.meta.errors.join(
|
||||
","
|
||||
)}
|
||||
</em>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</form>
|
||||
</div>
|
||||
</LstCard>
|
||||
<div className="grow max-w-[400px]">
|
||||
<LstCard className="m-1 ">charts go here</LstCard>
|
||||
<LstCard className="m-1">extra options here</LstCard>
|
||||
</div>
|
||||
</div>
|
||||
</LstCard>
|
||||
);
|
||||
}
|
||||
|
||||
const Disclaimer = () => {
|
||||
return (
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<CircleAlert className="ml-1 w-[14px]" />
|
||||
</TooltipTrigger>
|
||||
<TooltipContent className="max-w-48">
|
||||
<p className="text-pretty">
|
||||
If you have had this page open for a period of time
|
||||
before submitting your data, there is a chance that the
|
||||
stock levels will be different from the ones you see
|
||||
above
|
||||
</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,30 @@
|
||||
import { getStockSilo } from "@/utils/querys/logistics/siloAdjustments/getStockSilo";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import SiloCard from "./SiloCard";
|
||||
|
||||
export default function SiloPage() {
|
||||
const { data, isError, error, isLoading } = useQuery(getStockSilo());
|
||||
|
||||
if (isLoading) return;
|
||||
|
||||
if (isError) return;
|
||||
|
||||
if (error)
|
||||
return (
|
||||
<div>
|
||||
{" "}
|
||||
There was an error getting the silos please notify your admin if
|
||||
this continues to be an issue
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="flex flex-wrap">
|
||||
{data?.map((s: any) => (
|
||||
<div key={s.LocationID} className="grow m-2 max-w-[800px]">
|
||||
<SiloCard silo={s} />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
131
frontend/src/components/ocme/WrapperCard.tsx
Normal file
131
frontend/src/components/ocme/WrapperCard.tsx
Normal file
@@ -0,0 +1,131 @@
|
||||
import axios from "axios";
|
||||
import { LstCard } from "../extendedUI/LstCard";
|
||||
import { Button } from "../ui/button";
|
||||
import { ScrollArea } from "../ui/scroll-area";
|
||||
import { Skeleton } from "../ui/skeleton";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "../ui/table";
|
||||
import { toast } from "sonner";
|
||||
|
||||
const currentPallets = [
|
||||
{ key: "line", label: "Line" },
|
||||
{ key: "runningNr", label: "Running #" },
|
||||
{ key: "upd_date", label: "Date Scanned" },
|
||||
{ key: "waitingfor", label: "Waiting For" },
|
||||
{ key: "clear", label: "Clear" },
|
||||
];
|
||||
|
||||
const currentTags = [
|
||||
{ key: "line", label: "Line" },
|
||||
{ key: "printerName", label: "Printer" },
|
||||
{ key: "runningNr", label: "Running #" },
|
||||
{ key: "upd_date", label: "Label date" },
|
||||
{ key: "status", label: "Label Status" },
|
||||
];
|
||||
export default function WrapperManualTrigger() {
|
||||
const cameraTrigger = async () => {
|
||||
try {
|
||||
const res = await axios.get("/ocme/api/v1/manualCameraTrigger");
|
||||
|
||||
if (res.data.success) {
|
||||
toast.success(res.data.message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!res.data.success) {
|
||||
toast.error(res.data.message);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
//stoast.success(error.data.message);
|
||||
}
|
||||
};
|
||||
return (
|
||||
<LstCard className="m-2 p-2">
|
||||
<ScrollArea className="max-h-[200px]">
|
||||
<span>Wrapper Pallet Info</span>
|
||||
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
{currentPallets.map((l) => (
|
||||
<TableHead key={l.key}>{l.label}</TableHead>
|
||||
))}
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{Array(3)
|
||||
.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>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</ScrollArea>
|
||||
<ScrollArea className="max-h-[200px]">
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
{currentTags.map((l) => (
|
||||
<TableHead key={l.key}>{l.label}</TableHead>
|
||||
))}
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{Array(3)
|
||||
.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>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</ScrollArea>
|
||||
<div>
|
||||
<hr />
|
||||
<p className="text-center mb-3">Manual Triggers</p>
|
||||
<div className="flex flex-row justify-between">
|
||||
<Button onClick={cameraTrigger}>Camera</Button>
|
||||
<Button>Rfid</Button>
|
||||
</div>
|
||||
</div>
|
||||
</LstCard>
|
||||
);
|
||||
}
|
||||
@@ -1,14 +1,27 @@
|
||||
import {toast} from "sonner";
|
||||
import {LstCard} from "../extendedUI/LstCard";
|
||||
import {Button} from "../ui/button";
|
||||
import {Input} from "../ui/input";
|
||||
import {Table, TableBody, TableCell, TableHead, TableHeader, TableRow} from "../ui/table";
|
||||
import {Skeleton} from "../ui/skeleton";
|
||||
import { toast } from "sonner";
|
||||
import { LstCard } from "../extendedUI/LstCard";
|
||||
import { Button } from "../ui/button";
|
||||
import { Input } from "../ui/input";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "../ui/table";
|
||||
import { Skeleton } from "../ui/skeleton";
|
||||
//import CycleCountLog from "./CycleCountLog";
|
||||
import {Select, SelectContent, SelectItem, SelectTrigger, SelectValue} from "../ui/select";
|
||||
import {Controller, useForm} from "react-hook-form";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "../ui/select";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import axios from "axios";
|
||||
import {useState} from "react";
|
||||
import { useState } from "react";
|
||||
|
||||
export default function OcmeCycleCount() {
|
||||
const token = localStorage.getItem("auth_token");
|
||||
@@ -18,7 +31,7 @@ export default function OcmeCycleCount() {
|
||||
register,
|
||||
handleSubmit,
|
||||
//watch,
|
||||
formState: {errors},
|
||||
formState: { errors },
|
||||
reset,
|
||||
control,
|
||||
} = useForm();
|
||||
@@ -28,13 +41,22 @@ export default function OcmeCycleCount() {
|
||||
setCounting(true);
|
||||
toast.success(`Cycle count started`);
|
||||
try {
|
||||
const res = await axios.post("/ocme/api/v1/cyclecount", data, {
|
||||
headers: {Authorization: `Bearer ${token}`},
|
||||
const res = await axios.post("/ocme/api/v1/cycleCount", data, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
toast.success(res.data.message);
|
||||
setData(res.data.data);
|
||||
setCounting(false);
|
||||
reset();
|
||||
|
||||
if (res.data.success) {
|
||||
toast.success(res.data.message);
|
||||
setData(res.data.data);
|
||||
setCounting(false);
|
||||
reset();
|
||||
}
|
||||
|
||||
if (res.data.success) {
|
||||
toast.success(res.data.message);
|
||||
|
||||
setCounting(false);
|
||||
}
|
||||
} catch (error) {
|
||||
toast.error("There was an error cycle counting");
|
||||
setCounting(false);
|
||||
@@ -45,20 +67,25 @@ export default function OcmeCycleCount() {
|
||||
<div className="flex flex-row w-screen">
|
||||
<div className="m-2 w-5/6">
|
||||
<LstCard>
|
||||
<p className="ml-2">Please enter the name or laneID you want to cycle count.</p>
|
||||
<p className="ml-2">
|
||||
Please enter the name or laneID you want to cycle count.
|
||||
</p>
|
||||
<div>
|
||||
<form onSubmit={handleSubmit(onSubmit)}>
|
||||
<div className="flex justify-between">
|
||||
<div className="m-2 flex flex-row">
|
||||
<Input
|
||||
placeholder="enter lane: L064"
|
||||
className={errors.lane ? "border-red-500" : ""}
|
||||
className={
|
||||
errors.lane ? "border-red-500" : ""
|
||||
}
|
||||
aria-invalid={!!errors.lane}
|
||||
{...register("lane", {
|
||||
required: true,
|
||||
minLength: {
|
||||
value: 3,
|
||||
message: "The lane is too short!",
|
||||
message:
|
||||
"The lane is too short!",
|
||||
},
|
||||
})}
|
||||
/>
|
||||
@@ -68,25 +95,39 @@ export default function OcmeCycleCount() {
|
||||
name="laneType"
|
||||
defaultValue={""}
|
||||
render={({
|
||||
field: {onChange},
|
||||
field: { onChange },
|
||||
fieldState: {},
|
||||
//formState,
|
||||
}) => (
|
||||
<Select onValueChange={onChange}>
|
||||
<Select
|
||||
onValueChange={onChange}
|
||||
>
|
||||
<SelectTrigger className="w-[180px]">
|
||||
<SelectValue placeholder="Select name or id" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="name">Name</SelectItem>
|
||||
<SelectItem value="laneId">Lane ID</SelectItem>
|
||||
<SelectItem value="name">
|
||||
Name
|
||||
</SelectItem>
|
||||
<SelectItem value="laneId">
|
||||
Lane ID
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<Button className="m-2" type="submit" disabled={counting}>
|
||||
{counting ? <span>Counting...</span> : <span>CycleCount</span>}
|
||||
<Button
|
||||
className="m-2"
|
||||
type="submit"
|
||||
disabled={counting}
|
||||
>
|
||||
{counting ? (
|
||||
<span>Counting...</span>
|
||||
) : (
|
||||
<span>CycleCount</span>
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
@@ -105,44 +146,46 @@ export default function OcmeCycleCount() {
|
||||
<TableHead>Result</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
{data.length === 0 ? (
|
||||
{data?.length === 0 ? (
|
||||
<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>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4" />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
.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>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4" />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
) : (
|
||||
<>
|
||||
{data.map((i: any) => {
|
||||
let classname = ``;
|
||||
if (i.info === "Quality Check Required") {
|
||||
if (
|
||||
i.info === "Quality Check Required"
|
||||
) {
|
||||
classname = `bg-red-500`;
|
||||
}
|
||||
if (i.info === "Sent to Inv") {
|
||||
@@ -150,24 +193,46 @@ export default function OcmeCycleCount() {
|
||||
}
|
||||
return (
|
||||
<TableRow key={i.runningNumber}>
|
||||
<TableCell className={`font-medium ${classname}`}>
|
||||
<TableCell
|
||||
className={`font-medium ${classname}`}
|
||||
>
|
||||
{i.alpla_laneID}
|
||||
</TableCell>
|
||||
<TableCell className={`font-medium ${classname}`}>
|
||||
<TableCell
|
||||
className={`font-medium ${classname}`}
|
||||
>
|
||||
{i.alpla_laneDescription}
|
||||
</TableCell>
|
||||
<TableCell className={`font-medium ${classname}`}>
|
||||
<TableCell
|
||||
className={`font-medium ${classname}`}
|
||||
>
|
||||
{i.Article}
|
||||
</TableCell>
|
||||
<TableCell className={`font-medium ${classname}`}>
|
||||
<TableCell
|
||||
className={`font-medium ${classname}`}
|
||||
>
|
||||
{i.alpla_laneDescription}
|
||||
</TableCell>
|
||||
<TableCell className={`font-medium ${classname}`}>
|
||||
<TableCell
|
||||
className={`font-medium ${classname}`}
|
||||
>
|
||||
{i.runningNumber}
|
||||
</TableCell>
|
||||
<TableCell className={`font-medium ${classname}`}>{i.ocme}</TableCell>
|
||||
<TableCell className={`font-medium ${classname}`}>{i.stock}</TableCell>
|
||||
<TableCell className={`font-medium ${classname}`}>{i.info}</TableCell>
|
||||
<TableCell
|
||||
className={`font-medium ${classname}`}
|
||||
>
|
||||
{i.ocme}
|
||||
</TableCell>
|
||||
<TableCell
|
||||
className={`font-medium ${classname}`}
|
||||
>
|
||||
{i.stock}
|
||||
</TableCell>
|
||||
<TableCell
|
||||
className={`font-medium ${classname}`}
|
||||
>
|
||||
{i.info}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
);
|
||||
})}
|
||||
|
||||
@@ -1,23 +1,31 @@
|
||||
import {LstCard} from "@/components/extendedUI/LstCard";
|
||||
import { LstCard } from "@/components/extendedUI/LstCard";
|
||||
|
||||
import {Skeleton} from "@/components/ui/skeleton";
|
||||
import {Table, TableBody, TableCell, TableHead, TableHeader, TableRow} from "@/components/ui/table";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableFooter,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/components/ui/table";
|
||||
// import {useSessionStore} from "@/lib/store/sessionStore";
|
||||
// import {useSettingStore} from "@/lib/store/useSettings";
|
||||
import {useQuery} from "@tanstack/react-query";
|
||||
import {getlabels} from "@/utils/querys/production/labels";
|
||||
import {format} from "date-fns";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { getlabels } from "@/utils/querys/production/labels";
|
||||
import { format } from "date-fns";
|
||||
|
||||
const labelLogs = [
|
||||
{key: "line", label: "Line"},
|
||||
{key: "printerName", label: "Printer"},
|
||||
{key: "runningNr", label: "Running #"},
|
||||
{key: "upd_date", label: "Label date"},
|
||||
{key: "status", label: "Label Status"},
|
||||
{ key: "line", label: "Line" },
|
||||
{ key: "printerName", label: "Printer" },
|
||||
{ key: "runningNr", label: "Running #" },
|
||||
{ key: "upd_date", label: "Label date" },
|
||||
{ key: "status", label: "Label Status" },
|
||||
//{key: "reprint", label: "Reprint"}, // removing the reprint button for now until repritning is working as intended
|
||||
];
|
||||
export default function LabelLog() {
|
||||
const {data, isError, isLoading} = useQuery(getlabels("4"));
|
||||
const { data, isError, isLoading } = useQuery(getlabels("4"));
|
||||
//const {user} = useSessionStore();
|
||||
//const {settings} = useSettingStore();
|
||||
//const server = settings.filter((n) => n.name === "server")[0]?.value || "";
|
||||
@@ -40,33 +48,33 @@ export default function LabelLog() {
|
||||
|
||||
<TableBody>
|
||||
{Array(7)
|
||||
.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>
|
||||
</TableRow>
|
||||
))}
|
||||
.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>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</LstCard>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const labelData = data ? data : [];
|
||||
return (
|
||||
<LstCard className="m-2 p-2 min-h-2/5">
|
||||
<p className="text-center">Labels for the last 2 hours</p>
|
||||
@@ -82,43 +90,64 @@ export default function LabelLog() {
|
||||
<>
|
||||
<TableBody>
|
||||
{Array(7)
|
||||
.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>
|
||||
</TableRow>
|
||||
))}
|
||||
.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>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</>
|
||||
) : (
|
||||
<TableBody>
|
||||
{data?.map((label: any) => (
|
||||
{labelData.map((label: any) => (
|
||||
<TableRow key={label.runningNr}>
|
||||
<TableCell className="font-medium">{label.line}</TableCell>
|
||||
<TableCell className="font-medium">{label.printerName}</TableCell>
|
||||
<TableCell className="font-medium">{label.runningNr}</TableCell>
|
||||
<TableCell className="font-medium">
|
||||
{format(label.upd_date, "M/d/yyyy hh:mm")}
|
||||
{label.line}
|
||||
</TableCell>
|
||||
<TableCell className="font-medium">
|
||||
{label.printerName}
|
||||
</TableCell>
|
||||
<TableCell className="font-medium">
|
||||
{label.runningNr}
|
||||
</TableCell>
|
||||
<TableCell className="font-medium">
|
||||
{format(
|
||||
label?.upd_date.replace("Z", ""),
|
||||
"M/d/yyyy hh:mm"
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell className="font-medium">
|
||||
{label.status}
|
||||
</TableCell>
|
||||
<TableCell className="font-medium">{label.status}</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
)}
|
||||
|
||||
<TableFooter>
|
||||
{labelData.length === 0 && (
|
||||
<div>
|
||||
<h2 className="text-center text-2xl">
|
||||
No labels have been printed in the last 2 hours
|
||||
</h2>
|
||||
</div>
|
||||
)}
|
||||
</TableFooter>
|
||||
</Table>
|
||||
</LstCard>
|
||||
);
|
||||
|
||||
@@ -1,14 +1,22 @@
|
||||
import {LstCard} from "@/components/extendedUI/LstCard";
|
||||
import { LstCard } from "@/components/extendedUI/LstCard";
|
||||
|
||||
import {Skeleton} from "@/components/ui/skeleton";
|
||||
import {Table, TableBody, TableCell, TableHead, TableHeader, TableRow} from "@/components/ui/table";
|
||||
import {useSessionStore} from "@/lib/store/sessionStore";
|
||||
import {useSettingStore} from "@/lib/store/useSettings";
|
||||
import {LotType} from "@/types/lots";
|
||||
import {getlots} from "@/utils/querys/production/lots";
|
||||
import {useQuery} from "@tanstack/react-query";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/components/ui/table";
|
||||
import { useSessionStore } from "@/lib/store/sessionStore";
|
||||
import { useSettingStore } from "@/lib/store/useSettings";
|
||||
import { LotType } from "@/types/lots";
|
||||
import { getlots } from "@/utils/querys/production/lots";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import ManualPrint from "./ManualPrinting/ManualPrint";
|
||||
import ManualPrintForm from "./ManualPrinting/ManualPrintForm";
|
||||
import { ScrollArea } from "@/components/ui/scroll-area";
|
||||
|
||||
let lotColumns = [
|
||||
{
|
||||
@@ -24,7 +32,7 @@ let lotColumns = [
|
||||
label: "AvDescription",
|
||||
},
|
||||
{
|
||||
key: "LOT",
|
||||
key: "lot",
|
||||
label: "LotNumber",
|
||||
},
|
||||
{
|
||||
@@ -57,14 +65,13 @@ let lotColumns = [
|
||||
// },
|
||||
];
|
||||
export default function Lots() {
|
||||
const {data, isError, isLoading} = useQuery(getlots());
|
||||
const {user} = useSessionStore();
|
||||
const {settings} = useSettingStore();
|
||||
const { data, isError, isLoading } = useQuery(getlots());
|
||||
const { user } = useSessionStore();
|
||||
const { settings } = useSettingStore();
|
||||
const server = settings.filter((n) => n.name === "server")[0]?.value || "";
|
||||
|
||||
console.log(server);
|
||||
|
||||
const roles = ["admin", "manager", "operator"];
|
||||
const lotdata = data ? data : [];
|
||||
|
||||
if (user && roles.includes(user.role)) {
|
||||
//width = 1280;
|
||||
@@ -83,140 +90,168 @@ export default function Lots() {
|
||||
if (isError) {
|
||||
return (
|
||||
<div className="m-2 p-2 min-h-2/5">
|
||||
<LstCard>
|
||||
<p className="text-center">Current Assigned lots</p>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
{lotColumns.map((l) => (
|
||||
<TableHead key={l.key}>{l.label}</TableHead>
|
||||
))}
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
|
||||
<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>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4" />
|
||||
</TableCell>
|
||||
<ScrollArea className="max-h-1/2 rounded-md border p-4">
|
||||
<LstCard>
|
||||
<p className="text-center">Current Assigned lots</p>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
{lotColumns.map((l) => (
|
||||
<TableHead key={l.key}>
|
||||
{l.label}
|
||||
</TableHead>
|
||||
))}
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</LstCard>
|
||||
</TableHeader>
|
||||
|
||||
<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>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4" />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</LstCard>
|
||||
</ScrollArea>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<LstCard className="m-2 p-2 min-h-2/5">
|
||||
<p className="text-center">Current Assigned lots</p>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
{lotColumns.map((l) => (
|
||||
<TableHead key={l.key}>{l.label}</TableHead>
|
||||
))}
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
{isLoading ? (
|
||||
<>
|
||||
<ScrollArea className="h-[400px]">
|
||||
<p className="text-center">Current Assigned lots</p>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
{lotColumns.map((l) => (
|
||||
<TableHead key={l.key}>{l.label}</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>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4" />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</>
|
||||
) : (
|
||||
<TableBody>
|
||||
{Array(10)
|
||||
.fill(0)
|
||||
.map((_, i) => (
|
||||
<TableRow key={i}>
|
||||
{lotdata.map((lot: LotType) => (
|
||||
<TableRow key={lot.LabelOnlineID}>
|
||||
<TableCell className="font-medium">
|
||||
<Skeleton className="h-4" />
|
||||
{lot.MachineLocation}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4" />
|
||||
<TableCell className="font-medium">
|
||||
{lot.AV}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4" />
|
||||
<TableCell className="font-medium">
|
||||
{lot.Alias}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4" />
|
||||
<TableCell
|
||||
className={`font-medium ${lot.ProlinkLot != lot.lot ? "text-red-500" : ""}`}
|
||||
>
|
||||
{lot.lot}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4" />
|
||||
<TableCell
|
||||
className={`font-medium ${lot.ProlinkLot != lot.lot ? "text-red-500" : ""}`}
|
||||
>
|
||||
{lot.ProlinkLot}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4" />
|
||||
<TableCell className="font-medium">
|
||||
{lot.PlannedQTY}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4" />
|
||||
<TableCell className="font-medium">
|
||||
{lot.Produced}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4" />
|
||||
<TableCell className="font-medium">
|
||||
{lot.Remaining}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4" />
|
||||
<TableCell className="font-medium">
|
||||
{lot.overPrinting}
|
||||
</TableCell>
|
||||
{user && roles.includes(user.role) && (
|
||||
<>
|
||||
{server === "usday1vms006" ||
|
||||
server === "localhost" ? (
|
||||
<>
|
||||
<TableCell className="flex justify-center">
|
||||
<ManualPrintForm />
|
||||
</TableCell>
|
||||
</>
|
||||
) : (
|
||||
<TableCell className="flex justify-center">
|
||||
<ManualPrint lot={lot} />
|
||||
</TableCell>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</>
|
||||
) : (
|
||||
<TableBody>
|
||||
{data?.map((lot: LotType) => (
|
||||
<TableRow key={lot.LabelOnlineID}>
|
||||
<TableCell className="font-medium">{lot.MachineLocation}</TableCell>
|
||||
<TableCell className="font-medium">{lot.AV}</TableCell>
|
||||
<TableCell className="font-medium">{lot.Alias}</TableCell>
|
||||
<TableCell className="font-medium">{lot.LOT}</TableCell>
|
||||
<TableCell className="font-medium">{lot.ProlinkLot}</TableCell>
|
||||
<TableCell className="font-medium">{lot.PlannedQTY}</TableCell>
|
||||
<TableCell className="font-medium">{lot.Produced}</TableCell>
|
||||
<TableCell className="font-medium">{lot.Remaining}</TableCell>
|
||||
<TableCell className="font-medium">{lot.overPrinting}</TableCell>
|
||||
{user && roles.includes(user.role) && (
|
||||
<>
|
||||
{server === "usday1vms006" || server === "localhost" ? (
|
||||
<>
|
||||
<TableCell className="flex justify-center">
|
||||
<ManualPrintForm lot={lot} />
|
||||
</TableCell>
|
||||
</>
|
||||
) : (
|
||||
<TableCell className="flex justify-center">
|
||||
<ManualPrint lot={lot} />
|
||||
</TableCell>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
)}
|
||||
</Table>
|
||||
)}
|
||||
</Table>
|
||||
</ScrollArea>
|
||||
</LstCard>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {Button} from "@/components/ui/button";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@@ -8,8 +8,8 @@ import {
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@/components/ui/dialog";
|
||||
import {Input} from "@/components/ui/input";
|
||||
import {Label} from "@/components/ui/label";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
@@ -19,81 +19,81 @@ import {
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/components/ui/select";
|
||||
import {Textarea} from "@/components/ui/textarea";
|
||||
import {useSessionStore} from "@/lib/store/sessionStore";
|
||||
import {useSettingStore} from "@/lib/store/useSettings";
|
||||
import {LotType} from "@/types/lots";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { useSettingStore } from "@/lib/store/useSettings";
|
||||
import axios from "axios";
|
||||
import {Tag} from "lucide-react";
|
||||
import {useState} from "react";
|
||||
import {Controller, useForm} from "react-hook-form";
|
||||
import {toast} from "sonner";
|
||||
import {manualPrintLabels} from "./ManualPrintLabel";
|
||||
import { Tag } from "lucide-react";
|
||||
import { useState } from "react";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import { toast } from "sonner";
|
||||
|
||||
const printReason = [
|
||||
{key: "printerIssue", label: "Printer Related"},
|
||||
{key: "strapper", label: "Strapper Error"},
|
||||
{key: "manualCheck", label: "20th pallet check"},
|
||||
{key: "outOfSync", label: "Labeler Out of Sync"},
|
||||
{ key: "printerIssue", label: "Printer Related" },
|
||||
{ key: "missingRfidTag", label: "Missing or incorrect tag" },
|
||||
{ key: "strapper", label: "Strapper Error" },
|
||||
{ key: "manualCheck", label: "20th pallet check" },
|
||||
{ key: "outOfSync", label: "Labeler Out of Sync" },
|
||||
];
|
||||
|
||||
export default function ManualPrintForm({lot}: {lot: LotType}) {
|
||||
const {user} = useSessionStore();
|
||||
export default function ManualPrintForm() {
|
||||
const token = localStorage.getItem("auth_token");
|
||||
const {settings} = useSettingStore();
|
||||
const { settings } = useSettingStore();
|
||||
const [open, setOpen] = useState(false);
|
||||
const server = settings.filter((n) => n.name === "server")[0]?.value;
|
||||
// const serverPort = settings.filter((n) => n.name === "serverPort")[0]?.value;
|
||||
// const serverUrl = `http://${server}:${serverPort}`;
|
||||
|
||||
// what is the dyco set to? rfid or dyco
|
||||
const dyco = settings.filter((n) => n.name === "dycoPrint");
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
//watch,
|
||||
formState: {errors},
|
||||
formState: { errors },
|
||||
reset,
|
||||
control,
|
||||
} = useForm();
|
||||
|
||||
const handlePrintLabel = async (lot: LotType) => {
|
||||
//console.log(lot);
|
||||
const labels: any = await manualPrintLabels(lot, user);
|
||||
|
||||
if (labels.success) {
|
||||
toast.success(labels.message);
|
||||
} else {
|
||||
toast.error(labels.message);
|
||||
}
|
||||
};
|
||||
|
||||
const handleManualPrintLog = async (logData: any, lot: LotType) => {
|
||||
const handleManualPrintLog = async (logData: any) => {
|
||||
// toast.success(`A new label was sent to printer: ${lot.PrinterName} for line ${lot.MachineDescription} `);
|
||||
const logdataUrl = `/api/ocp/manualLabelLog`;
|
||||
const logdataUrl = `/api/ocp/manuallabellog`;
|
||||
axios
|
||||
.post(logdataUrl, logData, {headers: {Authorization: `Bearer ${token}`}})
|
||||
.then((d) => {
|
||||
//console.log(d);
|
||||
toast.success(d.data.message);
|
||||
handlePrintLabel(lot);
|
||||
reset();
|
||||
})
|
||||
.catch((e) => {
|
||||
if (e.response.status === 500) {
|
||||
toast.error(`Internal Server error please try again.`);
|
||||
return {sucess: false};
|
||||
}
|
||||
.post(logdataUrl, logData, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
})
|
||||
.then((d) => {
|
||||
console.log(d);
|
||||
if (d.data.success) {
|
||||
toast.success(d.data.message);
|
||||
} else {
|
||||
toast.error(d.data.message);
|
||||
}
|
||||
reset();
|
||||
setOpen(false);
|
||||
})
|
||||
.catch((e) => {
|
||||
if (e.response.status === 500) {
|
||||
toast.error(`Internal Server error please try again.`);
|
||||
return { sucess: false };
|
||||
}
|
||||
|
||||
if (e.response.status === 401) {
|
||||
//console.log(e.response);
|
||||
toast.error(`You are not authorized to do this.`);
|
||||
return {sucess: false};
|
||||
}
|
||||
});
|
||||
if (e.response.status === 401) {
|
||||
//console.log(e.response);
|
||||
toast.error(`You are not authorized to do this.`);
|
||||
return { sucess: false };
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const onSubmit = (data: any) => {
|
||||
console.log(data);
|
||||
//console.log(data);
|
||||
|
||||
handleManualPrintLog(data, lot);
|
||||
handleManualPrintLog(data);
|
||||
};
|
||||
|
||||
const closeForm = () => {
|
||||
reset();
|
||||
setOpen(false);
|
||||
};
|
||||
return (
|
||||
<Dialog
|
||||
@@ -117,12 +117,14 @@ export default function ManualPrintForm({lot}: {lot: LotType}) {
|
||||
<DialogHeader>
|
||||
<DialogTitle>Edit profile</DialogTitle>
|
||||
<DialogDescription>
|
||||
Make changes to your profile here. Click save when you're done.
|
||||
Make changes to your profile here. Click save when
|
||||
you're done.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<form onSubmit={handleSubmit(onSubmit)}>
|
||||
<p>
|
||||
To manually print a label you must complete all the required fields below.
|
||||
To manually print a label you must complete all the
|
||||
required fields below.
|
||||
<br />
|
||||
If you clicked this in error just click close
|
||||
</p>
|
||||
@@ -133,7 +135,7 @@ export default function ManualPrintForm({lot}: {lot: LotType}) {
|
||||
name="printReason"
|
||||
defaultValue={""}
|
||||
render={({
|
||||
field: {onChange},
|
||||
field: { onChange },
|
||||
fieldState: {},
|
||||
//formState,
|
||||
}) => (
|
||||
@@ -143,35 +145,46 @@ export default function ManualPrintForm({lot}: {lot: LotType}) {
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
<SelectLabel>Print Reasons</SelectLabel>
|
||||
{printReason.map((printReason: any) => (
|
||||
<SelectItem value={printReason.key}>{printReason.label}</SelectItem>
|
||||
))}
|
||||
<SelectLabel>
|
||||
Print Reasons
|
||||
</SelectLabel>
|
||||
{printReason.map(
|
||||
(printReason: any) => (
|
||||
<SelectItem
|
||||
value={printReason.key}
|
||||
>
|
||||
{printReason.label}
|
||||
</SelectItem>
|
||||
)
|
||||
)}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
)}
|
||||
/>
|
||||
) : (
|
||||
<div>
|
||||
<div className="m-2">
|
||||
<Label htmlFor="printRason" className="m-1">
|
||||
Why are you manually printing?
|
||||
</Label>
|
||||
<Input
|
||||
type="text"
|
||||
className={errors.printReason ? "border-red-500" : ""}
|
||||
className={
|
||||
errors.printReason ? "border-red-500" : ""
|
||||
}
|
||||
aria-invalid={!!errors.printReason}
|
||||
{...register("printReason", {
|
||||
required: true,
|
||||
minLength: {
|
||||
value: 5,
|
||||
message: "To short of a reason please try again!",
|
||||
message:
|
||||
"To short of a reason please try again!",
|
||||
},
|
||||
})}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div>
|
||||
<div className="m-2">
|
||||
<Label htmlFor="line" className="m-1">
|
||||
"What is the line number you are printing?"
|
||||
</Label>
|
||||
@@ -180,11 +193,11 @@ export default function ManualPrintForm({lot}: {lot: LotType}) {
|
||||
type="number"
|
||||
className={errors.line ? "border-red-500" : ""}
|
||||
aria-invalid={!!errors.line}
|
||||
{...register("line", {required: true})}
|
||||
{...register("line", { required: true })}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className="m-2">
|
||||
<Label htmlFor="initials" className="m-1">
|
||||
Enter intials
|
||||
</Label>
|
||||
@@ -192,23 +205,55 @@ export default function ManualPrintForm({lot}: {lot: LotType}) {
|
||||
//variant="underlined"
|
||||
//label="Enter intials"
|
||||
|
||||
{...register("initials", {required: true})}
|
||||
{...register("initials", { required: true })}
|
||||
/>
|
||||
</div>
|
||||
<hr />
|
||||
{dyco[0].value === "0" && (
|
||||
<div>
|
||||
<p>Enter the missing tag number.</p>
|
||||
<hr />
|
||||
<Label htmlFor="rfidTag" className="m-1">
|
||||
Enter the tag number only Example
|
||||
ALPLA000002541. only enter 2541
|
||||
</Label>
|
||||
<Input
|
||||
type="text"
|
||||
className={
|
||||
errors.printReason ? "border-red-500" : ""
|
||||
}
|
||||
aria-invalid={!!errors.printReason}
|
||||
{...register("rfidTag", {
|
||||
required: true,
|
||||
minLength: {
|
||||
value: 1,
|
||||
message: "Tag number is to short!",
|
||||
},
|
||||
})}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div className="m-2">
|
||||
<Textarea
|
||||
//label="Comments"
|
||||
placeholder="add more info as needed."
|
||||
{...register("additionalComments")}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Textarea
|
||||
//label="Comments"
|
||||
placeholder="add more info as needed."
|
||||
{...register("additionalComments")}
|
||||
/>
|
||||
|
||||
<DialogFooter>
|
||||
<Button color="danger" variant="default" onClick={() => setOpen(!open)}>
|
||||
Close
|
||||
</Button>
|
||||
<Button color="primary" type="submit">
|
||||
Print
|
||||
</Button>
|
||||
<div className="mt-3">
|
||||
<Button
|
||||
color="danger"
|
||||
variant="default"
|
||||
onClick={closeForm}
|
||||
>
|
||||
Close
|
||||
</Button>
|
||||
<Button color="primary" type="submit">
|
||||
Print
|
||||
</Button>
|
||||
</div>
|
||||
</DialogFooter>
|
||||
</form>
|
||||
</DialogContent>
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import {LotType} from "@/types/lots";
|
||||
import { LotType } from "@/types/lots";
|
||||
import axios from "axios";
|
||||
|
||||
export const manualPrintLabels = async (lot: LotType, user: any) => {
|
||||
//console.log(lot);
|
||||
const labelUrl = `/ocp/manualPrintAndFollow`;
|
||||
const labelUrl = `/api/ocp/manualprintandfollow`;
|
||||
|
||||
try {
|
||||
const res = await axios.post(
|
||||
labelUrl,
|
||||
{line: lot.MachineLocation, printerName: lot.PrinterName},
|
||||
{headers: {Authorization: `Basic ${user?.prod}`}}
|
||||
{ line: lot.MachineLocation, printerName: lot.PrinterName },
|
||||
{ headers: { Authorization: `Basic ${user?.prod}` } }
|
||||
);
|
||||
|
||||
if (res.data.success) {
|
||||
@@ -19,7 +19,7 @@ export const manualPrintLabels = async (lot: LotType, user: any) => {
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
success: true,
|
||||
success: false,
|
||||
message: `Line ${lot.MachineDescription} encountered an error printing labels: ${res.data.message}`,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,5 +1,154 @@
|
||||
import {LstCard} from "@/components/extendedUI/LstCard";
|
||||
import { LstCard } from "@/components/extendedUI/LstCard";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/components/ui/table";
|
||||
import { getOcpLogs } from "@/utils/querys/production/ocpLogs";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import axios from "axios";
|
||||
import { format } from "date-fns";
|
||||
import { Trash } from "lucide-react";
|
||||
import { toast } from "sonner";
|
||||
|
||||
const labelLogs = [
|
||||
{ key: "message", label: "Error Message" },
|
||||
{ key: "created_at", label: "ErrorDat" },
|
||||
{ key: "clear", label: "Clear" },
|
||||
//{key: "reprint", label: "Reprint"}, // removing the reprint button for now until repritning is working as intended
|
||||
];
|
||||
|
||||
export default function OcpLogs() {
|
||||
return <LstCard className="m-2 p-2">Ocp Logs</LstCard>;
|
||||
const { data, isError, isLoading } = useQuery(getOcpLogs("4"));
|
||||
|
||||
const clearLog = async (log: any) => {
|
||||
try {
|
||||
const res = await axios.patch(`/api/logger/logs/${log.log_id}`);
|
||||
|
||||
if (res.data.success) {
|
||||
toast.success(`Log message: ${log.message}, was just cleared`);
|
||||
} else {
|
||||
console.log(res);
|
||||
toast.error(`There was an error clearing the message.`);
|
||||
}
|
||||
} catch (error) {
|
||||
toast.error(`There was an error trying to clearing the message.`);
|
||||
}
|
||||
};
|
||||
const logData = data ? data : [];
|
||||
if (isError) {
|
||||
return (
|
||||
<div className="m-2 p-2 min-h-2/5">
|
||||
<LstCard>
|
||||
<p className="text-center">Labels for the last 2 hours</p>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
{labelLogs.map((l) => (
|
||||
<TableHead key={l.key}>{l.label}</TableHead>
|
||||
))}
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
|
||||
<TableBody>
|
||||
{Array(7)
|
||||
.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>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</LstCard>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<LstCard className="m-2 p-2 min-h-2/5">
|
||||
<p className="text-center">Labels for the last 2 hours</p>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
{labelLogs.map((l) => (
|
||||
<TableHead key={l.key}>{l.label}</TableHead>
|
||||
))}
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
{isLoading ? (
|
||||
<>
|
||||
<TableBody>
|
||||
{Array(7)
|
||||
.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>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</>
|
||||
) : (
|
||||
<TableBody>
|
||||
{logData.map((label: any) => (
|
||||
<TableRow key={label.log_id}>
|
||||
<TableCell className="font-medium max-w-5/6">
|
||||
<p className="text-balance">
|
||||
{label.message}
|
||||
</p>
|
||||
</TableCell>
|
||||
<TableCell className="font-medium">
|
||||
{format(
|
||||
label?.created_at.replace("Z", ""),
|
||||
"M/d/yyyy hh:mm"
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell className="font-medium">
|
||||
<Button
|
||||
size="icon"
|
||||
onClick={() => clearLog(label)}
|
||||
>
|
||||
<Trash />
|
||||
</Button>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
)}
|
||||
</Table>
|
||||
</LstCard>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,28 +1,54 @@
|
||||
import WrapperManualTrigger from "@/components/ocme/WrapperCard";
|
||||
import LabelLog from "./LabelLog";
|
||||
import Lots from "./Lots";
|
||||
import OcpLogs from "./OcpLogs";
|
||||
import PrinterStatus from "./PrinterStatus";
|
||||
import { useSettingStore } from "@/lib/store/useSettings";
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||
|
||||
export default function OCPPage() {
|
||||
const { settings } = useSettingStore();
|
||||
|
||||
const server = settings.filter((n) => n.plantToken === "usday1");
|
||||
console.log(server);
|
||||
return (
|
||||
<div className="h-dvh w-full overflow-hidden">
|
||||
<div className="h-screen w-full ">
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<div className="flex flex-col w-4/5 h-dvh">
|
||||
<div className="">
|
||||
<Lots />
|
||||
</div>
|
||||
|
||||
<div className="flex flex-row">
|
||||
<div className="w-1/2">
|
||||
<LabelLog />
|
||||
</div>
|
||||
<div className="w-1/2">
|
||||
<OcpLogs />
|
||||
</div>
|
||||
<div className="w-5/6 h-1/2">
|
||||
<Tabs defaultValue="ocplogs" className="w-full">
|
||||
<TabsList className="grid w-full grid-cols-2">
|
||||
<TabsTrigger value="ocplogs">
|
||||
OcpLogs
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="labels">Labels</TabsTrigger>
|
||||
</TabsList>
|
||||
<TabsContent value="ocplogs">
|
||||
<div className="w-full">
|
||||
<OcpLogs />
|
||||
</div>
|
||||
</TabsContent>
|
||||
<TabsContent value="labels">
|
||||
<div className="w-full">
|
||||
<LabelLog />
|
||||
</div>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-1/6">
|
||||
<PrinterStatus />
|
||||
<div className="w-1/6 flex flex-col">
|
||||
{server.length >= 1 && (
|
||||
<div>
|
||||
<WrapperManualTrigger />
|
||||
</div>
|
||||
)}
|
||||
<div>
|
||||
<PrinterStatus />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
import {LstCard} from "@/components/extendedUI/LstCard";
|
||||
import {Skeleton} from "@/components/ui/skeleton";
|
||||
import {Table, TableBody, TableCell, TableHead, TableHeader, TableRow} from "@/components/ui/table";
|
||||
import { LstCard } from "@/components/extendedUI/LstCard";
|
||||
import { ScrollArea } from "@/components/ui/scroll-area";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/components/ui/table";
|
||||
import { getPrinters } from "@/utils/querys/production/printers";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
|
||||
let printerCols = [
|
||||
{
|
||||
key: "status",
|
||||
label: "Status",
|
||||
},
|
||||
{
|
||||
key: "printer",
|
||||
label: "Printer",
|
||||
@@ -17,36 +23,92 @@ let printerCols = [
|
||||
},
|
||||
];
|
||||
export default function PrinterStatus() {
|
||||
const { data, isError, isLoading } = useQuery(getPrinters());
|
||||
|
||||
if (isError) {
|
||||
return (
|
||||
<ScrollArea className="h-[400px]">
|
||||
<p className="text-center">Printer Staus error</p>
|
||||
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
{printerCols.map((l) => (
|
||||
<TableHead key={l.key}>{l.label}</TableHead>
|
||||
))}
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
|
||||
<TableBody>
|
||||
{Array(5)
|
||||
.fill(0)
|
||||
.map((_, i) => (
|
||||
<TableRow key={i}>
|
||||
<TableCell className="font-medium">
|
||||
<Skeleton className="h-4" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4" />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</ScrollArea>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* only show the assigned printers
|
||||
*/
|
||||
|
||||
const assigned = data?.filter((a: any) => a.assigned) || [];
|
||||
return (
|
||||
<LstCard className="m-2 p-2">
|
||||
<p className="text-center">Printer Status</p>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
{printerCols.map((l) => (
|
||||
<TableHead key={l.key}>{l.label}</TableHead>
|
||||
))}
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<ScrollArea className="max-h-[800px]">
|
||||
<p className="text-center">
|
||||
{isLoading ? (
|
||||
<span>Printers status loading...</span>
|
||||
) : (
|
||||
<span>Printer Status</span>
|
||||
)}
|
||||
</p>
|
||||
|
||||
<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>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
{printerCols.map((l) => (
|
||||
<TableHead key={l.key}>{l.label}</TableHead>
|
||||
))}
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableHeader>{" "}
|
||||
{isLoading ? (
|
||||
<TableBody>
|
||||
{Array(5)
|
||||
.fill(0)
|
||||
.map((_, i) => (
|
||||
<TableRow key={i}>
|
||||
<TableCell className="font-medium">
|
||||
<Skeleton className="h-4" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4" />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
) : (
|
||||
<TableBody>
|
||||
{assigned?.map((p: any) => (
|
||||
<TableRow key={p.printer_id}>
|
||||
<TableCell>{p.name}</TableCell>
|
||||
<TableCell>{p.statusText}</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
)}
|
||||
</Table>
|
||||
</ScrollArea>
|
||||
</LstCard>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,20 +1,31 @@
|
||||
import {QueryClient, QueryClientProvider} from "@tanstack/react-query";
|
||||
import {useModuleStore} from "../../lib/store/useModuleStore";
|
||||
import {useEffect} from "react";
|
||||
import {useSettingStore} from "@/lib/store/useSettings";
|
||||
//import {useGetUserRoles} from "@/lib/store/useGetRoles";
|
||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
import { useModuleStore } from "../../lib/store/useModuleStore";
|
||||
import { useEffect } from "react";
|
||||
import { useSettingStore } from "@/lib/store/useSettings";
|
||||
import { useGetUserRoles } from "@/lib/store/useGetRoles";
|
||||
import { useSubModuleStore } from "@/lib/store/useSubModuleStore";
|
||||
|
||||
const queryClient = new QueryClient();
|
||||
|
||||
export const SessionProvider = ({children}: {children: React.ReactNode}) => {
|
||||
const {fetchModules} = useModuleStore();
|
||||
const {fetchSettings} = useSettingStore();
|
||||
//const {fetchUserRoles} = useGetUserRoles();
|
||||
export const SessionProvider = ({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) => {
|
||||
const { fetchModules } = useModuleStore();
|
||||
const { fetchSettings } = useSettingStore();
|
||||
const { fetchUserRoles } = useGetUserRoles();
|
||||
const { fetchSubModules } = useSubModuleStore();
|
||||
|
||||
useEffect(() => {
|
||||
fetchModules();
|
||||
fetchSettings();
|
||||
//fetchUserRoles();
|
||||
fetchUserRoles();
|
||||
fetchSubModules();
|
||||
}, []);
|
||||
return <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>;
|
||||
return (
|
||||
<QueryClientProvider client={queryClient}>
|
||||
{children}
|
||||
</QueryClientProvider>
|
||||
);
|
||||
};
|
||||
|
||||
64
frontend/src/components/ui/accordion.tsx
Normal file
64
frontend/src/components/ui/accordion.tsx
Normal file
@@ -0,0 +1,64 @@
|
||||
import * as React from "react"
|
||||
import * as AccordionPrimitive from "@radix-ui/react-accordion"
|
||||
import { ChevronDownIcon } from "lucide-react"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
function Accordion({
|
||||
...props
|
||||
}: React.ComponentProps<typeof AccordionPrimitive.Root>) {
|
||||
return <AccordionPrimitive.Root data-slot="accordion" {...props} />
|
||||
}
|
||||
|
||||
function AccordionItem({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof AccordionPrimitive.Item>) {
|
||||
return (
|
||||
<AccordionPrimitive.Item
|
||||
data-slot="accordion-item"
|
||||
className={cn("border-b last:border-b-0", className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function AccordionTrigger({
|
||||
className,
|
||||
children,
|
||||
...props
|
||||
}: React.ComponentProps<typeof AccordionPrimitive.Trigger>) {
|
||||
return (
|
||||
<AccordionPrimitive.Header className="flex">
|
||||
<AccordionPrimitive.Trigger
|
||||
data-slot="accordion-trigger"
|
||||
className={cn(
|
||||
"focus-visible:border-ring focus-visible:ring-ring/50 flex flex-1 items-start justify-between gap-4 rounded-md py-4 text-left text-sm font-medium transition-all outline-none hover:underline focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 [&[data-state=open]>svg]:rotate-180",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
<ChevronDownIcon className="text-muted-foreground pointer-events-none size-4 shrink-0 translate-y-0.5 transition-transform duration-200" />
|
||||
</AccordionPrimitive.Trigger>
|
||||
</AccordionPrimitive.Header>
|
||||
)
|
||||
}
|
||||
|
||||
function AccordionContent({
|
||||
className,
|
||||
children,
|
||||
...props
|
||||
}: React.ComponentProps<typeof AccordionPrimitive.Content>) {
|
||||
return (
|
||||
<AccordionPrimitive.Content
|
||||
data-slot="accordion-content"
|
||||
className="data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down overflow-hidden text-sm"
|
||||
{...props}
|
||||
>
|
||||
<div className={cn("pt-0 pb-4", className)}>{children}</div>
|
||||
</AccordionPrimitive.Content>
|
||||
)
|
||||
}
|
||||
|
||||
export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }
|
||||
@@ -12,7 +12,7 @@ function Checkbox({
|
||||
<CheckboxPrimitive.Root
|
||||
data-slot="checkbox"
|
||||
className={cn(
|
||||
"peer border-input data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
|
||||
"peer border-input dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
||||
45
frontend/src/components/ui/resizable-panels.tsx
Normal file
45
frontend/src/components/ui/resizable-panels.tsx
Normal file
@@ -0,0 +1,45 @@
|
||||
"use client";
|
||||
|
||||
import { GripVertical } from "lucide-react";
|
||||
import * as ResizablePrimitive from "react-resizable-panels";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const ResizablePanelGroup = ({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof ResizablePrimitive.PanelGroup>) => (
|
||||
<ResizablePrimitive.PanelGroup
|
||||
className={cn(
|
||||
"flex h-full w-full data-[panel-group-direction=vertical]:flex-col",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
|
||||
const ResizablePanel = ResizablePrimitive.Panel;
|
||||
|
||||
const ResizableHandle = ({
|
||||
withHandle,
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof ResizablePrimitive.PanelResizeHandle> & {
|
||||
withHandle?: boolean;
|
||||
}) => (
|
||||
<ResizablePrimitive.PanelResizeHandle
|
||||
className={cn(
|
||||
"relative flex w-px items-center justify-center bg-border after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1 data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:-translate-y-1/2 data-[panel-group-direction=vertical]:after:translate-x-0 [&[data-panel-group-direction=vertical]>div]:rotate-90",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{withHandle && (
|
||||
<div className="z-10 flex h-4 w-3 items-center justify-center rounded-sm border bg-border">
|
||||
<GripVertical className="h-2.5 w-2.5" />
|
||||
</div>
|
||||
)}
|
||||
</ResizablePrimitive.PanelResizeHandle>
|
||||
);
|
||||
|
||||
export { ResizablePanelGroup, ResizablePanel, ResizableHandle };
|
||||
56
frontend/src/components/ui/scroll-area.tsx
Normal file
56
frontend/src/components/ui/scroll-area.tsx
Normal file
@@ -0,0 +1,56 @@
|
||||
import * as React from "react"
|
||||
import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
function ScrollArea({
|
||||
className,
|
||||
children,
|
||||
...props
|
||||
}: React.ComponentProps<typeof ScrollAreaPrimitive.Root>) {
|
||||
return (
|
||||
<ScrollAreaPrimitive.Root
|
||||
data-slot="scroll-area"
|
||||
className={cn("relative", className)}
|
||||
{...props}
|
||||
>
|
||||
<ScrollAreaPrimitive.Viewport
|
||||
data-slot="scroll-area-viewport"
|
||||
className="ring-ring/10 dark:ring-ring/20 dark:outline-ring/40 outline-ring/50 size-full rounded-[inherit] transition-[color,box-shadow] focus-visible:ring-4 focus-visible:outline-1"
|
||||
>
|
||||
{children}
|
||||
</ScrollAreaPrimitive.Viewport>
|
||||
<ScrollBar />
|
||||
<ScrollAreaPrimitive.Corner />
|
||||
</ScrollAreaPrimitive.Root>
|
||||
)
|
||||
}
|
||||
|
||||
function ScrollBar({
|
||||
className,
|
||||
orientation = "vertical",
|
||||
...props
|
||||
}: React.ComponentProps<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>) {
|
||||
return (
|
||||
<ScrollAreaPrimitive.ScrollAreaScrollbar
|
||||
data-slot="scroll-area-scrollbar"
|
||||
orientation={orientation}
|
||||
className={cn(
|
||||
"flex touch-none p-px transition-colors select-none",
|
||||
orientation === "vertical" &&
|
||||
"h-full w-2.5 border-l border-l-transparent",
|
||||
orientation === "horizontal" &&
|
||||
"h-2.5 flex-col border-t border-t-transparent",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<ScrollAreaPrimitive.ScrollAreaThumb
|
||||
data-slot="scroll-area-thumb"
|
||||
className="bg-border relative flex-1 rounded-full"
|
||||
/>
|
||||
</ScrollAreaPrimitive.ScrollAreaScrollbar>
|
||||
)
|
||||
}
|
||||
|
||||
export { ScrollArea, ScrollBar }
|
||||
@@ -1,6 +1,5 @@
|
||||
import {create} from "zustand";
|
||||
import {useSessionStore} from "./sessionStore";
|
||||
import {Modules} from "@/types/modules";
|
||||
import { create } from "zustand";
|
||||
import { Modules } from "@/types/modules";
|
||||
import axios from "axios";
|
||||
|
||||
interface SettingState {
|
||||
@@ -15,15 +14,17 @@ interface FetchModulesResponse {
|
||||
|
||||
export const useGetUserRoles = create<SettingState>()((set) => ({
|
||||
userRoles: [],
|
||||
setUserRoles: (userRoles) => set({userRoles}),
|
||||
setUserRoles: (userRoles) => set({ userRoles }),
|
||||
fetchUserRoles: async () => {
|
||||
try {
|
||||
//const response = await axios.get<{data: Setting[]}>(`${process.env.NEXT_PUBLIC_URL}/api/settings/client`);
|
||||
const {token} = useSessionStore();
|
||||
const response = await axios.get("/api/auth/getuseraccess", {headers: {Authorization: `Bearer ${token}`}});
|
||||
const token = localStorage.getItem("auth_token");
|
||||
const response = await axios.get("/api/auth/getuseraccess", {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
const data: FetchModulesResponse = response.data; //await response.json();
|
||||
//console.log(data);
|
||||
set({userRoles: data.data});
|
||||
set({ userRoles: data.data });
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch settings:", error);
|
||||
}
|
||||
|
||||
30
frontend/src/lib/store/useSubModuleStore.ts
Normal file
30
frontend/src/lib/store/useSubModuleStore.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { SubModules } from "@/types/modules";
|
||||
import axios from "axios";
|
||||
import { create } from "zustand";
|
||||
|
||||
interface SettingState {
|
||||
subModules: SubModules[];
|
||||
|
||||
fetchSubModules: () => Promise<void>;
|
||||
setSubModules: (modules: SubModules[]) => void;
|
||||
}
|
||||
interface FetchModulesResponse {
|
||||
data: SubModules[];
|
||||
}
|
||||
|
||||
export const useSubModuleStore = create<SettingState>()((set) => ({
|
||||
subModules: [],
|
||||
setSubModules: (subModules) => set({ subModules }),
|
||||
fetchSubModules: async () => {
|
||||
try {
|
||||
//const response = await axios.get<{data: Setting[]}>(`${process.env.NEXT_PUBLIC_URL}/api/settings/client`);
|
||||
const response = await axios.get(`/api/server/submodules`, {});
|
||||
const data: FetchModulesResponse = response.data; //await response.json();
|
||||
//console.log(data);
|
||||
set({ subModules: data.data });
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch settings:", error);
|
||||
set({ subModules: [] });
|
||||
}
|
||||
},
|
||||
}));
|
||||
@@ -20,14 +20,17 @@ import { Route as IndexImport } from './routes/index'
|
||||
import { Route as OcpIndexImport } from './routes/ocp/index'
|
||||
import { Route as EomEomImport } from './routes/_eom/eom'
|
||||
import { Route as AuthProfileImport } from './routes/_auth/profile'
|
||||
import { Route as AdminUsersImport } from './routes/_admin/users'
|
||||
import { Route as AdminSettingsImport } from './routes/_admin/settings'
|
||||
import { Route as AdminServersImport } from './routes/_admin/servers'
|
||||
import { Route as AdminModulesImport } from './routes/_admin/modules'
|
||||
import { Route as ocmeCyclecountIndexImport } from './routes/(ocme)/cyclecount/index'
|
||||
import { Route as logisticsSiloAdjustmentsIndexImport } from './routes/(logistics)/siloAdjustments/index'
|
||||
import { Route as logisticsMaterialHelperIndexImport } from './routes/(logistics)/materialHelper/index'
|
||||
import { Route as EomArticleAvImport } from './routes/_eom/article/$av'
|
||||
import { Route as logisticsMaterialHelperSiloLinkIndexImport } from './routes/(logistics)/materialHelper/siloLink/index'
|
||||
import { Route as logisticsMaterialHelperConsumptionIndexImport } from './routes/(logistics)/materialHelper/consumption/index'
|
||||
import { Route as logisticsSiloAdjustmentsCommentCommentImport } from './routes/(logistics)/siloAdjustments/comment/$comment'
|
||||
|
||||
// Create/Update Routes
|
||||
|
||||
@@ -82,6 +85,12 @@ const AuthProfileRoute = AuthProfileImport.update({
|
||||
getParentRoute: () => AuthRoute,
|
||||
} as any)
|
||||
|
||||
const AdminUsersRoute = AdminUsersImport.update({
|
||||
id: '/users',
|
||||
path: '/users',
|
||||
getParentRoute: () => AdminRoute,
|
||||
} as any)
|
||||
|
||||
const AdminSettingsRoute = AdminSettingsImport.update({
|
||||
id: '/settings',
|
||||
path: '/settings',
|
||||
@@ -106,6 +115,13 @@ const ocmeCyclecountIndexRoute = ocmeCyclecountIndexImport.update({
|
||||
getParentRoute: () => rootRoute,
|
||||
} as any)
|
||||
|
||||
const logisticsSiloAdjustmentsIndexRoute =
|
||||
logisticsSiloAdjustmentsIndexImport.update({
|
||||
id: '/(logistics)/siloAdjustments/',
|
||||
path: '/siloAdjustments/',
|
||||
getParentRoute: () => rootRoute,
|
||||
} as any)
|
||||
|
||||
const logisticsMaterialHelperIndexRoute =
|
||||
logisticsMaterialHelperIndexImport.update({
|
||||
id: '/(logistics)/materialHelper/',
|
||||
@@ -133,6 +149,13 @@ const logisticsMaterialHelperConsumptionIndexRoute =
|
||||
getParentRoute: () => rootRoute,
|
||||
} as any)
|
||||
|
||||
const logisticsSiloAdjustmentsCommentCommentRoute =
|
||||
logisticsSiloAdjustmentsCommentCommentImport.update({
|
||||
id: '/(logistics)/siloAdjustments/comment/$comment',
|
||||
path: '/siloAdjustments/comment/$comment',
|
||||
getParentRoute: () => rootRoute,
|
||||
} as any)
|
||||
|
||||
// Populate the FileRoutesByPath interface
|
||||
|
||||
declare module '@tanstack/react-router' {
|
||||
@@ -200,6 +223,13 @@ declare module '@tanstack/react-router' {
|
||||
preLoaderRoute: typeof AdminSettingsImport
|
||||
parentRoute: typeof AdminImport
|
||||
}
|
||||
'/_admin/users': {
|
||||
id: '/_admin/users'
|
||||
path: '/users'
|
||||
fullPath: '/users'
|
||||
preLoaderRoute: typeof AdminUsersImport
|
||||
parentRoute: typeof AdminImport
|
||||
}
|
||||
'/_auth/profile': {
|
||||
id: '/_auth/profile'
|
||||
path: '/profile'
|
||||
@@ -235,6 +265,13 @@ declare module '@tanstack/react-router' {
|
||||
preLoaderRoute: typeof logisticsMaterialHelperIndexImport
|
||||
parentRoute: typeof rootRoute
|
||||
}
|
||||
'/(logistics)/siloAdjustments/': {
|
||||
id: '/(logistics)/siloAdjustments/'
|
||||
path: '/siloAdjustments'
|
||||
fullPath: '/siloAdjustments'
|
||||
preLoaderRoute: typeof logisticsSiloAdjustmentsIndexImport
|
||||
parentRoute: typeof rootRoute
|
||||
}
|
||||
'/(ocme)/cyclecount/': {
|
||||
id: '/(ocme)/cyclecount/'
|
||||
path: '/cyclecount'
|
||||
@@ -242,6 +279,13 @@ declare module '@tanstack/react-router' {
|
||||
preLoaderRoute: typeof ocmeCyclecountIndexImport
|
||||
parentRoute: typeof rootRoute
|
||||
}
|
||||
'/(logistics)/siloAdjustments/comment/$comment': {
|
||||
id: '/(logistics)/siloAdjustments/comment/$comment'
|
||||
path: '/siloAdjustments/comment/$comment'
|
||||
fullPath: '/siloAdjustments/comment/$comment'
|
||||
preLoaderRoute: typeof logisticsSiloAdjustmentsCommentCommentImport
|
||||
parentRoute: typeof rootRoute
|
||||
}
|
||||
'/(logistics)/materialHelper/consumption/': {
|
||||
id: '/(logistics)/materialHelper/consumption/'
|
||||
path: '/materialHelper/consumption'
|
||||
@@ -265,12 +309,14 @@ interface AdminRouteChildren {
|
||||
AdminModulesRoute: typeof AdminModulesRoute
|
||||
AdminServersRoute: typeof AdminServersRoute
|
||||
AdminSettingsRoute: typeof AdminSettingsRoute
|
||||
AdminUsersRoute: typeof AdminUsersRoute
|
||||
}
|
||||
|
||||
const AdminRouteChildren: AdminRouteChildren = {
|
||||
AdminModulesRoute: AdminModulesRoute,
|
||||
AdminServersRoute: AdminServersRoute,
|
||||
AdminSettingsRoute: AdminSettingsRoute,
|
||||
AdminUsersRoute: AdminUsersRoute,
|
||||
}
|
||||
|
||||
const AdminRouteWithChildren = AdminRoute._addFileChildren(AdminRouteChildren)
|
||||
@@ -305,12 +351,15 @@ export interface FileRoutesByFullPath {
|
||||
'/modules': typeof AdminModulesRoute
|
||||
'/servers': typeof AdminServersRoute
|
||||
'/settings': typeof AdminSettingsRoute
|
||||
'/users': typeof AdminUsersRoute
|
||||
'/profile': typeof AuthProfileRoute
|
||||
'/eom': typeof EomEomRoute
|
||||
'/ocp': typeof OcpIndexRoute
|
||||
'/article/$av': typeof EomArticleAvRoute
|
||||
'/materialHelper': typeof logisticsMaterialHelperIndexRoute
|
||||
'/siloAdjustments': typeof logisticsSiloAdjustmentsIndexRoute
|
||||
'/cyclecount': typeof ocmeCyclecountIndexRoute
|
||||
'/siloAdjustments/comment/$comment': typeof logisticsSiloAdjustmentsCommentCommentRoute
|
||||
'/materialHelper/consumption': typeof logisticsMaterialHelperConsumptionIndexRoute
|
||||
'/materialHelper/siloLink': typeof logisticsMaterialHelperSiloLinkIndexRoute
|
||||
}
|
||||
@@ -323,12 +372,15 @@ export interface FileRoutesByTo {
|
||||
'/modules': typeof AdminModulesRoute
|
||||
'/servers': typeof AdminServersRoute
|
||||
'/settings': typeof AdminSettingsRoute
|
||||
'/users': typeof AdminUsersRoute
|
||||
'/profile': typeof AuthProfileRoute
|
||||
'/eom': typeof EomEomRoute
|
||||
'/ocp': typeof OcpIndexRoute
|
||||
'/article/$av': typeof EomArticleAvRoute
|
||||
'/materialHelper': typeof logisticsMaterialHelperIndexRoute
|
||||
'/siloAdjustments': typeof logisticsSiloAdjustmentsIndexRoute
|
||||
'/cyclecount': typeof ocmeCyclecountIndexRoute
|
||||
'/siloAdjustments/comment/$comment': typeof logisticsSiloAdjustmentsCommentCommentRoute
|
||||
'/materialHelper/consumption': typeof logisticsMaterialHelperConsumptionIndexRoute
|
||||
'/materialHelper/siloLink': typeof logisticsMaterialHelperSiloLinkIndexRoute
|
||||
}
|
||||
@@ -344,12 +396,15 @@ export interface FileRoutesById {
|
||||
'/_admin/modules': typeof AdminModulesRoute
|
||||
'/_admin/servers': typeof AdminServersRoute
|
||||
'/_admin/settings': typeof AdminSettingsRoute
|
||||
'/_admin/users': typeof AdminUsersRoute
|
||||
'/_auth/profile': typeof AuthProfileRoute
|
||||
'/_eom/eom': typeof EomEomRoute
|
||||
'/ocp/': typeof OcpIndexRoute
|
||||
'/_eom/article/$av': typeof EomArticleAvRoute
|
||||
'/(logistics)/materialHelper/': typeof logisticsMaterialHelperIndexRoute
|
||||
'/(logistics)/siloAdjustments/': typeof logisticsSiloAdjustmentsIndexRoute
|
||||
'/(ocme)/cyclecount/': typeof ocmeCyclecountIndexRoute
|
||||
'/(logistics)/siloAdjustments/comment/$comment': typeof logisticsSiloAdjustmentsCommentCommentRoute
|
||||
'/(logistics)/materialHelper/consumption/': typeof logisticsMaterialHelperConsumptionIndexRoute
|
||||
'/(logistics)/materialHelper/siloLink/': typeof logisticsMaterialHelperSiloLinkIndexRoute
|
||||
}
|
||||
@@ -364,12 +419,15 @@ export interface FileRouteTypes {
|
||||
| '/modules'
|
||||
| '/servers'
|
||||
| '/settings'
|
||||
| '/users'
|
||||
| '/profile'
|
||||
| '/eom'
|
||||
| '/ocp'
|
||||
| '/article/$av'
|
||||
| '/materialHelper'
|
||||
| '/siloAdjustments'
|
||||
| '/cyclecount'
|
||||
| '/siloAdjustments/comment/$comment'
|
||||
| '/materialHelper/consumption'
|
||||
| '/materialHelper/siloLink'
|
||||
fileRoutesByTo: FileRoutesByTo
|
||||
@@ -381,12 +439,15 @@ export interface FileRouteTypes {
|
||||
| '/modules'
|
||||
| '/servers'
|
||||
| '/settings'
|
||||
| '/users'
|
||||
| '/profile'
|
||||
| '/eom'
|
||||
| '/ocp'
|
||||
| '/article/$av'
|
||||
| '/materialHelper'
|
||||
| '/siloAdjustments'
|
||||
| '/cyclecount'
|
||||
| '/siloAdjustments/comment/$comment'
|
||||
| '/materialHelper/consumption'
|
||||
| '/materialHelper/siloLink'
|
||||
id:
|
||||
@@ -400,12 +461,15 @@ export interface FileRouteTypes {
|
||||
| '/_admin/modules'
|
||||
| '/_admin/servers'
|
||||
| '/_admin/settings'
|
||||
| '/_admin/users'
|
||||
| '/_auth/profile'
|
||||
| '/_eom/eom'
|
||||
| '/ocp/'
|
||||
| '/_eom/article/$av'
|
||||
| '/(logistics)/materialHelper/'
|
||||
| '/(logistics)/siloAdjustments/'
|
||||
| '/(ocme)/cyclecount/'
|
||||
| '/(logistics)/siloAdjustments/comment/$comment'
|
||||
| '/(logistics)/materialHelper/consumption/'
|
||||
| '/(logistics)/materialHelper/siloLink/'
|
||||
fileRoutesById: FileRoutesById
|
||||
@@ -420,7 +484,9 @@ export interface RootRouteChildren {
|
||||
LoginRoute: typeof LoginRoute
|
||||
OcpIndexRoute: typeof OcpIndexRoute
|
||||
logisticsMaterialHelperIndexRoute: typeof logisticsMaterialHelperIndexRoute
|
||||
logisticsSiloAdjustmentsIndexRoute: typeof logisticsSiloAdjustmentsIndexRoute
|
||||
ocmeCyclecountIndexRoute: typeof ocmeCyclecountIndexRoute
|
||||
logisticsSiloAdjustmentsCommentCommentRoute: typeof logisticsSiloAdjustmentsCommentCommentRoute
|
||||
logisticsMaterialHelperConsumptionIndexRoute: typeof logisticsMaterialHelperConsumptionIndexRoute
|
||||
logisticsMaterialHelperSiloLinkIndexRoute: typeof logisticsMaterialHelperSiloLinkIndexRoute
|
||||
}
|
||||
@@ -434,7 +500,10 @@ const rootRouteChildren: RootRouteChildren = {
|
||||
LoginRoute: LoginRoute,
|
||||
OcpIndexRoute: OcpIndexRoute,
|
||||
logisticsMaterialHelperIndexRoute: logisticsMaterialHelperIndexRoute,
|
||||
logisticsSiloAdjustmentsIndexRoute: logisticsSiloAdjustmentsIndexRoute,
|
||||
ocmeCyclecountIndexRoute: ocmeCyclecountIndexRoute,
|
||||
logisticsSiloAdjustmentsCommentCommentRoute:
|
||||
logisticsSiloAdjustmentsCommentCommentRoute,
|
||||
logisticsMaterialHelperConsumptionIndexRoute:
|
||||
logisticsMaterialHelperConsumptionIndexRoute,
|
||||
logisticsMaterialHelperSiloLinkIndexRoute:
|
||||
@@ -459,7 +528,9 @@ export const routeTree = rootRoute
|
||||
"/login",
|
||||
"/ocp/",
|
||||
"/(logistics)/materialHelper/",
|
||||
"/(logistics)/siloAdjustments/",
|
||||
"/(ocme)/cyclecount/",
|
||||
"/(logistics)/siloAdjustments/comment/$comment",
|
||||
"/(logistics)/materialHelper/consumption/",
|
||||
"/(logistics)/materialHelper/siloLink/"
|
||||
]
|
||||
@@ -472,7 +543,8 @@ export const routeTree = rootRoute
|
||||
"children": [
|
||||
"/_admin/modules",
|
||||
"/_admin/servers",
|
||||
"/_admin/settings"
|
||||
"/_admin/settings",
|
||||
"/_admin/users"
|
||||
]
|
||||
},
|
||||
"/_auth": {
|
||||
@@ -506,6 +578,10 @@ export const routeTree = rootRoute
|
||||
"filePath": "_admin/settings.tsx",
|
||||
"parent": "/_admin"
|
||||
},
|
||||
"/_admin/users": {
|
||||
"filePath": "_admin/users.tsx",
|
||||
"parent": "/_admin"
|
||||
},
|
||||
"/_auth/profile": {
|
||||
"filePath": "_auth/profile.tsx",
|
||||
"parent": "/_auth"
|
||||
@@ -524,9 +600,15 @@ export const routeTree = rootRoute
|
||||
"/(logistics)/materialHelper/": {
|
||||
"filePath": "(logistics)/materialHelper/index.tsx"
|
||||
},
|
||||
"/(logistics)/siloAdjustments/": {
|
||||
"filePath": "(logistics)/siloAdjustments/index.tsx"
|
||||
},
|
||||
"/(ocme)/cyclecount/": {
|
||||
"filePath": "(ocme)/cyclecount/index.tsx"
|
||||
},
|
||||
"/(logistics)/siloAdjustments/comment/$comment": {
|
||||
"filePath": "(logistics)/siloAdjustments/comment/$comment.tsx"
|
||||
},
|
||||
"/(logistics)/materialHelper/consumption/": {
|
||||
"filePath": "(logistics)/materialHelper/consumption/index.tsx"
|
||||
},
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
import Comment from "@/components/logistics/siloAdjustments/Comment";
|
||||
import { createFileRoute, redirect } from "@tanstack/react-router";
|
||||
|
||||
export const Route = createFileRoute(
|
||||
"/(logistics)/siloAdjustments/comment/$comment"
|
||||
)({
|
||||
beforeLoad: async () => {
|
||||
const auth = localStorage.getItem("auth_token");
|
||||
if (!auth) {
|
||||
throw redirect({
|
||||
to: "/login",
|
||||
search: {
|
||||
// Use the current location to power a redirect after login
|
||||
// (Do not use `router.state.resolvedLocation` as it can
|
||||
// potentially lag behind the actual current location)
|
||||
redirect: location.pathname + location.search,
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
// In a loader
|
||||
loader: ({ params }) => params.comment,
|
||||
// Or in a component
|
||||
component: RouteComponent,
|
||||
});
|
||||
|
||||
function RouteComponent() {
|
||||
const { comment } = Route.useParams();
|
||||
return (
|
||||
<div className="ml-20 mt-20">
|
||||
<Comment id={comment} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
28
frontend/src/routes/(logistics)/siloAdjustments/index.tsx
Normal file
28
frontend/src/routes/(logistics)/siloAdjustments/index.tsx
Normal file
@@ -0,0 +1,28 @@
|
||||
import SiloPage from "@/components/logistics/siloAdjustments/SiloPage";
|
||||
import { createFileRoute, redirect } from "@tanstack/react-router";
|
||||
|
||||
export const Route = createFileRoute("/(logistics)/siloAdjustments/")({
|
||||
component: RouteComponent,
|
||||
beforeLoad: async () => {
|
||||
const auth = localStorage.getItem("auth_token");
|
||||
if (!auth) {
|
||||
throw redirect({
|
||||
to: "/login",
|
||||
search: {
|
||||
// Use the current location to power a redirect after login
|
||||
// (Do not use `router.state.resolvedLocation` as it can
|
||||
// potentially lag behind the actual current location)
|
||||
redirect: location.pathname + location.search,
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
function RouteComponent() {
|
||||
return (
|
||||
<div>
|
||||
<SiloPage />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import {createFileRoute, redirect} from "@tanstack/react-router";
|
||||
import { createFileRoute, redirect } from "@tanstack/react-router";
|
||||
|
||||
// src/routes/_authenticated.tsx
|
||||
export const Route = createFileRoute("/_admin")({
|
||||
@@ -7,6 +7,12 @@ export const Route = createFileRoute("/_admin")({
|
||||
if (!auth) {
|
||||
throw redirect({
|
||||
to: "/login",
|
||||
search: {
|
||||
// Use the current location to power a redirect after login
|
||||
// (Do not use `router.state.resolvedLocation` as it can
|
||||
// potentially lag behind the actual current location)
|
||||
redirect: location.pathname + location.search,
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
10
frontend/src/routes/_admin/users.tsx
Normal file
10
frontend/src/routes/_admin/users.tsx
Normal file
@@ -0,0 +1,10 @@
|
||||
import UserPage from "@/components/admin/user/UserPage";
|
||||
import { createFileRoute } from "@tanstack/react-router";
|
||||
|
||||
export const Route = createFileRoute("/_admin/users")({
|
||||
component: RouteComponent,
|
||||
});
|
||||
|
||||
function RouteComponent() {
|
||||
return <UserPage />;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import {createFileRoute, redirect} from "@tanstack/react-router";
|
||||
import { createFileRoute, redirect } from "@tanstack/react-router";
|
||||
|
||||
// src/routes/_authenticated.tsx
|
||||
export const Route = createFileRoute("/_auth")({
|
||||
@@ -7,6 +7,12 @@ export const Route = createFileRoute("/_auth")({
|
||||
if (!auth) {
|
||||
throw redirect({
|
||||
to: "/login",
|
||||
search: {
|
||||
// Use the current location to power a redirect after login
|
||||
// (Do not use `router.state.resolvedLocation` as it can
|
||||
// potentially lag behind the actual current location)
|
||||
redirect: location.href,
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import {createFileRoute, redirect} from "@tanstack/react-router";
|
||||
import { createFileRoute, redirect } from "@tanstack/react-router";
|
||||
|
||||
import LoginForm from "@/components/auth/LoginForm";
|
||||
import { z } from "zod";
|
||||
|
||||
export const Route = createFileRoute("/login")({
|
||||
component: RouteComponent,
|
||||
@@ -12,6 +13,9 @@ export const Route = createFileRoute("/login")({
|
||||
});
|
||||
}
|
||||
},
|
||||
validateSearch: z.object({
|
||||
redirect: z.string().optional(),
|
||||
}),
|
||||
});
|
||||
|
||||
function RouteComponent() {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
export type LotType = {
|
||||
AV: number;
|
||||
Alias: string;
|
||||
LOT: number;
|
||||
lot: number;
|
||||
LabelOnlineID: number;
|
||||
MachineDescription: string;
|
||||
MachineID: number;
|
||||
|
||||
@@ -8,3 +8,13 @@ export interface Modules {
|
||||
upd_user: string;
|
||||
upd_date: Date;
|
||||
}
|
||||
|
||||
export interface SubModules {
|
||||
submodule_id: string;
|
||||
name: string;
|
||||
link: string;
|
||||
icon: string;
|
||||
moduleName: string;
|
||||
active: boolean;
|
||||
roles: string[];
|
||||
}
|
||||
|
||||
5
frontend/src/utils/formStuff/debugButton.tsx
Normal file
5
frontend/src/utils/formStuff/debugButton.tsx
Normal file
@@ -0,0 +1,5 @@
|
||||
import { Button } from "@/components/ui/button";
|
||||
|
||||
export const DebugButton = (data: any) => {
|
||||
return <Button onClick={() => console.log(data.data)}>Debug</Button>;
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user