Compare commits

...

206 Commits

Author SHA1 Message Date
51cc4aa370 feat(ocp): completly moved ocp to lst 2025-04-06 07:48:05 -05:00
95bebbde2b feat(silo adjustments): added in email if % wrong 2025-04-06 07:47:39 -05:00
85e3d46b2e refactor(ocp): added default time in for each printer to allow different delays 2025-04-06 07:46:47 -05:00
525de7dab2 test(test code): new test folder for testing stuff 2025-04-06 07:46:12 -05:00
1956ee313a ci(release): bump build number to 171 2025-04-05 11:44:13 -05:00
536899b6e7 ci(release): bump build number to 170 2025-04-04 22:11:49 -05:00
d9e60451f8 chore(release): 2.13.0 2025-04-04 22:10:30 -05:00
85577b291f feat(submodules and login redirect): submodules added and login redirect 2025-04-04 22:10:11 -05:00
f1abe7b33d feat(siloadjustments): added email for comments :D 2025-04-04 22:09:47 -05:00
9f26f2334f test(ocp): working on more migrations 2025-04-04 17:13:15 -05:00
a7818b4ca3 feat(notificaitons): fixed and corrections to get them working properly 2025-04-04 17:12:48 -05:00
99477bac19 refactor(materials): moved for better sturcture 2025-04-04 17:11:57 -05:00
5eacbb5ecf fix(datamart): added some fixed some 2025-04-04 17:11:32 -05:00
8b5698a839 feat(update all): added a new function to update all servers in a row. easier to walk away 2025-04-04 17:10:55 -05:00
ad5e77028d test(frontend): work on the frontend to have better admin 2025-04-04 17:09:30 -05:00
e1973e4da6 feat(submodules): to help with submodules of course 2025-04-04 17:08:47 -05:00
8194798a37 fix(database): correction to the printer modules 2025-04-04 17:08:25 -05:00
16e5413a90 ci(release): bump build number to 169 2025-04-04 16:35:09 -05:00
6065cccbd7 ci(release): bump build number to 168 2025-04-04 15:53:27 -05:00
9a5dc980f0 ci(release): bump build number to 167 2025-04-04 14:54:24 -05:00
23fa9f09dc ci(release): bump build number to 166 2025-04-04 14:33:49 -05:00
f1c9877686 ci(release): bump build number to 165 2025-04-04 12:19:58 -05:00
6ad49b704d ci(release): bump build number to 164 2025-04-04 12:17:20 -05:00
60cd6e551a ci(release): bump build number to 163 2025-04-04 06:51:21 -05:00
74445149b7 ci(release): bump build number to 162 2025-04-04 06:31:21 -05:00
2e05f79c72 ci(release): bump build number to 161 2025-04-03 20:22:10 -05:00
13df4af860 ci(release): bump build number to 160 2025-04-03 17:31:45 -05:00
6bd1bebe33 ci(release): bump build number to 159 2025-04-03 11:49:47 -05:00
99fd875dbb ci(release): bump build number to 158 2025-04-03 11:03:05 -05:00
17d7e54b7a ci(release): bump build number to 157 2025-04-03 09:56:19 -05:00
498c1626a1 ci(release): bump build number to 156 2025-04-03 09:43:51 -05:00
6180f61d08 ci(release): bump build number to 155 2025-04-03 08:16:10 -05:00
3e4d8b260c ci(release): bump build number to 154 2025-04-03 07:44:37 -05:00
fa9e5dd70f ci(release): bump build number to 153 2025-04-03 07:32:37 -05:00
b9397c029f fix(tcp): added in a catch if ocme is not active and we dont have a zebra camera 2025-04-03 06:08:15 -05:00
7e34d42fda style(ocme): format changes 2025-04-03 06:07:41 -05:00
96807bf77e build(builds): changes to the build system 2025-04-03 06:07:21 -05:00
7a6911c694 ci(release): bump build number to 152 2025-04-03 05:56:35 -05:00
05b22d7cb7 ci(release): bump build number to 151 2025-04-03 05:52:26 -05:00
6b5f7e0bcd ci(release): bump build number to 150 2025-04-03 05:27:24 -05:00
858bf986d9 ci(release): bump build number to 149 2025-04-03 05:03:16 -05:00
2cc81a5b07 chore(release): bump build number to 148 2025-04-02 21:27:33 -05:00
52e3e1b4a1 chore(release): 2.12.0 2025-04-02 21:26:45 -05:00
d27611d035 feat(servers): all servers in v2 meow 2025-04-02 21:26:32 -05:00
f771db6034 fix(ocp): delivery changes to happen after bookin is done 2025-04-02 21:26:15 -05:00
4f3b5d75a2 refactor(ocme): crashing for no reason added ?? 2025-04-02 21:25:49 -05:00
a1f62a3e51 fix(ti intergraion): chagnes to the special instructions 2025-04-02 21:25:30 -05:00
de0ee3a61c fix(sendmail): if server not installed just stop 2025-04-02 21:25:07 -05:00
b48dd8fa15 style(auth): format changes to the new config only 2025-04-02 21:24:51 -05:00
3355eb389c test(services): testing remove restart and stop 2025-04-02 21:24:23 -05:00
b2683d0429 feat(datamart): total inv migrated over 2025-04-02 21:23:42 -05:00
7e484a0f90 chore(release): bump build number to 147 2025-04-02 21:02:05 -05:00
77abaed60e chore(release): bump build number to 146 2025-04-02 16:38:47 -05:00
d10770bc49 chore(release): bump build number to 145 2025-04-02 15:29:10 -05:00
1fee4b719b chore(release): bump build number to 144 2025-04-02 14:58:43 -05:00
1dce3dccdc chore(release): bump build number to 143 2025-04-02 14:50:28 -05:00
3babf8a749 chore(release): bump build number to 142 2025-04-02 13:17:42 -05:00
29c9f2d1be chore(release): bump build number to 141 2025-04-02 12:17:34 -05:00
459b0f287c chore(release): bump build number to 140 2025-04-02 08:45:48 -05:00
7535e15337 chore(release): bump build number to 139 2025-04-02 08:15:43 -05:00
68dac0dd28 chore(release): bump build number to 138 2025-04-02 07:56:22 -05:00
f442cedff2 chore(release): bump build number to 137 2025-04-02 07:51:35 -05:00
63e005b790 feat(servers): added in jci lima sherman 2025-04-01 18:50:35 -05:00
814861e59c feat(ocp): added dual printing back in 2025-04-01 18:50:03 -05:00
dd62ceb133 fix(updater): fixed the iowa2 server so it has the correct port 2025-04-01 18:49:48 -05:00
e335225807 build(update server): added cheaters in to get rid of the other service to readd it 2025-04-01 18:49:27 -05:00
3e54685a7e chore(release): bump build number to 136 2025-04-01 16:30:06 -05:00
f481197d6e feat(new server): added mcd to the server setup 2025-04-01 16:23:13 -05:00
053c05c1a7 fix(perms): fixed the location for the test update 2025-04-01 16:22:52 -05:00
8bdbc4995c refactor(ocp): more work on perfecting dyco and labeling 2025-04-01 16:22:21 -05:00
bc2336e46d refactor(compile): changes to keep the last 20 builds 2025-04-01 16:22:01 -05:00
544e82c01d fix(update server missing migrate): missing 2025-04-01 16:21:15 -05:00
44507d41c4 feat(datamart): initial get active query migrated 2025-04-01 16:20:18 -05:00
ee3026fa7c fix(ocme): cycle count typos 2025-04-01 16:19:25 -05:00
5c642805b1 feat(notifications): migrated all from v1 2025-04-01 16:18:48 -05:00
0d06dae6de chore(release): bump build number to 135 2025-04-01 13:37:46 -05:00
8a639ceaf8 chore(release): bump build number to 134 2025-04-01 10:14:50 -05:00
8c6dc5f690 chore(release): bump build number to 133 2025-04-01 09:50:03 -05:00
16b39fd386 chore(release): bump build number to 132 2025-03-31 20:36:09 -05:00
075bba95ee chore(release): bump build number to 131 2025-03-31 20:33:34 -05:00
6ec9f5827c chore(release): bump build number to 130 2025-03-31 10:23:34 -05:00
93941723cc chore(release): bump build number to 129 2025-03-31 10:18:08 -05:00
fb41fb1dd1 chore(release): bump build number to 128 2025-03-30 18:51:23 -05:00
6d5bcde88e chore(release): bump build number to 127 2025-03-30 18:48:18 -05:00
1156bbd223 chore(release): bump build number to 126 2025-03-30 10:13:01 -05:00
bfd4aec4eb chore(release): 2.11.0 2025-03-30 10:12:17 -05:00
63b1151cb7 fix(misc): work on ocp to improve the errors that were missed and better logging 2025-03-30 10:11:58 -05:00
a5dee58223 refactor(server): removed console logs 2025-03-30 10:11:29 -05:00
9784072aab refactor(format changes): changes to the file formats to match across computers 2025-03-30 10:10:53 -05:00
f9096b54f5 fix(admin auth): added in role change for v1 2025-03-30 10:10:01 -05:00
11e5cf4d86 refactor(lst): added huston backin 2025-03-30 10:09:32 -05:00
a647d05d3b chore(release): bump build number to 125 2025-03-30 10:03:20 -05:00
098c477119 chore(release): bump build number to 124 2025-03-30 09:44:19 -05:00
3228ad7892 feat(lst): script added for the test server to readd the permissions once it boots up 2025-03-30 08:41:55 -05:00
c27ad7cf6a refactor(lst): added in a removal of old files so we can keep the server clean 2025-03-30 08:41:26 -05:00
a48d4bd5af feat(auth): admin user updates added
if a password change happens then an email will be sent to the user.
2025-03-30 08:40:49 -05:00
09c0825194 chore(release): bump build number to 123 2025-03-30 05:09:52 -05:00
28fbf2c1e4 chore(release): bump build number to 122 2025-03-29 18:26:57 -05:00
af5dc9266f chore(release): bump build number to 121 2025-03-29 12:16:23 -05:00
b903c8ee2d chore(release): bump build number to 120 2025-03-29 12:15:02 -05:00
035eda9aa8 chore(release): bump build number to 119 2025-03-29 12:13:16 -05:00
1f7c33d871 chore(release): bump build number to 118 2025-03-29 07:54:44 -05:00
d046c4ea41 chore(release): bump build number to 117 2025-03-29 07:39:34 -05:00
88258baf9d chore(release): bump build number to 116 2025-03-28 14:50:34 -05:00
82acfcc4a9 chore(release): bump build number to 116 2025-03-28 14:20:37 -05:00
ba3d721940 refactor(ocp): lots of work for rfid and dyco contorl 2025-03-27 21:12:22 -05:00
27d6b6e884 refactor(ocme): added new error in posting where we know when the pallet is not instock 2025-03-27 21:11:42 -05:00
2c8d1fb710 fix(logger): changes to get the most recent verse aged 2025-03-27 21:10:57 -05:00
b5de6445b3 feat(rfid): work on the readers and there functions 2025-03-27 21:08:05 -05:00
f9f68ce969 refactor(logger): changed log level to be in the env file vs hardcoded 2025-03-27 21:07:15 -05:00
0ced135ec3 feat(updater): added in a delete function for the server side 2025-03-27 21:06:45 -05:00
7b1c6e1361 refactor(ocp): finished the dashboard and move logs and labels to a tab style 2025-03-27 21:06:25 -05:00
e3ba45ae13 fix(ocme): fixed to make sure we can always just update a runnning nunmber 2025-03-27 21:05:49 -05:00
ac7859fda3 chore(release): bump build number to 115 2025-03-27 20:21:24 -05:00
fb31ae79d1 chore(release): bump build number to 114 2025-03-27 18:50:04 -05:00
ff1dfdde68 chore(release): bump build number to 113 2025-03-27 18:44:11 -05:00
f0b9bd599a chore(release): bump build number to 112 2025-03-27 18:42:43 -05:00
f3103d8c1a chore(release): bump build number to 111 2025-03-27 18:22:13 -05:00
d557728fa2 chore(release): bump build number to 110 2025-03-27 17:26:30 -05:00
d58cb5286e chore(release): bump build number to 109 2025-03-27 17:03:39 -05:00
7d4733896e chore(release): bump build number to 108 2025-03-27 16:48:14 -05:00
175c7226ed chore(release): bump build number to 107 2025-03-27 15:00:51 -05:00
c32547ceb8 chore(release): bump build number to 106 2025-03-27 14:47:42 -05:00
a01c0566c2 chore(release): bump build number to 105 2025-03-27 14:46:43 -05:00
ca4106945b chore(release): bump build number to 104 2025-03-27 14:45:41 -05:00
1386e0f00f chore(release): bump build number to 103 2025-03-27 14:44:10 -05:00
290f20b86b chore(release): bump build number to 102 2025-03-27 14:33:34 -05:00
52171c87fc chore(release): bump build number to 101 2025-03-27 14:31:22 -05:00
c474536992 chore(release): bump build number to 100 2025-03-27 14:07:33 -05:00
600a989226 chore(release): bump build number to 99 2025-03-27 11:55:35 -05:00
ea7801fccf chore(release): bump build number to 98 2025-03-27 10:59:53 -05:00
c03b61f48a chore(release): bump build number to 97 2025-03-27 10:33:59 -05:00
ca552d5587 chore(release): bump build number to 96 2025-03-27 10:12:23 -05:00
278c5538bc chore(release): bump build number to 95 2025-03-27 09:21:15 -05:00
f39ae0f590 chore(release): bump build number to 94 2025-03-27 09:10:01 -05:00
b4e0f4c666 chore(release): bump build number to 93 2025-03-26 22:12:03 -05:00
db66302415 chore(release): 2.10.0 2025-03-26 22:11:27 -05:00
90e9bb0ff6 refactor(rfid): refactored the way the wrapper works to indlude backup dyco plan 2025-03-26 22:10:39 -05:00
bd11feb136 refactor(rfid): refactored station 3 (lines) and complete logic 2025-03-26 22:10:05 -05:00
96e7f742fe refactor(ocme): removed some info logs as ocme calls alot 2025-03-26 22:09:23 -05:00
eb051d51f2 feat(notify): intial nofity system added to monitor crashes and rfid wrapper 2025-03-26 22:08:53 -05:00
7a1a4773e7 feat(ocp): create and book in plus dyco controller implemented 2025-03-26 22:07:19 -05:00
878e650e62 chore(release): bump build number to 92 2025-03-26 22:05:21 -05:00
a31e7ea163 chore(release): bump build number to 91 2025-03-26 16:17:53 -05:00
04aa943920 chore(release): bump build number to 90 2025-03-26 16:00:56 -05:00
af076b8e27 chore(release): bump build number to 89 2025-03-26 15:39:57 -05:00
c0a0589b3c chore(release): bump build number to 88 2025-03-26 15:19:55 -05:00
509ef84726 chore(release): bump build number to 87 2025-03-26 15:18:53 -05:00
5ab813f378 chore(release): bump build number to 86 2025-03-26 12:44:17 -05:00
5d61eb879e chore(release): bump build number to 85 2025-03-26 12:42:58 -05:00
2d4b1db5f4 fix(logistics): correction to the lane grab 2025-03-26 09:16:16 -05:00
58f7b4322d feat(logistics): added in return material by lane name and gets lane id 2025-03-26 08:36:47 -05:00
3b5e82fdc1 feat(ocp): added wrappercard into the mix 2025-03-25 18:57:00 -05:00
f9cd3fb881 feat(ocp): prodlink check added 2025-03-25 18:56:36 -05:00
51267f5202 fix(ocme): fixed the camera routes 2025-03-25 18:55:57 -05:00
ceaa25f31e feat(ocp): added labeling logs in 2025-03-25 18:55:23 -05:00
416254353c chore(release): bump build number to 84 2025-03-25 18:21:47 -05:00
7f946c095b chore(release): bump build number to 83 2025-03-25 18:03:32 -05:00
c2aa69ab0a chore(release): bump build number to 82 2025-03-25 18:02:14 -05:00
250988800e chore(release): bump build number to 81 2025-03-25 17:57:13 -05:00
cacfd6d2e0 chore(release): bump build number to 80 2025-03-25 17:49:07 -05:00
8d2721b0c2 chore(release): bump build number to 79 2025-03-25 17:44:41 -05:00
36cdc7b4bf chore(release): bump build number to 78 2025-03-25 17:39:26 -05:00
4d4d6fc7a4 chore(release): bump build number to 77 2025-03-25 15:48:28 -05:00
030f9f9aac refactor(ocp): moved printers to there own folder to keep everything clean 2025-03-25 13:39:39 -05:00
9e9a56cbb1 feat(ocp): add lots with scroll view was added 2025-03-25 13:39:18 -05:00
b01980e1c5 fix(ocme): fixed some import errors 2025-03-25 12:48:18 -05:00
fe0c500dcf feat(server): clearn up code 2025-03-25 12:47:52 -05:00
8a040d15db fix(servers): fixed the weird conflict import that happened 2025-03-25 12:47:36 -05:00
f90066c090 feat(ocp): added in printers get and add 2025-03-25 12:47:15 -05:00
04eb2e3e14 refactor(tcpserver): just the tcp server doing something 2025-03-25 07:58:37 -05:00
90fb0d364d Merge branch 'main' of https://git.tuffraid.net/cowch/lstV2 2025-03-25 07:57:55 -05:00
e6e1cecce3 refactor(ocme): corrections to endpoints to work with ocnme as intneeded 2025-03-25 07:54:58 -05:00
73aa95a693 refactor(ocme): cleaup on pickedup 2025-03-25 07:54:22 -05:00
b9f19095cb refactor(ocme): clean up on the getInfo endpoint 2025-03-25 07:54:00 -05:00
dcb56d4274 fix(ocme): corrections to posting data for the response was added 2025-03-25 07:53:30 -05:00
bc1821132e feat(ocme): manual camera trigger for the wrapper added 2025-03-25 07:52:40 -05:00
2551d6c907 refactor(updateserver): removed ocme from starting back up as it was migrated 2025-03-25 07:41:10 -05:00
adf0880659 refactor(server): changed to log only when in dev, and removed the redirect of the url 2025-03-25 07:40:15 -05:00
5149de3199 ci(lst): changes made to the settings file to work across all pvs 2025-03-25 07:39:32 -05:00
c71b514d9a refactor(frontend): prettier change to formatting 2025-03-25 07:27:45 -05:00
9254e52808 chore(release): bump build number to 76 2025-03-25 06:17:31 -05:00
b8c028a6c1 chore(release): bump build number to 75 2025-03-24 20:20:55 -05:00
529e922485 chore(release): bump build number to 74 2025-03-24 20:13:07 -05:00
5201012235 chore(release): bump build number to 73 2025-03-24 20:08:59 -05:00
abe53b8f5d chore(release): bump build number to 72 2025-03-24 20:06:15 -05:00
836f3e294b chore(release): bump build number to 71 2025-03-24 19:56:03 -05:00
96abef762b chore(release): bump build number to 70 2025-03-24 19:40:39 -05:00
2c227f9428 chore(release): bump build number to 69 2025-03-24 18:33:12 -05:00
46647687dc chore(release): bump build number to 68 2025-03-24 18:23:24 -05:00
cb01ef1af1 chore(release): bump build number to 67 2025-03-24 17:16:23 -05:00
b3b5fcec65 chore(release): bump build number to 66 2025-03-24 17:14:25 -05:00
3a4dc47a36 chore(release): bump build number to 65 2025-03-24 17:06:23 -05:00
63177b523e chore(release): bump build number to 64 2025-03-24 17:00:20 -05:00
e1cad027d2 chore(release): bump build number to 63 2025-03-24 16:42:53 -05:00
c1cc355f4f chore(release): bump build number to 62 2025-03-24 16:40:50 -05:00
5ed67f3fc0 chore(release): bump build number to 61 2025-03-24 16:28:32 -05:00
57e82d2360 chore(release): bump build number to 60 2025-03-24 16:26:04 -05:00
9395ec6cd4 chore(release): bump build number to 59 2025-03-24 15:50:29 -05:00
0475bb30f9 chore(release): bump build number to 58 2025-03-24 15:49:37 -05:00
6843368c36 chore(release): bump build number to 57 2025-03-24 15:47:16 -05:00
335ea2deca chore(release): bump build number to 56 2025-03-24 15:39:33 -05:00
96814c1115 Merge branch 'main' of https://git.tuffraid.net/cowch/lstV2 2025-03-24 15:31:35 -05:00
6dd9ed848b test(ocme): lots of changes to get it working in production 2025-03-24 15:31:31 -05:00
0c5fc1dfb0 chore(release): bump build number to 55 2025-03-24 15:28:10 -05:00
5886bea85d chore(release): bump build number to 52 2025-03-24 11:43:52 -05:00
275 changed files with 45117 additions and 2322 deletions

1
.gitignore vendored
View File

@@ -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

View File

@@ -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
View File

@@ -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
}
}

View File

@@ -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)

View 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");

View 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;

View File

@@ -0,0 +1 @@
ALTER TABLE "printers" ALTER COLUMN "port" DROP NOT NULL;

View File

@@ -0,0 +1,2 @@
DROP INDEX "humanReadableId";--> statement-breakpoint
CREATE UNIQUE INDEX "humanReadableId" ON "printers" USING btree ("humanReadableId");

View File

@@ -0,0 +1,4 @@
CREATE TABLE "prodlabels" (
"label_id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"runningNr" integer NOT NULL
);

View 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");

View 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");

View 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");

View File

@@ -0,0 +1,2 @@
ALTER TABLE "printers" ALTER COLUMN "lastTimePrinted" SET DATA TYPE timestamp;--> statement-breakpoint
ALTER TABLE "printers" ADD COLUMN "printDelay" numeric;

View 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;

View File

@@ -0,0 +1 @@
ALTER TABLE "printers" ALTER COLUMN "lastTimePrinted" SET DATA TYPE timestamp with time zone;

View File

@@ -0,0 +1 @@
ALTER TABLE "printers" DROP COLUMN "lastTimePrinted";

View File

@@ -0,0 +1 @@
ALTER TABLE "printers" DROP COLUMN "printDelay";

View 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");

View 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");

View File

@@ -0,0 +1 @@
DROP INDEX "subModule_name";

View 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;

View 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'
);

View 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";

View File

@@ -0,0 +1 @@
ALTER TABLE "siloAdjustments" ADD COLUMN "commentKey" text;

View File

@@ -0,0 +1 @@
CREATE UNIQUE INDEX "subModule_name" ON "subModules" USING btree ("name");

View File

@@ -0,0 +1 @@
ALTER TABLE "subModules" ADD COLUMN "icon" text;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -183,6 +183,160 @@
"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
}
]
}

View 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);

View File

@@ -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),
]
);

View 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);

View 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);

View File

@@ -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",

View 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("lsiloAdjust_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);

View File

@@ -0,0 +1,46 @@
import {
text,
pgTable,
timestamp,
boolean,
uuid,
uniqueIndex,
jsonb,
} from "drizzle-orm/pg-core";
import { createSelectSchema } from "drizzle-zod";
import { modules } from "./modules.js";
//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;

File diff suppressed because it is too large Load Diff

View File

@@ -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",

View File

@@ -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>
);
}

View File

@@ -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>
);
}

View File

@@ -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>
);
}

View File

@@ -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>

View File

@@ -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>

View 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>
);
}

View 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>
);
}

View 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>
);
}

View File

@@ -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;

View File

@@ -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>
)}

View File

@@ -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>

View 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>
);
}

View File

@@ -0,0 +1,14 @@
import { LstCard } from "@/components/extendedUI/LstCard";
import { CardHeader } from "@/components/ui/card";
export default function SiloCard(data: any) {
const silo = data.silo;
return (
<LstCard>
<CardHeader>{silo.Description}</CardHeader>
<div>
<hr />
</div>
</LstCard>
);
}

View File

@@ -0,0 +1,26 @@
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-row gap-2">
{data?.map((s: any) => <SiloCard silo={s} />)}
</div>
);
}

View 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>
);
}

View File

@@ -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>
);
})}

View File

@@ -1,23 +1,30 @@
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,
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 +47,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,39 +89,50 @@ 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>

View File

@@ -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,13 +65,11 @@ 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"];
if (user && roles.includes(user.role)) {
@@ -83,140 +89,169 @@ 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}>
{data?.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>
);
}

View File

@@ -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>

View File

@@ -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}`,
};
}

View File

@@ -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>
);
}

View File

@@ -1,28 +1,53 @@
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");
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 && (
<div>
<WrapperManualTrigger />
</div>
)}
<div>
<PrinterStatus />
</div>
</div>
</div>
</div>

View File

@@ -1,6 +1,14 @@
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";
let printerCols = [
{
@@ -19,34 +27,37 @@ let printerCols = [
export default function PrinterStatus() {
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-[300px]">
<p className="text-center">Printer Status</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>
<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>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</ScrollArea>
</LstCard>
);
}

View File

@@ -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>
);
};

View 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 }

View File

@@ -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}

View 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 };

View 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 }

View File

@@ -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);
}

View 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: [] });
}
},
}));

View File

@@ -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"
},

View File

@@ -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>
);
}

View 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>
);
}

View File

@@ -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,
},
});
}
},

View 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 />;
}

View File

@@ -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,
},
});
}
},

View File

@@ -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() {

View File

@@ -1,7 +1,7 @@
export type LotType = {
AV: number;
Alias: string;
LOT: number;
lot: number;
LabelOnlineID: number;
MachineDescription: string;
MachineID: number;

View File

@@ -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[];
}

View 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>;
};

View File

@@ -0,0 +1,32 @@
//import { Input } from "@/components/ui/input";
//import { Label } from "@radix-ui/react-dropdown-menu";
// export const FormInput = (form: any, label: string) => {
// // <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">{label}</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>
// // );
// // }}
// // />;
// };

Some files were not shown because too many files have changed in this diff Show More