Compare commits
37 Commits
8fb06c71d3
...
e597968777
| Author | SHA1 | Date | |
|---|---|---|---|
| e597968777 | |||
| bbd7a17144 | |||
| 5945ace9f2 | |||
| 316b27e3e0 | |||
| 7165c959b9 | |||
| ae7e3fd54e | |||
| 7ec5c5beb0 | |||
| c9aa41ab00 | |||
| 4696835c65 | |||
| 2d3f308877 | |||
| 3d083986ae | |||
| 92b47f03d9 | |||
| 3b8f18093e | |||
| 1cd1d3a3e9 | |||
| 8324fffeb6 | |||
| 354f3260a5 | |||
| ab5af4deac | |||
| 7a15b160ac | |||
| ca0ba7fe59 | |||
| 0914b53341 | |||
| 34b80cf236 | |||
| 196ea00972 | |||
| 807a4ca699 | |||
| d98a659262 | |||
| 6dd5f4b61f | |||
| 751b9d5701 | |||
| b0634d9427 | |||
| 8a143fbb19 | |||
| 8b72a1b47e | |||
| f4c44fb02b | |||
| 03aa7e5aee | |||
| f035e6f14a | |||
| 227e2aa00c | |||
| 4a48dd2bb5 | |||
| 9796947db5 | |||
| 1e02d4fa4f | |||
| 26ea8d5e89 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -148,3 +148,4 @@ dist
|
|||||||
.yarn/install-state.gz
|
.yarn/install-state.gz
|
||||||
.pnp.*
|
.pnp.*
|
||||||
|
|
||||||
|
backend-0.1.3.zip
|
||||||
|
|||||||
2
database/migrations/0023_wealthy_marvel_boy.sql
Normal file
2
database/migrations/0023_wealthy_marvel_boy.sql
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE "logs" ADD COLUMN "checked" boolean DEFAULT false;--> statement-breakpoint
|
||||||
|
ALTER TABLE "logs" ADD COLUMN "checkedAt" timestamp;
|
||||||
9
database/migrations/0024_curved_venom.sql
Normal file
9
database/migrations/0024_curved_venom.sql
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
CREATE TABLE "manualPrinting" (
|
||||||
|
"print_id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||||
|
"line" integer,
|
||||||
|
"printReason" text NOT NULL,
|
||||||
|
"initials" text NOT NULL,
|
||||||
|
"additionalComments" text NOT NULL,
|
||||||
|
"add_date" timestamp DEFAULT now(),
|
||||||
|
"add_user" text
|
||||||
|
);
|
||||||
1087
database/migrations/meta/0023_snapshot.json
Normal file
1087
database/migrations/meta/0023_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1144
database/migrations/meta/0024_snapshot.json
Normal file
1144
database/migrations/meta/0024_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -162,6 +162,20 @@
|
|||||||
"when": 1742156466912,
|
"when": 1742156466912,
|
||||||
"tag": "0022_amused_true_believers",
|
"tag": "0022_amused_true_believers",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 23,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1742346003832,
|
||||||
|
"tag": "0023_wealthy_marvel_boy",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 24,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1742408812383,
|
||||||
|
"tag": "0024_curved_venom",
|
||||||
|
"breakpoints": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -10,6 +10,8 @@ export const logs = pgTable(
|
|||||||
username: text("username").default("LST_Serivce"),
|
username: text("username").default("LST_Serivce"),
|
||||||
service: text("service").notNull().default("system"),
|
service: text("service").notNull().default("system"),
|
||||||
message: text("message").notNull(),
|
message: text("message").notNull(),
|
||||||
|
checked: boolean("checked").default(false),
|
||||||
|
checkedAt: timestamp("checkedAt"),
|
||||||
created_at: timestamp("add_Date").defaultNow(),
|
created_at: timestamp("add_Date").defaultNow(),
|
||||||
},
|
},
|
||||||
(table) => [
|
(table) => [
|
||||||
|
|||||||
20
database/schema/ocpManualPrint.ts
Normal file
20
database/schema/ocpManualPrint.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import {text, pgTable, timestamp, uuid, integer} from "drizzle-orm/pg-core";
|
||||||
|
import {createInsertSchema, createSelectSchema} from "drizzle-zod";
|
||||||
|
import {z} from "zod";
|
||||||
|
|
||||||
|
export const manualPrinting = pgTable("manualPrinting", {
|
||||||
|
print_id: uuid("print_id").defaultRandom().primaryKey(),
|
||||||
|
line: integer("line"),
|
||||||
|
printReason: text("printReason").notNull(),
|
||||||
|
initials: text("initials").notNull(),
|
||||||
|
additionalComments: text("additionalComments").notNull(),
|
||||||
|
add_date: timestamp("add_date").defaultNow(),
|
||||||
|
add_user: text("add_user"),
|
||||||
|
});
|
||||||
|
|
||||||
|
// 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(manualPrinting);
|
||||||
50
frontend/package-lock.json
generated
50
frontend/package-lock.json
generated
@@ -16,6 +16,7 @@
|
|||||||
"@radix-ui/react-dropdown-menu": "^2.1.6",
|
"@radix-ui/react-dropdown-menu": "^2.1.6",
|
||||||
"@radix-ui/react-label": "^2.1.2",
|
"@radix-ui/react-label": "^2.1.2",
|
||||||
"@radix-ui/react-popover": "^1.1.6",
|
"@radix-ui/react-popover": "^1.1.6",
|
||||||
|
"@radix-ui/react-select": "^2.1.6",
|
||||||
"@radix-ui/react-separator": "^1.1.2",
|
"@radix-ui/react-separator": "^1.1.2",
|
||||||
"@radix-ui/react-slot": "^1.1.2",
|
"@radix-ui/react-slot": "^1.1.2",
|
||||||
"@radix-ui/react-tabs": "^1.1.3",
|
"@radix-ui/react-tabs": "^1.1.3",
|
||||||
@@ -1152,6 +1153,12 @@
|
|||||||
"node": ">= 8"
|
"node": ">= 8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@radix-ui/number": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-V3gRzhVNU1ldS5XhAPTom1fOIo4ccrjjJgmE+LI2h/WaFpHmx0MQApT+KZHnx8abG6Avtfcz4WoEciMnpFT3HQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@radix-ui/primitive": {
|
"node_modules/@radix-ui/primitive": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.1.tgz",
|
||||||
@@ -1722,6 +1729,49 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@radix-ui/react-select": {
|
||||||
|
"version": "2.1.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.1.6.tgz",
|
||||||
|
"integrity": "sha512-T6ajELxRvTuAMWH0YmRJ1qez+x4/7Nq7QIx7zJ0VK3qaEWdnWpNbEDnmWldG1zBDwqrLy5aLMUWcoGirVj5kMg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@radix-ui/number": "1.1.0",
|
||||||
|
"@radix-ui/primitive": "1.1.1",
|
||||||
|
"@radix-ui/react-collection": "1.1.2",
|
||||||
|
"@radix-ui/react-compose-refs": "1.1.1",
|
||||||
|
"@radix-ui/react-context": "1.1.1",
|
||||||
|
"@radix-ui/react-direction": "1.1.0",
|
||||||
|
"@radix-ui/react-dismissable-layer": "1.1.5",
|
||||||
|
"@radix-ui/react-focus-guards": "1.1.1",
|
||||||
|
"@radix-ui/react-focus-scope": "1.1.2",
|
||||||
|
"@radix-ui/react-id": "1.1.0",
|
||||||
|
"@radix-ui/react-popper": "1.2.2",
|
||||||
|
"@radix-ui/react-portal": "1.1.4",
|
||||||
|
"@radix-ui/react-primitive": "2.0.2",
|
||||||
|
"@radix-ui/react-slot": "1.1.2",
|
||||||
|
"@radix-ui/react-use-callback-ref": "1.1.0",
|
||||||
|
"@radix-ui/react-use-controllable-state": "1.1.0",
|
||||||
|
"@radix-ui/react-use-layout-effect": "1.1.0",
|
||||||
|
"@radix-ui/react-use-previous": "1.1.0",
|
||||||
|
"@radix-ui/react-visually-hidden": "1.1.2",
|
||||||
|
"aria-hidden": "^1.2.4",
|
||||||
|
"react-remove-scroll": "^2.6.3"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"@types/react-dom": "*",
|
||||||
|
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||||
|
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@types/react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@radix-ui/react-separator": {
|
"node_modules/@radix-ui/react-separator": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.2.tgz",
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
"@radix-ui/react-dropdown-menu": "^2.1.6",
|
"@radix-ui/react-dropdown-menu": "^2.1.6",
|
||||||
"@radix-ui/react-label": "^2.1.2",
|
"@radix-ui/react-label": "^2.1.2",
|
||||||
"@radix-ui/react-popover": "^1.1.6",
|
"@radix-ui/react-popover": "^1.1.6",
|
||||||
|
"@radix-ui/react-select": "^2.1.6",
|
||||||
"@radix-ui/react-separator": "^1.1.2",
|
"@radix-ui/react-separator": "^1.1.2",
|
||||||
"@radix-ui/react-slot": "^1.1.2",
|
"@radix-ui/react-slot": "^1.1.2",
|
||||||
"@radix-ui/react-tabs": "^1.1.3",
|
"@radix-ui/react-tabs": "^1.1.3",
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import {useQuery} from "@tanstack/react-query";
|
|||||||
import {useRouter} from "@tanstack/react-router";
|
import {useRouter} from "@tanstack/react-router";
|
||||||
import {format} from "date-fns";
|
import {format} from "date-fns";
|
||||||
import UpdateServer from "./UpdateServer";
|
import UpdateServer from "./UpdateServer";
|
||||||
|
import {adminUrlCheck} from "@/utils/adminUrlCheck";
|
||||||
|
|
||||||
export type Servers = {
|
export type Servers = {
|
||||||
server_id?: string;
|
server_id?: string;
|
||||||
@@ -85,9 +86,7 @@ export default function ServerPage() {
|
|||||||
{format(server.lastUpdated, "MM/dd/yyyy hh:mm")}
|
{format(server.lastUpdated, "MM/dd/yyyy hh:mm")}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className="font-medium">
|
<TableCell className="font-medium">
|
||||||
{window.location.host.split(":")[0] === "localhost" && (
|
{adminUrlCheck() && <UpdateServer server={server} token={token as string} />}
|
||||||
<UpdateServer server={server} token={token as string} />
|
|
||||||
)}
|
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ export default function SettingsPage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LstCard className="m-2 flex place-content-center w-dvh">
|
<LstCard className="m-2 flex place-content-center w-fit">
|
||||||
<Table>
|
<Table>
|
||||||
<TableHeader>
|
<TableHeader>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
|
|||||||
@@ -61,8 +61,10 @@ const LoginForm = () => {
|
|||||||
|
|
||||||
// Store token in localStorage
|
// Store token in localStorage
|
||||||
// localStorage.setItem("auth_token", data.data.token);
|
// localStorage.setItem("auth_token", data.data.token);
|
||||||
|
const prod = btoa(`${value.username.toLowerCase()}:${value.password}`);
|
||||||
|
const prodUser = {...data.user, prod: prod};
|
||||||
|
|
||||||
setSession(data.user, data.token);
|
setSession(prodUser, data.token);
|
||||||
toast.success(`You are logged in as ${data.user.username}`);
|
toast.success(`You are logged in as ${data.user.username}`);
|
||||||
router.navigate({to: "/"});
|
router.navigate({to: "/"});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ const items = [
|
|||||||
title: "One Click Print",
|
title: "One Click Print",
|
||||||
url: "/ocp",
|
url: "/ocp",
|
||||||
icon: Printer,
|
icon: Printer,
|
||||||
role: ["systemAdmin"],
|
role: ["viwer"],
|
||||||
module: "ocp",
|
module: "ocp",
|
||||||
active: true,
|
active: true,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import {Button} from "@/components/ui/button";
|
|||||||
import {CardHeader} from "@/components/ui/card";
|
import {CardHeader} from "@/components/ui/card";
|
||||||
import {Input} from "@/components/ui/input";
|
import {Input} from "@/components/ui/input";
|
||||||
import {Label} from "@/components/ui/label";
|
import {Label} from "@/components/ui/label";
|
||||||
|
import {useSessionStore} from "@/lib/store/sessionStore";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import {useState} from "react";
|
import {useState} from "react";
|
||||||
|
|
||||||
@@ -12,7 +13,7 @@ import {toast} from "sonner";
|
|||||||
export default function ConsumeMaterial() {
|
export default function ConsumeMaterial() {
|
||||||
const {register: register1, handleSubmit: handleSubmit1, reset} = useForm();
|
const {register: register1, handleSubmit: handleSubmit1, reset} = useForm();
|
||||||
const [submitting, setSubmitting] = useState(false);
|
const [submitting, setSubmitting] = useState(false);
|
||||||
const token = localStorage.getItem("auth_token");
|
const {token} = useSessionStore();
|
||||||
|
|
||||||
const handleConsume = async (data: any) => {
|
const handleConsume = async (data: any) => {
|
||||||
setSubmitting(!submitting);
|
setSubmitting(!submitting);
|
||||||
|
|||||||
@@ -1,5 +1,92 @@
|
|||||||
import {LstCard} from "@/components/extendedUI/LstCard";
|
import {LstCard} from "@/components/extendedUI/LstCard";
|
||||||
|
import {CardHeader} from "@/components/ui/card";
|
||||||
|
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";
|
||||||
|
|
||||||
|
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: "reprint", label: "Reprint"}, // removing the reprint button for now until repritning is working as intended
|
||||||
|
];
|
||||||
export default function LabelLog() {
|
export default function LabelLog() {
|
||||||
return <LstCard className="m-2 p-2"> label logs here</LstCard>;
|
const {data, isError, error, isLoading} = useQuery(getlabels("4"));
|
||||||
|
//const {user} = useSessionStore();
|
||||||
|
//const {settings} = useSettingStore();
|
||||||
|
//const server = settings.filter((n) => n.name === "server")[0]?.value || "";
|
||||||
|
|
||||||
|
//const roles = ["admin", "manager", "operator"];
|
||||||
|
|
||||||
|
if (isError) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<LstCard>
|
||||||
|
<CardHeader>There was an error loading the lots</CardHeader>
|
||||||
|
{JSON.stringify(error)}
|
||||||
|
</LstCard>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<LstCard className="m-2 p-2 min-h-2/5">
|
||||||
|
<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>
|
||||||
|
{data?.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")}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="font-medium">{label.status}</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))}
|
||||||
|
</TableBody>
|
||||||
|
)}
|
||||||
|
</Table>
|
||||||
|
</LstCard>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,177 @@
|
|||||||
import {LstCard} from "@/components/extendedUI/LstCard";
|
import {LstCard} from "@/components/extendedUI/LstCard";
|
||||||
|
import {CardHeader} from "@/components/ui/card";
|
||||||
|
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";
|
||||||
|
|
||||||
|
let lotColumns = [
|
||||||
|
{
|
||||||
|
key: "MachineDescription",
|
||||||
|
label: "Machine",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "AV",
|
||||||
|
label: "AV",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "Alias",
|
||||||
|
label: "AvDescription",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "LOT",
|
||||||
|
label: "LotNumber",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "ProlinkLot",
|
||||||
|
label: "ProlinkLot",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "PlannedQTY",
|
||||||
|
label: "PlannedQTY",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "Produced",
|
||||||
|
label: "Produced",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "Remaining",
|
||||||
|
label: "Remaining",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "overPrinting",
|
||||||
|
label: "Overprinting",
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// key: "lastProlinkUpdate",
|
||||||
|
// label: "Last ProlinkCheck",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// key: "printLabel",
|
||||||
|
// label: "Print Label",
|
||||||
|
// },
|
||||||
|
];
|
||||||
export default function Lots() {
|
export default function Lots() {
|
||||||
|
const {data, isError, error, 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)) {
|
||||||
|
//width = 1280;
|
||||||
|
const checkCol = lotColumns.some((l) => l.key === "printLabel");
|
||||||
|
if (!checkCol) {
|
||||||
|
lotColumns = [
|
||||||
|
...lotColumns,
|
||||||
|
{
|
||||||
|
key: "printLabel",
|
||||||
|
label: "Print Label",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isError) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<LstCard>
|
||||||
|
<CardHeader>There was an error loading the lots</CardHeader>
|
||||||
|
{JSON.stringify(error)}
|
||||||
|
</LstCard>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LstCard className="m-2 p-2 min-h-2/5">
|
<LstCard className="m-2 p-2 min-h-2/5">
|
||||||
<h1>Lots</h1>
|
<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>
|
||||||
|
{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>
|
||||||
</LstCard>
|
</LstCard>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
import {Button} from "@/components/ui/button";
|
||||||
|
import {useSessionStore} from "@/lib/store/sessionStore";
|
||||||
|
//import {useSettingStore} from "@/lib/store/useSettings";
|
||||||
|
import {LotType} from "@/types/lots";
|
||||||
|
import {Tag} from "lucide-react";
|
||||||
|
import {toast} from "sonner";
|
||||||
|
import {manualPrintLabels} from "./ManualPrintLabel";
|
||||||
|
|
||||||
|
export default function ManualPrint({lot}: {lot: LotType}) {
|
||||||
|
const {user} = useSessionStore();
|
||||||
|
//const {settings} = useSettingStore();
|
||||||
|
//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}`;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<Button variant="outline" size="icon" onClick={() => handlePrintLabel(lot)}>
|
||||||
|
<Tag className="h-[16px] w-[16px]" />
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,217 @@
|
|||||||
|
import {Button} from "@/components/ui/button";
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogDescription,
|
||||||
|
DialogFooter,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
DialogTrigger,
|
||||||
|
} from "@/components/ui/dialog";
|
||||||
|
import {Input} from "@/components/ui/input";
|
||||||
|
import {Label} from "@/components/ui/label";
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectGroup,
|
||||||
|
SelectItem,
|
||||||
|
SelectLabel,
|
||||||
|
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 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";
|
||||||
|
|
||||||
|
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"},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function ManualPrintForm({lot}: {lot: LotType}) {
|
||||||
|
const {user} = useSessionStore();
|
||||||
|
const token = localStorage.getItem("auth_token");
|
||||||
|
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}`;
|
||||||
|
const {
|
||||||
|
register,
|
||||||
|
handleSubmit,
|
||||||
|
//watch,
|
||||||
|
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) => {
|
||||||
|
// toast.success(`A new label was sent to printer: ${lot.PrinterName} for line ${lot.MachineDescription} `);
|
||||||
|
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};
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
handleManualPrintLog(data, lot);
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<Dialog
|
||||||
|
open={open}
|
||||||
|
onOpenChange={(isOpen) => {
|
||||||
|
if (!open) {
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
setOpen(isOpen);
|
||||||
|
// toast.message("Model was something", {
|
||||||
|
// description: isOpen ? "Modal is open" : "Modal is closed",
|
||||||
|
// });
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<DialogTrigger asChild>
|
||||||
|
<Button variant="outline" size="icon">
|
||||||
|
<Tag className="h-[16px] w-[16px]" />
|
||||||
|
</Button>
|
||||||
|
</DialogTrigger>
|
||||||
|
<DialogContent className="sm:max-w-[425px]">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>Edit profile</DialogTitle>
|
||||||
|
<DialogDescription>
|
||||||
|
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.
|
||||||
|
<br />
|
||||||
|
If you clicked this in error just click close
|
||||||
|
</p>
|
||||||
|
<hr className="mt-2 mb-2" />
|
||||||
|
{server == "usday1vms006" ? (
|
||||||
|
<Controller
|
||||||
|
control={control}
|
||||||
|
name="printReason"
|
||||||
|
defaultValue={""}
|
||||||
|
render={({
|
||||||
|
field: {onChange},
|
||||||
|
fieldState: {},
|
||||||
|
//formState,
|
||||||
|
}) => (
|
||||||
|
<Select onValueChange={onChange}>
|
||||||
|
<SelectTrigger className="w-[180px]">
|
||||||
|
<SelectValue placeholder="Select Reason" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectGroup>
|
||||||
|
<SelectLabel>Print Reasons</SelectLabel>
|
||||||
|
{printReason.map((printReason: any) => (
|
||||||
|
<SelectItem value={printReason.key}>{printReason.label}</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectGroup>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<div>
|
||||||
|
<Label htmlFor="printRason" className="m-1">
|
||||||
|
Why are you manually printing?
|
||||||
|
</Label>
|
||||||
|
<Input
|
||||||
|
type="text"
|
||||||
|
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!",
|
||||||
|
},
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div>
|
||||||
|
<Label htmlFor="line" className="m-1">
|
||||||
|
"What is the line number you are printing?"
|
||||||
|
</Label>
|
||||||
|
<Input
|
||||||
|
//variant="underlined"
|
||||||
|
type="number"
|
||||||
|
className={errors.line ? "border-red-500" : ""}
|
||||||
|
aria-invalid={!!errors.line}
|
||||||
|
{...register("line", {required: true})}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<Label htmlFor="initials" className="m-1">
|
||||||
|
Enter intials
|
||||||
|
</Label>
|
||||||
|
<Input
|
||||||
|
//variant="underlined"
|
||||||
|
//label="Enter intials"
|
||||||
|
|
||||||
|
{...register("initials", {required: true})}
|
||||||
|
/>
|
||||||
|
</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>
|
||||||
|
</DialogFooter>
|
||||||
|
</form>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
import {LotType} from "@/types/lots";
|
||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
export const manualPrintLabels = async (lot: LotType, user: any) => {
|
||||||
|
//console.log(lot);
|
||||||
|
const labelUrl = `/ocp/manualPrintAndFollow`;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await axios.post(
|
||||||
|
labelUrl,
|
||||||
|
{line: lot.MachineLocation, printerName: lot.PrinterName},
|
||||||
|
{headers: {Authorization: `Basic ${user?.prod}`}}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (res.data.success) {
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: `A new label was printed for ${lot.MachineDescription} to printer: ${lot.PrinterName}`,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: `Line ${lot.MachineDescription} encountered an error printing labels: ${res.data.message}`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
if (error.response.status === 500) {
|
||||||
|
//toast.error(`Internal Server error please try again.`);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: `Internal Server error please try again.`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error.response.status === 401) {
|
||||||
|
//console.log(e.response);
|
||||||
|
//toast.error(`You are not authorized to do this.`);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: `You are not authorized to do this.`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -1,16 +1,19 @@
|
|||||||
import {QueryClient, QueryClientProvider} from "@tanstack/react-query";
|
import {QueryClient, QueryClientProvider} from "@tanstack/react-query";
|
||||||
import {useModuleStore} from "../../lib/store/useModuleStore";
|
import {useModuleStore} from "../../lib/store/useModuleStore";
|
||||||
import {useEffect} from "react";
|
import {useEffect} from "react";
|
||||||
|
import {useSettingStore} from "@/lib/store/useSettings";
|
||||||
//import {useGetUserRoles} from "@/lib/store/useGetRoles";
|
//import {useGetUserRoles} from "@/lib/store/useGetRoles";
|
||||||
|
|
||||||
const queryClient = new QueryClient();
|
const queryClient = new QueryClient();
|
||||||
|
|
||||||
export const SessionProvider = ({children}: {children: React.ReactNode}) => {
|
export const SessionProvider = ({children}: {children: React.ReactNode}) => {
|
||||||
const {fetchModules} = useModuleStore();
|
const {fetchModules} = useModuleStore();
|
||||||
|
const {fetchSettings} = useSettingStore();
|
||||||
//const {fetchUserRoles} = useGetUserRoles();
|
//const {fetchUserRoles} = useGetUserRoles();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchModules();
|
fetchModules();
|
||||||
|
fetchSettings();
|
||||||
//fetchUserRoles();
|
//fetchUserRoles();
|
||||||
}, []);
|
}, []);
|
||||||
return <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>;
|
return <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>;
|
||||||
|
|||||||
183
frontend/src/components/ui/select.tsx
Normal file
183
frontend/src/components/ui/select.tsx
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
import * as React from "react"
|
||||||
|
import * as SelectPrimitive from "@radix-ui/react-select"
|
||||||
|
import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "lucide-react"
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
|
function Select({
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof SelectPrimitive.Root>) {
|
||||||
|
return <SelectPrimitive.Root data-slot="select" {...props} />
|
||||||
|
}
|
||||||
|
|
||||||
|
function SelectGroup({
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof SelectPrimitive.Group>) {
|
||||||
|
return <SelectPrimitive.Group data-slot="select-group" {...props} />
|
||||||
|
}
|
||||||
|
|
||||||
|
function SelectValue({
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof SelectPrimitive.Value>) {
|
||||||
|
return <SelectPrimitive.Value data-slot="select-value" {...props} />
|
||||||
|
}
|
||||||
|
|
||||||
|
function SelectTrigger({
|
||||||
|
className,
|
||||||
|
size = "default",
|
||||||
|
children,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof SelectPrimitive.Trigger> & {
|
||||||
|
size?: "sm" | "default"
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<SelectPrimitive.Trigger
|
||||||
|
data-slot="select-trigger"
|
||||||
|
data-size={size}
|
||||||
|
className={cn(
|
||||||
|
"border-input data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex w-fit items-center justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
<SelectPrimitive.Icon asChild>
|
||||||
|
<ChevronDownIcon className="size-4 opacity-50" />
|
||||||
|
</SelectPrimitive.Icon>
|
||||||
|
</SelectPrimitive.Trigger>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function SelectContent({
|
||||||
|
className,
|
||||||
|
children,
|
||||||
|
position = "popper",
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof SelectPrimitive.Content>) {
|
||||||
|
return (
|
||||||
|
<SelectPrimitive.Portal>
|
||||||
|
<SelectPrimitive.Content
|
||||||
|
data-slot="select-content"
|
||||||
|
className={cn(
|
||||||
|
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border shadow-md",
|
||||||
|
position === "popper" &&
|
||||||
|
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
position={position}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<SelectScrollUpButton />
|
||||||
|
<SelectPrimitive.Viewport
|
||||||
|
className={cn(
|
||||||
|
"p-1",
|
||||||
|
position === "popper" &&
|
||||||
|
"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] scroll-my-1"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</SelectPrimitive.Viewport>
|
||||||
|
<SelectScrollDownButton />
|
||||||
|
</SelectPrimitive.Content>
|
||||||
|
</SelectPrimitive.Portal>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function SelectLabel({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof SelectPrimitive.Label>) {
|
||||||
|
return (
|
||||||
|
<SelectPrimitive.Label
|
||||||
|
data-slot="select-label"
|
||||||
|
className={cn("text-muted-foreground px-2 py-1.5 text-xs", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function SelectItem({
|
||||||
|
className,
|
||||||
|
children,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof SelectPrimitive.Item>) {
|
||||||
|
return (
|
||||||
|
<SelectPrimitive.Item
|
||||||
|
data-slot="select-item"
|
||||||
|
className={cn(
|
||||||
|
"focus:bg-accent focus:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<span className="absolute right-2 flex size-3.5 items-center justify-center">
|
||||||
|
<SelectPrimitive.ItemIndicator>
|
||||||
|
<CheckIcon className="size-4" />
|
||||||
|
</SelectPrimitive.ItemIndicator>
|
||||||
|
</span>
|
||||||
|
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
|
||||||
|
</SelectPrimitive.Item>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function SelectSeparator({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof SelectPrimitive.Separator>) {
|
||||||
|
return (
|
||||||
|
<SelectPrimitive.Separator
|
||||||
|
data-slot="select-separator"
|
||||||
|
className={cn("bg-border pointer-events-none -mx-1 my-1 h-px", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function SelectScrollUpButton({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof SelectPrimitive.ScrollUpButton>) {
|
||||||
|
return (
|
||||||
|
<SelectPrimitive.ScrollUpButton
|
||||||
|
data-slot="select-scroll-up-button"
|
||||||
|
className={cn(
|
||||||
|
"flex cursor-default items-center justify-center py-1",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<ChevronUpIcon className="size-4" />
|
||||||
|
</SelectPrimitive.ScrollUpButton>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function SelectScrollDownButton({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof SelectPrimitive.ScrollDownButton>) {
|
||||||
|
return (
|
||||||
|
<SelectPrimitive.ScrollDownButton
|
||||||
|
data-slot="select-scroll-down-button"
|
||||||
|
className={cn(
|
||||||
|
"flex cursor-default items-center justify-center py-1",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<ChevronDownIcon className="size-4" />
|
||||||
|
</SelectPrimitive.ScrollDownButton>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectGroup,
|
||||||
|
SelectItem,
|
||||||
|
SelectLabel,
|
||||||
|
SelectScrollDownButton,
|
||||||
|
SelectScrollUpButton,
|
||||||
|
SelectSeparator,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue,
|
||||||
|
}
|
||||||
18
frontend/src/components/ui/textarea.tsx
Normal file
18
frontend/src/components/ui/textarea.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import * as React from "react"
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
|
function Textarea({ className, ...props }: React.ComponentProps<"textarea">) {
|
||||||
|
return (
|
||||||
|
<textarea
|
||||||
|
data-slot="textarea"
|
||||||
|
className={cn(
|
||||||
|
"border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export { Textarea }
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import {User} from "@/types/users";
|
import {User} from "@/types/users";
|
||||||
|
import axios from "axios";
|
||||||
import {create} from "zustand";
|
import {create} from "zustand";
|
||||||
|
|
||||||
export type SessionState = {
|
export type SessionState = {
|
||||||
@@ -16,9 +17,14 @@ export const useSessionStore = create<SessionState>((set) => {
|
|||||||
user: null, // User is NOT stored in localStorage
|
user: null, // User is NOT stored in localStorage
|
||||||
token: storedToken || null,
|
token: storedToken || null,
|
||||||
|
|
||||||
setSession: (user, token) => {
|
setSession: async (user: any, token) => {
|
||||||
if (token) {
|
if (token) {
|
||||||
localStorage.setItem("auth_token", token);
|
localStorage.setItem("auth_token", token);
|
||||||
|
const response = await axios.get("/api/auth/getuseraccess", {
|
||||||
|
headers: {Authorization: `Bearer ${token}`},
|
||||||
|
});
|
||||||
|
const data = response.data; //await response.json();
|
||||||
|
user = {...user, roles: data.data};
|
||||||
} else {
|
} else {
|
||||||
localStorage.removeItem("auth_token");
|
localStorage.removeItem("auth_token");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import {create} from "zustand";
|
import {create} from "zustand";
|
||||||
import {useSessionStore} from "./sessionStore";
|
import {useSessionStore} from "./sessionStore";
|
||||||
import {Modules} from "@/types/modules";
|
import {Modules} from "@/types/modules";
|
||||||
|
import axios from "axios";
|
||||||
|
|
||||||
interface SettingState {
|
interface SettingState {
|
||||||
userRoles: Modules[];
|
userRoles: Modules[];
|
||||||
@@ -19,15 +20,8 @@ export const useGetUserRoles = create<SettingState>()((set) => ({
|
|||||||
try {
|
try {
|
||||||
//const response = await axios.get<{data: Setting[]}>(`${process.env.NEXT_PUBLIC_URL}/api/settings/client`);
|
//const response = await axios.get<{data: Setting[]}>(`${process.env.NEXT_PUBLIC_URL}/api/settings/client`);
|
||||||
const {token} = useSessionStore();
|
const {token} = useSessionStore();
|
||||||
const response = await fetch(`/api/auth/getuseraccess`, {
|
const response = await axios.get("/api/auth/getuseraccess", {headers: {Authorization: `Bearer ${token}`}});
|
||||||
method: "GET",
|
const data: FetchModulesResponse = response.data; //await response.json();
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
Authentication: `Beaer ${token}`,
|
|
||||||
// You can add other headers here if necessary
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const data: FetchModulesResponse = await response.json();
|
|
||||||
//console.log(data);
|
//console.log(data);
|
||||||
set({userRoles: data.data});
|
set({userRoles: data.data});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import {Modules} from "@/types/modules";
|
import {Modules} from "@/types/modules";
|
||||||
|
import axios from "axios";
|
||||||
import {create} from "zustand";
|
import {create} from "zustand";
|
||||||
|
|
||||||
interface SettingState {
|
interface SettingState {
|
||||||
@@ -17,14 +18,8 @@ export const useModuleStore = create<SettingState>()((set) => ({
|
|||||||
fetchModules: async () => {
|
fetchModules: async () => {
|
||||||
try {
|
try {
|
||||||
//const response = await axios.get<{data: Setting[]}>(`${process.env.NEXT_PUBLIC_URL}/api/settings/client`);
|
//const response = await axios.get<{data: Setting[]}>(`${process.env.NEXT_PUBLIC_URL}/api/settings/client`);
|
||||||
const response = await fetch(`/api/server/modules`, {
|
const response = await axios.get(`/api/server/modules`, {});
|
||||||
method: "GET",
|
const data: FetchModulesResponse = response.data; //await response.json();
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
// You can add other headers here if necessary
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const data: FetchModulesResponse = await response.json();
|
|
||||||
//console.log(data);
|
//console.log(data);
|
||||||
set({modules: data.data});
|
set({modules: data.data});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
29
frontend/src/lib/store/useSettings.ts
Normal file
29
frontend/src/lib/store/useSettings.ts
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import axios from "axios";
|
||||||
|
import {create} from "zustand";
|
||||||
|
|
||||||
|
interface SettingState {
|
||||||
|
settings: any[];
|
||||||
|
|
||||||
|
fetchSettings: () => Promise<void>;
|
||||||
|
setSettings: (settings: any[]) => void;
|
||||||
|
}
|
||||||
|
interface FetchModulesResponse {
|
||||||
|
data: any[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useSettingStore = create<SettingState>()((set) => ({
|
||||||
|
settings: [],
|
||||||
|
setSettings: (settings) => set({settings}),
|
||||||
|
fetchSettings: async () => {
|
||||||
|
try {
|
||||||
|
//const response = await axios.get<{data: Setting[]}>(`${process.env.NEXT_PUBLIC_URL}/api/settings/client`);
|
||||||
|
const response = await axios.get(`/api/server/settings`, {});
|
||||||
|
const data: FetchModulesResponse = response.data; //await response.json();
|
||||||
|
//console.log(data);
|
||||||
|
set({settings: data.data});
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to fetch settings:", error);
|
||||||
|
set({settings: []});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}));
|
||||||
@@ -18,7 +18,6 @@ import { Route as AuthImport } from './routes/_auth'
|
|||||||
import { Route as AdminImport } from './routes/_admin'
|
import { Route as AdminImport } from './routes/_admin'
|
||||||
import { Route as IndexImport } from './routes/index'
|
import { Route as IndexImport } from './routes/index'
|
||||||
import { Route as OcpIndexImport } from './routes/ocp/index'
|
import { Route as OcpIndexImport } from './routes/ocp/index'
|
||||||
import { Route as OcpLotsImport } from './routes/ocp/lots'
|
|
||||||
import { Route as EomEomImport } from './routes/_eom/eom'
|
import { Route as EomEomImport } from './routes/_eom/eom'
|
||||||
import { Route as AuthProfileImport } from './routes/_auth/profile'
|
import { Route as AuthProfileImport } from './routes/_auth/profile'
|
||||||
import { Route as AdminSettingsImport } from './routes/_admin/settings'
|
import { Route as AdminSettingsImport } from './routes/_admin/settings'
|
||||||
@@ -70,12 +69,6 @@ const OcpIndexRoute = OcpIndexImport.update({
|
|||||||
getParentRoute: () => rootRoute,
|
getParentRoute: () => rootRoute,
|
||||||
} as any)
|
} as any)
|
||||||
|
|
||||||
const OcpLotsRoute = OcpLotsImport.update({
|
|
||||||
id: '/ocp/lots',
|
|
||||||
path: '/ocp/lots',
|
|
||||||
getParentRoute: () => rootRoute,
|
|
||||||
} as any)
|
|
||||||
|
|
||||||
const EomEomRoute = EomEomImport.update({
|
const EomEomRoute = EomEomImport.update({
|
||||||
id: '/eom',
|
id: '/eom',
|
||||||
path: '/eom',
|
path: '/eom',
|
||||||
@@ -214,13 +207,6 @@ declare module '@tanstack/react-router' {
|
|||||||
preLoaderRoute: typeof EomEomImport
|
preLoaderRoute: typeof EomEomImport
|
||||||
parentRoute: typeof EomImport
|
parentRoute: typeof EomImport
|
||||||
}
|
}
|
||||||
'/ocp/lots': {
|
|
||||||
id: '/ocp/lots'
|
|
||||||
path: '/ocp/lots'
|
|
||||||
fullPath: '/ocp/lots'
|
|
||||||
preLoaderRoute: typeof OcpLotsImport
|
|
||||||
parentRoute: typeof rootRoute
|
|
||||||
}
|
|
||||||
'/ocp/': {
|
'/ocp/': {
|
||||||
id: '/ocp/'
|
id: '/ocp/'
|
||||||
path: '/ocp'
|
path: '/ocp'
|
||||||
@@ -307,7 +293,6 @@ export interface FileRoutesByFullPath {
|
|||||||
'/settings': typeof AdminSettingsRoute
|
'/settings': typeof AdminSettingsRoute
|
||||||
'/profile': typeof AuthProfileRoute
|
'/profile': typeof AuthProfileRoute
|
||||||
'/eom': typeof EomEomRoute
|
'/eom': typeof EomEomRoute
|
||||||
'/ocp/lots': typeof OcpLotsRoute
|
|
||||||
'/ocp': typeof OcpIndexRoute
|
'/ocp': typeof OcpIndexRoute
|
||||||
'/article/$av': typeof EomArticleAvRoute
|
'/article/$av': typeof EomArticleAvRoute
|
||||||
'/materialHelper': typeof logisticsMaterialHelperIndexRoute
|
'/materialHelper': typeof logisticsMaterialHelperIndexRoute
|
||||||
@@ -325,7 +310,6 @@ export interface FileRoutesByTo {
|
|||||||
'/settings': typeof AdminSettingsRoute
|
'/settings': typeof AdminSettingsRoute
|
||||||
'/profile': typeof AuthProfileRoute
|
'/profile': typeof AuthProfileRoute
|
||||||
'/eom': typeof EomEomRoute
|
'/eom': typeof EomEomRoute
|
||||||
'/ocp/lots': typeof OcpLotsRoute
|
|
||||||
'/ocp': typeof OcpIndexRoute
|
'/ocp': typeof OcpIndexRoute
|
||||||
'/article/$av': typeof EomArticleAvRoute
|
'/article/$av': typeof EomArticleAvRoute
|
||||||
'/materialHelper': typeof logisticsMaterialHelperIndexRoute
|
'/materialHelper': typeof logisticsMaterialHelperIndexRoute
|
||||||
@@ -346,7 +330,6 @@ export interface FileRoutesById {
|
|||||||
'/_admin/settings': typeof AdminSettingsRoute
|
'/_admin/settings': typeof AdminSettingsRoute
|
||||||
'/_auth/profile': typeof AuthProfileRoute
|
'/_auth/profile': typeof AuthProfileRoute
|
||||||
'/_eom/eom': typeof EomEomRoute
|
'/_eom/eom': typeof EomEomRoute
|
||||||
'/ocp/lots': typeof OcpLotsRoute
|
|
||||||
'/ocp/': typeof OcpIndexRoute
|
'/ocp/': typeof OcpIndexRoute
|
||||||
'/_eom/article/$av': typeof EomArticleAvRoute
|
'/_eom/article/$av': typeof EomArticleAvRoute
|
||||||
'/(logistics)/materialHelper/': typeof logisticsMaterialHelperIndexRoute
|
'/(logistics)/materialHelper/': typeof logisticsMaterialHelperIndexRoute
|
||||||
@@ -366,7 +349,6 @@ export interface FileRouteTypes {
|
|||||||
| '/settings'
|
| '/settings'
|
||||||
| '/profile'
|
| '/profile'
|
||||||
| '/eom'
|
| '/eom'
|
||||||
| '/ocp/lots'
|
|
||||||
| '/ocp'
|
| '/ocp'
|
||||||
| '/article/$av'
|
| '/article/$av'
|
||||||
| '/materialHelper'
|
| '/materialHelper'
|
||||||
@@ -383,7 +365,6 @@ export interface FileRouteTypes {
|
|||||||
| '/settings'
|
| '/settings'
|
||||||
| '/profile'
|
| '/profile'
|
||||||
| '/eom'
|
| '/eom'
|
||||||
| '/ocp/lots'
|
|
||||||
| '/ocp'
|
| '/ocp'
|
||||||
| '/article/$av'
|
| '/article/$av'
|
||||||
| '/materialHelper'
|
| '/materialHelper'
|
||||||
@@ -402,7 +383,6 @@ export interface FileRouteTypes {
|
|||||||
| '/_admin/settings'
|
| '/_admin/settings'
|
||||||
| '/_auth/profile'
|
| '/_auth/profile'
|
||||||
| '/_eom/eom'
|
| '/_eom/eom'
|
||||||
| '/ocp/lots'
|
|
||||||
| '/ocp/'
|
| '/ocp/'
|
||||||
| '/_eom/article/$av'
|
| '/_eom/article/$av'
|
||||||
| '/(logistics)/materialHelper/'
|
| '/(logistics)/materialHelper/'
|
||||||
@@ -418,7 +398,6 @@ export interface RootRouteChildren {
|
|||||||
EomRoute: typeof EomRouteWithChildren
|
EomRoute: typeof EomRouteWithChildren
|
||||||
AboutRoute: typeof AboutRoute
|
AboutRoute: typeof AboutRoute
|
||||||
LoginRoute: typeof LoginRoute
|
LoginRoute: typeof LoginRoute
|
||||||
OcpLotsRoute: typeof OcpLotsRoute
|
|
||||||
OcpIndexRoute: typeof OcpIndexRoute
|
OcpIndexRoute: typeof OcpIndexRoute
|
||||||
logisticsMaterialHelperIndexRoute: typeof logisticsMaterialHelperIndexRoute
|
logisticsMaterialHelperIndexRoute: typeof logisticsMaterialHelperIndexRoute
|
||||||
logisticsMaterialHelperConsumptionIndexRoute: typeof logisticsMaterialHelperConsumptionIndexRoute
|
logisticsMaterialHelperConsumptionIndexRoute: typeof logisticsMaterialHelperConsumptionIndexRoute
|
||||||
@@ -432,7 +411,6 @@ const rootRouteChildren: RootRouteChildren = {
|
|||||||
EomRoute: EomRouteWithChildren,
|
EomRoute: EomRouteWithChildren,
|
||||||
AboutRoute: AboutRoute,
|
AboutRoute: AboutRoute,
|
||||||
LoginRoute: LoginRoute,
|
LoginRoute: LoginRoute,
|
||||||
OcpLotsRoute: OcpLotsRoute,
|
|
||||||
OcpIndexRoute: OcpIndexRoute,
|
OcpIndexRoute: OcpIndexRoute,
|
||||||
logisticsMaterialHelperIndexRoute: logisticsMaterialHelperIndexRoute,
|
logisticsMaterialHelperIndexRoute: logisticsMaterialHelperIndexRoute,
|
||||||
logisticsMaterialHelperConsumptionIndexRoute:
|
logisticsMaterialHelperConsumptionIndexRoute:
|
||||||
@@ -457,7 +435,6 @@ export const routeTree = rootRoute
|
|||||||
"/_eom",
|
"/_eom",
|
||||||
"/about",
|
"/about",
|
||||||
"/login",
|
"/login",
|
||||||
"/ocp/lots",
|
|
||||||
"/ocp/",
|
"/ocp/",
|
||||||
"/(logistics)/materialHelper/",
|
"/(logistics)/materialHelper/",
|
||||||
"/(logistics)/materialHelper/consumption/",
|
"/(logistics)/materialHelper/consumption/",
|
||||||
@@ -514,9 +491,6 @@ export const routeTree = rootRoute
|
|||||||
"filePath": "_eom/eom.tsx",
|
"filePath": "_eom/eom.tsx",
|
||||||
"parent": "/_eom"
|
"parent": "/_eom"
|
||||||
},
|
},
|
||||||
"/ocp/lots": {
|
|
||||||
"filePath": "ocp/lots.tsx"
|
|
||||||
},
|
|
||||||
"/ocp/": {
|
"/ocp/": {
|
||||||
"filePath": "ocp/index.tsx"
|
"filePath": "ocp/index.tsx"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
import { createFileRoute } from '@tanstack/react-router'
|
|
||||||
|
|
||||||
export const Route = createFileRoute('/ocp/lots')({
|
|
||||||
component: RouteComponent,
|
|
||||||
})
|
|
||||||
|
|
||||||
function RouteComponent() {
|
|
||||||
return <div>Hello "/ocp/lots"!</div>
|
|
||||||
}
|
|
||||||
19
frontend/src/types/lots.ts
Normal file
19
frontend/src/types/lots.ts
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
export type LotType = {
|
||||||
|
AV: number;
|
||||||
|
Alias: string;
|
||||||
|
LOT: number;
|
||||||
|
LabelOnlineID: number;
|
||||||
|
MachineDescription: string;
|
||||||
|
MachineID: number;
|
||||||
|
MachineLocation: number;
|
||||||
|
PlannedQTY: number;
|
||||||
|
PrinterName: string;
|
||||||
|
Produced: number;
|
||||||
|
ProlinkLot: number;
|
||||||
|
Remaining: number;
|
||||||
|
machineID: number;
|
||||||
|
overPrinting: string;
|
||||||
|
pallerCopies: number;
|
||||||
|
palletLabel: string;
|
||||||
|
printerID: number;
|
||||||
|
};
|
||||||
@@ -6,4 +6,5 @@ export type User = {
|
|||||||
username: string;
|
username: string;
|
||||||
roles: Roles[];
|
roles: Roles[];
|
||||||
role: string;
|
role: string;
|
||||||
|
prod?: string;
|
||||||
};
|
};
|
||||||
|
|||||||
8
frontend/src/utils/adminUrlCheck.ts
Normal file
8
frontend/src/utils/adminUrlCheck.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
export const adminUrlCheck = () => {
|
||||||
|
const host = window.location.host.split(":")[0];
|
||||||
|
const okHost = ["localhost", "usmcd1vms036"];
|
||||||
|
if (okHost.includes(host)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
20
frontend/src/utils/querys/production/labels.tsx
Normal file
20
frontend/src/utils/querys/production/labels.tsx
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import {queryOptions} from "@tanstack/react-query";
|
||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
export function getlabels(hours: string) {
|
||||||
|
return queryOptions({
|
||||||
|
queryKey: ["labels"],
|
||||||
|
queryFn: () => fetchSettings(hours),
|
||||||
|
|
||||||
|
staleTime: 1000,
|
||||||
|
refetchInterval: 2500,
|
||||||
|
refetchOnWindowFocus: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const fetchSettings = async (hours: string) => {
|
||||||
|
const {data} = await axios.get(`/api/v1/ocp/labels?hours=${hours}`);
|
||||||
|
// if we are not localhost ignore the devDir setting.
|
||||||
|
//const url: string = window.location.host.split(":")[0];
|
||||||
|
return data.data;
|
||||||
|
};
|
||||||
21
frontend/src/utils/querys/production/lots.tsx
Normal file
21
frontend/src/utils/querys/production/lots.tsx
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import {queryOptions} from "@tanstack/react-query";
|
||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
export function getlots() {
|
||||||
|
return queryOptions({
|
||||||
|
queryKey: ["lots"],
|
||||||
|
queryFn: () => fetchSettings(),
|
||||||
|
|
||||||
|
staleTime: 10 * 1000,
|
||||||
|
refetchInterval: 10 * 1000,
|
||||||
|
refetchOnWindowFocus: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const fetchSettings = async () => {
|
||||||
|
const {data} = await axios.get("/api/v1/ocp/lots");
|
||||||
|
// if we are not localhost ignore the devDir setting.
|
||||||
|
//const url: string = window.location.host.split(":")[0];
|
||||||
|
let lotData = data.data;
|
||||||
|
return lotData;
|
||||||
|
};
|
||||||
@@ -73,7 +73,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"admConfig": {
|
"admConfig": {
|
||||||
"build": 26,
|
"build": 43,
|
||||||
"oldBuild": "backend-0.1.2.zip"
|
"oldBuild": "backend-0.1.3.zip"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
|
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
|
||||||
import {serve} from "@hono/node-server";
|
import {serve} from "@hono/node-server";
|
||||||
import {OpenAPIHono} from "@hono/zod-openapi";
|
import {OpenAPIHono} from "@hono/zod-openapi";
|
||||||
|
import {proxy} from "hono/proxy";
|
||||||
import {serveStatic} from "@hono/node-server/serve-static";
|
import {serveStatic} from "@hono/node-server/serve-static";
|
||||||
import {logger} from "hono/logger";
|
import {logger} from "hono/logger";
|
||||||
import {cors} from "hono/cors";
|
import {cors} from "hono/cors";
|
||||||
import {createLog} from "./services/logger/logger.js";
|
import {createLog} from "./services/logger/logger.js";
|
||||||
import {closePool} from "./services/sqlServer/prodSqlServer.js";
|
|
||||||
|
|
||||||
// custom routes
|
// custom routes
|
||||||
import scalar from "./services/general/route/scalar.js";
|
import scalar from "./services/general/route/scalar.js";
|
||||||
@@ -17,7 +17,8 @@ import sqlService from "./services/sqlServer/sqlService.js";
|
|||||||
import logistics from "./services/logistics/logisticsService.js";
|
import logistics from "./services/logistics/logisticsService.js";
|
||||||
import rfid from "./services/rfid/rfidService.js";
|
import rfid from "./services/rfid/rfidService.js";
|
||||||
import printers from "./services/printers/printerService.js";
|
import printers from "./services/printers/printerService.js";
|
||||||
|
import loggerService from "./services/logger/loggerService.js";
|
||||||
|
import ocpService from "./services/ocp/ocpService.js";
|
||||||
import {db} from "../database/dbclient.js";
|
import {db} from "../database/dbclient.js";
|
||||||
import {settings} from "../database/schema/settings.js";
|
import {settings} from "../database/schema/settings.js";
|
||||||
import {count, eq} from "drizzle-orm";
|
import {count, eq} from "drizzle-orm";
|
||||||
@@ -32,32 +33,26 @@ const serverIntialized = await db.select({count: count()}).from(settings);
|
|||||||
export const installed = serverIntialized[0].count === 0 && process.env.NODE_ENV !== "development" ? false : true;
|
export const installed = serverIntialized[0].count === 0 && process.env.NODE_ENV !== "development" ? false : true;
|
||||||
createLog("info", "LST", "server", `Server is installed: ${installed}`);
|
createLog("info", "LST", "server", `Server is installed: ${installed}`);
|
||||||
|
|
||||||
const allowedOrigins = [
|
const app = new OpenAPIHono({strict: false});
|
||||||
"http://localhost:3000",
|
|
||||||
"http://localhost:4000",
|
|
||||||
"http://localhost:5173",
|
|
||||||
`http://usmcd1vms006:4000`,
|
|
||||||
];
|
|
||||||
const app = new OpenAPIHono();
|
|
||||||
|
|
||||||
// middle ware
|
// middle ware
|
||||||
app.use("*", logger());
|
app.use("*", logger());
|
||||||
app.use(
|
app.use(
|
||||||
"*",
|
"*",
|
||||||
cors({
|
cors({
|
||||||
origin: allowedOrigins,
|
origin: "*", // Allow all origins
|
||||||
allowHeaders: ["X-Custom-Header", "Upgrade-Insecure-Requests"],
|
allowHeaders: ["Content-Type", "Authorization", "X-Requested-With"],
|
||||||
allowMethods: ["POST", "GET", "OPTIONS"],
|
allowMethods: ["GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"],
|
||||||
exposeHeaders: ["Content-Length", "X-Kuma-Revision"],
|
exposeHeaders: ["Content-Length", "X-Kuma-Revision"],
|
||||||
|
credentials: true, // Allow credentials if needed
|
||||||
maxAge: 600,
|
maxAge: 600,
|
||||||
credentials: true,
|
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
// Middleware to normalize route case
|
// Middleware to normalize route case
|
||||||
app.use("*", async (c, next) => {
|
app.use("*", async (c, next) => {
|
||||||
const lowercasedUrl = c.req.url.toLowerCase();
|
const lowercasedUrl = c.req.url.toLowerCase();
|
||||||
|
//console.log("Incoming Request:", c.req.url, c.req.method);
|
||||||
// If the URL is already lowercase, continue as usual
|
// If the URL is already lowercase, continue as usual
|
||||||
if (c.req.url === lowercasedUrl) {
|
if (c.req.url === lowercasedUrl) {
|
||||||
return next();
|
return next();
|
||||||
@@ -85,22 +80,46 @@ const routes = [
|
|||||||
logistics,
|
logistics,
|
||||||
rfid,
|
rfid,
|
||||||
printers,
|
printers,
|
||||||
|
loggerService,
|
||||||
|
ocpService,
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
const appRoutes = routes.forEach((route) => {
|
const appRoutes = routes.forEach((route) => {
|
||||||
app.route("/api/", route);
|
app.route("/api/", route);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.route("/ocme/*", ocme);
|
||||||
|
|
||||||
|
//--------------- lst v1 proxy ----------------------\\
|
||||||
|
app.all("/api/v1/*", (c) => {
|
||||||
|
const path = c.req.path.replace("/api/v1/", ""); // Extract the subpath
|
||||||
|
const query = c.req.query() ? "?" + new URLSearchParams(c.req.query()).toString() : ""; // Get query params
|
||||||
|
return proxy(`http://localhost:4900/${path}${query}`, {
|
||||||
|
headers: {
|
||||||
|
...c.req.header(),
|
||||||
|
"X-Forwarded-For": "127.0.0.1",
|
||||||
|
"X-Forwarded-Host": c.req.header("host"),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
app.all("/system/*", (c) => {
|
||||||
|
const path = c.req.path.replace("/system/", ""); // Extract the subpath
|
||||||
|
const query = c.req.query() ? "?" + new URLSearchParams(c.req.query()).toString() : ""; // Get query params
|
||||||
|
return proxy(`http://localhost:4200/${path}${query}`, {
|
||||||
|
headers: {
|
||||||
|
...c.req.header(),
|
||||||
|
"X-Forwarded-For": "127.0.0.1",
|
||||||
|
"X-Forwarded-Host": c.req.header("host"),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
//---------------------------------------------------\\
|
||||||
|
|
||||||
// the catch all api route
|
// the catch all api route
|
||||||
app.all("/api/*", (c) => c.json({error: "API route not found"}, 404));
|
app.all("/api/*", (c) => c.json({error: "API route not found"}, 404));
|
||||||
|
|
||||||
app.route("/ocme/", ocme);
|
|
||||||
|
|
||||||
// async (c) => {
|
|
||||||
// //return ocmeService(c);
|
|
||||||
// c.json({error: "Ocme route not found"}, 404);
|
|
||||||
// });
|
|
||||||
|
|
||||||
// front end static files
|
// front end static files
|
||||||
app.use("/*", serveStatic({root: "./frontend/dist"}));
|
app.use("/*", serveStatic({root: "./frontend/dist"}));
|
||||||
app.use("*", serveStatic({path: "./frontend/dist/index.html"}));
|
app.use("*", serveStatic({path: "./frontend/dist/index.html"}));
|
||||||
|
|||||||
@@ -172,21 +172,28 @@ $plantFunness = {
|
|||||||
Write-Host "Removing services that are no longer used."
|
Write-Host "Removing services that are no longer used."
|
||||||
& $nssmPath remove "LogisticsSupportTool" confirm
|
& $nssmPath remove "LogisticsSupportTool" confirm
|
||||||
& $nssmPath remove $serviceAuth confirm
|
& $nssmPath remove $serviceAuth confirm
|
||||||
|
# & $nssmPath remove $serviceGateway confirm
|
||||||
|
# if($token -eq "usday1"){
|
||||||
|
# & $nssmPath remove $serviceOcme confirm
|
||||||
|
# }
|
||||||
Start-Sleep -Seconds 5
|
Start-Sleep -Seconds 5
|
||||||
|
|
||||||
## adding in lstAdm
|
$service = Get-Service -Name $serviceLstV2 -ErrorAction SilentlyContinue
|
||||||
Write-Host "Adding $($serviceLstV2)... incase its missing."
|
|
||||||
$commandToRun = "run start"
|
|
||||||
$description = "logistics Support Tool"
|
|
||||||
& $nssmPath install $serviceLstV2 $npmPath $commandToRun
|
|
||||||
Write-Host "Setting the app directory"
|
|
||||||
& $nssmPath set $serviceLstV2 AppDirectory $appPath
|
|
||||||
Write-Host "Setting the description"
|
|
||||||
& $nssmPath set $serviceLstV2 Description $description
|
|
||||||
Write-Host "Setting recovery options"
|
|
||||||
# Set recovery options
|
|
||||||
sc.exe failure $serviceLstV2 reset= 0 actions= restart/5000/restart/5000/restart/5000
|
|
||||||
|
|
||||||
|
if(-not $service){
|
||||||
|
## adding in lstAdm
|
||||||
|
Write-Host "Adding $($serviceLstV2)... incase its missing."
|
||||||
|
$commandToRun = "run start"
|
||||||
|
$description = "logistics Support Tool"
|
||||||
|
& $nssmPath install $serviceLstV2 $npmPath $commandToRun
|
||||||
|
Write-Host "Setting the app directory"
|
||||||
|
& $nssmPath set $serviceLstV2 AppDirectory $appPath
|
||||||
|
Write-Host "Setting the description"
|
||||||
|
& $nssmPath set $serviceLstV2 Description $description
|
||||||
|
Write-Host "Setting recovery options"
|
||||||
|
# Set recovery options
|
||||||
|
sc.exe failure $serviceLstV2 reset= 0 actions= restart/5000/restart/5000/restart/5000
|
||||||
|
}
|
||||||
# Doing an install
|
# Doing an install
|
||||||
Write-Host "Running the install to make sure everything is updated."
|
Write-Host "Running the install to make sure everything is updated."
|
||||||
Set-Location $serverPath
|
Set-Location $serverPath
|
||||||
@@ -235,10 +242,9 @@ $plantFunness = {
|
|||||||
Start-Service -DisplayName $serviceLstV2
|
Start-Service -DisplayName $serviceLstV2
|
||||||
Start-Sleep -Seconds 1
|
Start-Sleep -Seconds 1
|
||||||
Write-Host "$($server) finished updating"
|
Write-Host "$($server) finished updating"
|
||||||
|
|
||||||
if($token -eq "usday1"){
|
if($token -eq "usday1"){
|
||||||
Write-Host "Starting $($serviceOcme)"
|
Write-Host "Starting $($serviceOcme)"
|
||||||
Start-Service -DisplayName $serviceOcme
|
Start-Service -DisplayName $serviceOcme
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ export async function login(
|
|||||||
user_id: user[0].user_id,
|
user_id: user[0].user_id,
|
||||||
username: user[0].username,
|
username: user[0].username,
|
||||||
email: user[0].email,
|
email: user[0].email,
|
||||||
roles: roles || null,
|
//roles: roles || null,
|
||||||
role: user[0].role || null, // this should be removed onces full migration to v2 is completed
|
role: user[0].role || null, // this should be removed onces full migration to v2 is completed
|
||||||
prod: btoa(`${username.toLowerCase()}:${password}`),
|
prod: btoa(`${username.toLowerCase()}:${password}`),
|
||||||
};
|
};
|
||||||
|
|||||||
22
server/services/logger/controller/clearLog.ts
Normal file
22
server/services/logger/controller/clearLog.ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import {eq, sql} from "drizzle-orm";
|
||||||
|
import {db} from "../../../../database/dbclient.js";
|
||||||
|
import {logs} from "../../../../database/schema/logs.js";
|
||||||
|
import {createLog} from "../logger.js";
|
||||||
|
|
||||||
|
export const clearLog = async (id: string) => {
|
||||||
|
/**
|
||||||
|
* mark the log as cleared
|
||||||
|
*/
|
||||||
|
|
||||||
|
try {
|
||||||
|
const clear = await db
|
||||||
|
.update(logs)
|
||||||
|
.set({checked: true, checkedAt: sql`NOW()`})
|
||||||
|
.where(eq(logs.log_id, id));
|
||||||
|
createLog("info", "lst", "logger", "Log just cleared.");
|
||||||
|
return {success: true, message: "Log was just cleared."};
|
||||||
|
} catch (error) {
|
||||||
|
createLog("error", "lst", "logger", "There was an error clearing the log.");
|
||||||
|
return {success: false, message: "There was an error clearing the log."};
|
||||||
|
}
|
||||||
|
};
|
||||||
28
server/services/logger/controller/getLogs.ts
Normal file
28
server/services/logger/controller/getLogs.ts
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import {and, eq, inArray, lte, sql} from "drizzle-orm";
|
||||||
|
import {db} from "../../../../database/dbclient.js";
|
||||||
|
import {logs} from "../../../../database/schema/logs.js";
|
||||||
|
import {createLog} from "../logger.js";
|
||||||
|
|
||||||
|
export const getLogs = async (data: any) => {
|
||||||
|
try {
|
||||||
|
// clear all remaining logs ne to info.
|
||||||
|
const checked = data.checked && data.checked[0] === "true" ? true : false || false;
|
||||||
|
const logData = await db
|
||||||
|
.select()
|
||||||
|
.from(logs)
|
||||||
|
.where(
|
||||||
|
and(
|
||||||
|
lte(logs.created_at, sql.raw(`NOW() - INTERVAL '${data.hours} hours'`)),
|
||||||
|
inArray(logs.service, data.service),
|
||||||
|
inArray(logs.level, data.level),
|
||||||
|
eq(logs.checked, checked)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return {success: true, message: "logs returned", data: logData};
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
createLog("error", "lst", "logger", `There was an error deleteing server logs. ${error}`);
|
||||||
|
return {success: false, message: "An error occured while trying to get the logs", error};
|
||||||
|
}
|
||||||
|
};
|
||||||
55
server/services/logger/controller/logCleanup.ts
Normal file
55
server/services/logger/controller/logCleanup.ts
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
import {and, eq, inArray, lte, ne, sql} from "drizzle-orm";
|
||||||
|
import {db} from "../../../../database/dbclient.js";
|
||||||
|
import {logs} from "../../../../database/schema/logs.js";
|
||||||
|
import {createLog} from "../logger.js";
|
||||||
|
|
||||||
|
export const logCleanup = async () => {
|
||||||
|
/**
|
||||||
|
* We will run the clean logger where we have aged logs that do not need to be here flooding the db
|
||||||
|
*/
|
||||||
|
|
||||||
|
// clear the server logs older than 3 days
|
||||||
|
try {
|
||||||
|
// clear info logs older than 3 days
|
||||||
|
const delLogs = await db
|
||||||
|
.delete(logs)
|
||||||
|
.where(
|
||||||
|
and(
|
||||||
|
lte(logs.created_at, sql`NOW() - INTERVAL '3 days'`),
|
||||||
|
inArray(logs.service, ["server", "tcp", "sqlProd", "globalutils"]),
|
||||||
|
eq(logs.level, "30")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.returning({name: logs.message});
|
||||||
|
createLog(
|
||||||
|
"info",
|
||||||
|
"lst",
|
||||||
|
"logger",
|
||||||
|
`${delLogs.length} Server logs were just deleted that were older than 3 days`
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
createLog("error", "lst", "logger", `There was an error deleteing server logs. ${error}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// clear all remaining logs ne to info.
|
||||||
|
const delLogs = await db
|
||||||
|
.delete(logs)
|
||||||
|
.where(
|
||||||
|
and(
|
||||||
|
lte(logs.created_at, sql`NOW() - INTERVAL '7 days'`),
|
||||||
|
inArray(logs.service, ["server", "tcp", "sqlProd", "globalutils"]),
|
||||||
|
ne(logs.level, "30")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.returning({name: logs.message});
|
||||||
|
createLog(
|
||||||
|
"info",
|
||||||
|
"lst",
|
||||||
|
"logger",
|
||||||
|
`${delLogs.length} Server logs were just deleted that were older than 7 days`
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
createLog("error", "lst", "logger", `There was an error deleteing server logs. ${error}`);
|
||||||
|
}
|
||||||
|
};
|
||||||
30
server/services/logger/loggerService.ts
Normal file
30
server/services/logger/loggerService.ts
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import {OpenAPIHono} from "@hono/zod-openapi";
|
||||||
|
|
||||||
|
// routes
|
||||||
|
import clearLog from "./routes/clearLog.js";
|
||||||
|
import {db} from "../../../database/dbclient.js";
|
||||||
|
import {settings} from "../../../database/schema/settings.js";
|
||||||
|
import {logCleanup} from "./controller/logCleanup.js";
|
||||||
|
import createNewLog from "./routes/createLog.js";
|
||||||
|
import getLogs from "./routes/getLogs.js";
|
||||||
|
|
||||||
|
const app = new OpenAPIHono();
|
||||||
|
|
||||||
|
const routes = [clearLog, createNewLog, getLogs] as const;
|
||||||
|
const setting = await db.select().from(settings);
|
||||||
|
|
||||||
|
const appRoutes = routes.forEach((route) => {
|
||||||
|
app.route("/logger", route);
|
||||||
|
});
|
||||||
|
|
||||||
|
app.all("/logger/*", (c) => {
|
||||||
|
return c.json({success: false, message: "You have encounters a log route that dose not exist."});
|
||||||
|
});
|
||||||
|
|
||||||
|
// run the clean up job ones on server restart/crash/update and then once a date
|
||||||
|
logCleanup();
|
||||||
|
setInterval(async () => {
|
||||||
|
logCleanup();
|
||||||
|
}, 60 * 1000 * 60 * 24);
|
||||||
|
|
||||||
|
export default app;
|
||||||
44
server/services/logger/routes/clearLog.ts
Normal file
44
server/services/logger/routes/clearLog.ts
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import {createRoute, OpenAPIHono, z} from "@hono/zod-openapi";
|
||||||
|
import {apiHit} from "../../../globalUtils/apiHits.js";
|
||||||
|
import {responses} from "../../../globalUtils/routeDefs/responses.js";
|
||||||
|
import {clearLog} from "../controller/clearLog.js";
|
||||||
|
|
||||||
|
const app = new OpenAPIHono({strict: false});
|
||||||
|
const ParamsSchema = z.object({
|
||||||
|
id: z
|
||||||
|
.string()
|
||||||
|
.min(3)
|
||||||
|
.openapi({
|
||||||
|
param: {
|
||||||
|
name: "id",
|
||||||
|
in: "path",
|
||||||
|
},
|
||||||
|
example: "1212121",
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
app.openapi(
|
||||||
|
createRoute({
|
||||||
|
tags: ["server:logger"],
|
||||||
|
summary: "Marks the select log id as cleared out.",
|
||||||
|
method: "patch",
|
||||||
|
path: "/logs/{id}",
|
||||||
|
request: {
|
||||||
|
params: ParamsSchema,
|
||||||
|
},
|
||||||
|
responses: responses(),
|
||||||
|
}),
|
||||||
|
async (c) => {
|
||||||
|
const {id} = c.req.valid("param");
|
||||||
|
//const body = await c.req.json();
|
||||||
|
// make sure we have a vaid user being accessed thats really logged in
|
||||||
|
apiHit(c, {endpoint: `api/logger/logs/id`});
|
||||||
|
try {
|
||||||
|
const clear = await clearLog(id);
|
||||||
|
return c.json({success: clear.success, message: clear.message, data: []}, 200);
|
||||||
|
} catch (error) {
|
||||||
|
return c.json({success: false, message: "There was an error clearing the log.", data: error}, 400);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
export default app;
|
||||||
38
server/services/logger/routes/createLog.ts
Normal file
38
server/services/logger/routes/createLog.ts
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
// an external way to creating logs
|
||||||
|
import {createRoute, OpenAPIHono, z} from "@hono/zod-openapi";
|
||||||
|
import {apiHit} from "../../../globalUtils/apiHits.js";
|
||||||
|
import {responses} from "../../../globalUtils/routeDefs/responses.js";
|
||||||
|
import {createLog} from "../logger.js";
|
||||||
|
|
||||||
|
const app = new OpenAPIHono({strict: false});
|
||||||
|
const CreateLog = z.object({
|
||||||
|
level: z.string().openapi({example: "info"}),
|
||||||
|
service: z.string().openapi({example: "server"}),
|
||||||
|
message: z.string().openapi({example: "This is a new log posted"}),
|
||||||
|
});
|
||||||
|
|
||||||
|
app.openapi(
|
||||||
|
createRoute({
|
||||||
|
tags: ["server:logger"],
|
||||||
|
summary: "Post a log to the db.",
|
||||||
|
method: "post",
|
||||||
|
path: "/logs",
|
||||||
|
description: "This might be a temp soltuin during the transtion between versions",
|
||||||
|
request: {
|
||||||
|
body: {content: {"application/json": {schema: CreateLog}}},
|
||||||
|
},
|
||||||
|
responses: responses(),
|
||||||
|
}),
|
||||||
|
async (c) => {
|
||||||
|
const body = await c.req.json();
|
||||||
|
|
||||||
|
apiHit(c, {endpoint: `api/logger/logs/id`});
|
||||||
|
try {
|
||||||
|
createLog(body.level, "logger", body.service, body.message);
|
||||||
|
return c.json({success: true, message: "A new log was created.", data: []}, 200);
|
||||||
|
} catch (error) {
|
||||||
|
return c.json({success: false, message: "There was an error clearing the log.", data: error}, 400);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
export default app;
|
||||||
39
server/services/logger/routes/getLogs.ts
Normal file
39
server/services/logger/routes/getLogs.ts
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
// an external way to creating logs
|
||||||
|
import {createRoute, OpenAPIHono, z} from "@hono/zod-openapi";
|
||||||
|
import {apiHit} from "../../../globalUtils/apiHits.js";
|
||||||
|
import {responses} from "../../../globalUtils/routeDefs/responses.js";
|
||||||
|
import {createLog} from "../logger.js";
|
||||||
|
import {getLogs} from "../controller/getLogs.js";
|
||||||
|
|
||||||
|
const app = new OpenAPIHono({strict: false});
|
||||||
|
const CreateLog = z.object({
|
||||||
|
level: z.string().openapi({example: "info"}),
|
||||||
|
service: z.string().openapi({example: "server"}),
|
||||||
|
message: z.string().openapi({example: "This is a new log posted"}),
|
||||||
|
});
|
||||||
|
|
||||||
|
app.openapi(
|
||||||
|
createRoute({
|
||||||
|
tags: ["server:logger"],
|
||||||
|
summary: "Gets logs.",
|
||||||
|
method: "get",
|
||||||
|
path: "/logs",
|
||||||
|
description: "This might be a temp soltuin during the transtion between versions",
|
||||||
|
request: {
|
||||||
|
body: {content: {"application/json": {schema: CreateLog}}},
|
||||||
|
},
|
||||||
|
responses: responses(),
|
||||||
|
}),
|
||||||
|
async (c) => {
|
||||||
|
const query = await c.req.queries();
|
||||||
|
|
||||||
|
apiHit(c, {endpoint: `api/logger/logs`});
|
||||||
|
try {
|
||||||
|
const logData = await getLogs(query);
|
||||||
|
return c.json({success: logData?.success, message: logData?.message, data: logData?.data}, 200);
|
||||||
|
} catch (error) {
|
||||||
|
return c.json({success: false, message: "There was an error clearing the log.", data: error}, 400);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
export default app;
|
||||||
@@ -6,12 +6,17 @@ import postRunningNr from "./route/postRunningNumber.js";
|
|||||||
import pickedup from "./route/pickedUp.js";
|
import pickedup from "./route/pickedUp.js";
|
||||||
import postsscc from "./route/postSSCC.js";
|
import postsscc from "./route/postSSCC.js";
|
||||||
import getShipments from "./route/getShipmentPallets.js";
|
import getShipments from "./route/getShipmentPallets.js";
|
||||||
|
import {serve} from "@hono/node-server";
|
||||||
|
import {createLog} from "../logger/logger.js";
|
||||||
|
import {db} from "../../../database/dbclient.js";
|
||||||
|
import {settings} from "../../../database/schema/settings.js";
|
||||||
|
|
||||||
const app = new OpenAPIHono();
|
const app = new OpenAPIHono();
|
||||||
|
const port = process.env.OCME_PORT;
|
||||||
const routes = [getInfo, postRunningNr, postsscc, pickedup, getShipments] as const;
|
const routes = [getInfo, postRunningNr, postsscc, pickedup, getShipments] as const;
|
||||||
|
const setting = await db.select().from(settings);
|
||||||
|
|
||||||
// app.route("/server", modules);
|
const isActive = setting.filter((n) => n.name === "ocmeService");
|
||||||
const appRoutes = routes.forEach((route) => {
|
const appRoutes = routes.forEach((route) => {
|
||||||
app.route("/api/v1", route);
|
app.route("/api/v1", route);
|
||||||
});
|
});
|
||||||
@@ -19,5 +24,17 @@ const appRoutes = routes.forEach((route) => {
|
|||||||
app.all("/api/v1/*", (c) => {
|
app.all("/api/v1/*", (c) => {
|
||||||
return c.json({success: false, message: "you have encounted an ocme route that dose not exist."});
|
return c.json({success: false, message: "you have encounted an ocme route that dose not exist."});
|
||||||
});
|
});
|
||||||
|
if (port && isActive[0]?.value === "1") {
|
||||||
|
serve(
|
||||||
|
{
|
||||||
|
fetch: app.fetch,
|
||||||
|
port: Number(port),
|
||||||
|
hostname: "0.0.0.0",
|
||||||
|
},
|
||||||
|
(info) => {
|
||||||
|
createLog("info", "LST", "server", `Ocme section is listening on http://${info.address}:${info.port}`);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export default app;
|
export default app;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import {createRoute, OpenAPIHono, z} from "@hono/zod-openapi";
|
|||||||
import {getInfo} from "../controller/getInfo.js";
|
import {getInfo} from "../controller/getInfo.js";
|
||||||
import {apiHit} from "../../../globalUtils/apiHits.js";
|
import {apiHit} from "../../../globalUtils/apiHits.js";
|
||||||
|
|
||||||
const app = new OpenAPIHono();
|
const app = new OpenAPIHono({strict: false});
|
||||||
|
|
||||||
const AddSetting = z.object({
|
const AddSetting = z.object({
|
||||||
name: z.string().openapi({example: "server"}),
|
name: z.string().openapi({example: "server"}),
|
||||||
|
|||||||
20
server/services/ocp/controller/manualLabelLog.ts
Normal file
20
server/services/ocp/controller/manualLabelLog.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import {db} from "../../../../database/dbclient.js";
|
||||||
|
import {manualPrinting} from "../../../../database/schema/ocpManualPrint.js";
|
||||||
|
|
||||||
|
export const manualPrint = async (data: any) => {
|
||||||
|
/**
|
||||||
|
* add the reason we did a manual print.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const manualPrintData = {
|
||||||
|
line: data.line,
|
||||||
|
printReason: data.printReason,
|
||||||
|
initials: data.initials,
|
||||||
|
additionalComments: data?.additionalComments,
|
||||||
|
add_user: "lst",
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const manualPrint = await db.insert(manualPrinting).values(manualPrintData);
|
||||||
|
} catch (error) {}
|
||||||
|
};
|
||||||
22
server/services/ocp/ocpService.ts
Normal file
22
server/services/ocp/ocpService.ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import {OpenAPIHono} from "@hono/zod-openapi";
|
||||||
|
|
||||||
|
// routes
|
||||||
|
import manualLabelLog from "./routes/manualPrintLog.js";
|
||||||
|
|
||||||
|
import {db} from "../../../database/dbclient.js";
|
||||||
|
import {settings} from "../../../database/schema/settings.js";
|
||||||
|
|
||||||
|
const app = new OpenAPIHono();
|
||||||
|
|
||||||
|
const routes = [manualLabelLog] as const;
|
||||||
|
const setting = await db.select().from(settings);
|
||||||
|
|
||||||
|
const appRoutes = routes.forEach((route) => {
|
||||||
|
app.route("/ocp", route);
|
||||||
|
});
|
||||||
|
|
||||||
|
app.all("/ocp/*", (c) => {
|
||||||
|
return c.json({success: false, message: "You have encounters a ocp route that dose not exist."});
|
||||||
|
});
|
||||||
|
|
||||||
|
export default app;
|
||||||
56
server/services/ocp/routes/manualPrintLog.ts
Normal file
56
server/services/ocp/routes/manualPrintLog.ts
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
// an external way to creating logs
|
||||||
|
import {createRoute, OpenAPIHono, z} from "@hono/zod-openapi";
|
||||||
|
import {apiHit} from "../../../globalUtils/apiHits.js";
|
||||||
|
import {responses} from "../../../globalUtils/routeDefs/responses.js";
|
||||||
|
import type {User} from "../../../types/users.js";
|
||||||
|
import {verify} from "hono/jwt";
|
||||||
|
import {manualPrint} from "../controller/manualLabelLog.js";
|
||||||
|
import {authMiddleware} from "../../auth/middleware/authMiddleware.js";
|
||||||
|
|
||||||
|
const app = new OpenAPIHono({strict: false});
|
||||||
|
const CreateLog = z.object({
|
||||||
|
line: z.string().openapi({example: "info"}),
|
||||||
|
initials: z.string().openapi({example: "server"}),
|
||||||
|
printReason: z.string().openapi({example: "This is a new log posted"}),
|
||||||
|
additionalComments: z.string().optional().openapi({example: "Some reason why we did this."}),
|
||||||
|
});
|
||||||
|
|
||||||
|
app.openapi(
|
||||||
|
createRoute({
|
||||||
|
tags: ["ocp"],
|
||||||
|
summary: "Post the log for manaulprinting.",
|
||||||
|
method: "post",
|
||||||
|
path: "/manuallabellog",
|
||||||
|
//middleware: authMiddleware,
|
||||||
|
//description: "This might be a temp soltuin during the transtion between versions",
|
||||||
|
request: {
|
||||||
|
body: {content: {"application/json": {schema: CreateLog}}},
|
||||||
|
},
|
||||||
|
responses: responses(),
|
||||||
|
}),
|
||||||
|
async (c) => {
|
||||||
|
const body = await c.req.json();
|
||||||
|
apiHit(c, {endpoint: `api/logger/logs/id`});
|
||||||
|
// const authHeader = c.req.header("Authorization");
|
||||||
|
|
||||||
|
// const token = authHeader?.split("Bearer ")[1] || "";
|
||||||
|
// let user: User;
|
||||||
|
|
||||||
|
// try {
|
||||||
|
// const payload = await verify(token, process.env.JWT_SECRET!);
|
||||||
|
// user = payload.user as User;
|
||||||
|
// } catch (error) {
|
||||||
|
// console.log(error);
|
||||||
|
// return c.json({message: "Unauthorized"}, 401);
|
||||||
|
// }
|
||||||
|
|
||||||
|
try {
|
||||||
|
//const data = {...body, add_user: user.username};
|
||||||
|
await manualPrint(body);
|
||||||
|
return c.json({success: true, message: "Manual Print was added.", data: []}, 200);
|
||||||
|
} catch (error) {
|
||||||
|
return c.json({success: false, message: "There was an error clearing the log.", data: error}, 400);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
export default app;
|
||||||
52
server/services/ocp/routes/printLabel.ts
Normal file
52
server/services/ocp/routes/printLabel.ts
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
// an external way to creating logs
|
||||||
|
import {createRoute, OpenAPIHono, z} from "@hono/zod-openapi";
|
||||||
|
import {apiHit} from "../../../globalUtils/apiHits.js";
|
||||||
|
import {responses} from "../../../globalUtils/routeDefs/responses.js";
|
||||||
|
|
||||||
|
const app = new OpenAPIHono({strict: false});
|
||||||
|
const CreateLog = z.object({
|
||||||
|
line: z.string().openapi({example: "info"}),
|
||||||
|
initials: z.string().openapi({example: "server"}),
|
||||||
|
printReason: z.string().openapi({example: "This is a new log posted"}),
|
||||||
|
additionalComments: z.string().optional().openapi({example: "Some reason why we did this."}),
|
||||||
|
});
|
||||||
|
|
||||||
|
app.openapi(
|
||||||
|
createRoute({
|
||||||
|
tags: ["ocp"],
|
||||||
|
summary: "Prints a label.",
|
||||||
|
method: "post",
|
||||||
|
path: "/printlabel",
|
||||||
|
//middleware: authMiddleware,
|
||||||
|
//description: "This might be a temp soltuin during the transtion between versions",
|
||||||
|
request: {
|
||||||
|
body: {content: {"application/json": {schema: CreateLog}}},
|
||||||
|
},
|
||||||
|
responses: responses(),
|
||||||
|
}),
|
||||||
|
async (c) => {
|
||||||
|
const body = await c.req.json();
|
||||||
|
apiHit(c, {endpoint: `api/logger/logs/id`});
|
||||||
|
// const authHeader = c.req.header("Authorization");
|
||||||
|
|
||||||
|
// const token = authHeader?.split("Bearer ")[1] || "";
|
||||||
|
// let user: User;
|
||||||
|
|
||||||
|
// try {
|
||||||
|
// const payload = await verify(token, process.env.JWT_SECRET!);
|
||||||
|
// user = payload.user as User;
|
||||||
|
// } catch (error) {
|
||||||
|
// console.log(error);
|
||||||
|
// return c.json({message: "Unauthorized"}, 401);
|
||||||
|
// }
|
||||||
|
|
||||||
|
try {
|
||||||
|
//const data = {...body, add_user: user.username};
|
||||||
|
|
||||||
|
return c.json({success: true, message: "Label was printed.", data: []}, 200);
|
||||||
|
} catch (error) {
|
||||||
|
return c.json({success: false, message: "There was an error printing a label.", data: error}, 400);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
export default app;
|
||||||
@@ -4,6 +4,7 @@ import {addSetting} from "../../controller/settings/addSetting.js";
|
|||||||
import {verify} from "hono/jwt";
|
import {verify} from "hono/jwt";
|
||||||
import type {User} from "../../../../types/users.js";
|
import type {User} from "../../../../types/users.js";
|
||||||
import {authMiddleware} from "../../../auth/middleware/authMiddleware.js";
|
import {authMiddleware} from "../../../auth/middleware/authMiddleware.js";
|
||||||
|
import {responses} from "../../../../globalUtils/routeDefs/responses.js";
|
||||||
|
|
||||||
const app = new OpenAPIHono();
|
const app = new OpenAPIHono();
|
||||||
|
|
||||||
@@ -29,43 +30,7 @@ app.openapi(
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
responses: {
|
responses: responses(),
|
||||||
200: {
|
|
||||||
content: {
|
|
||||||
"application/json": {
|
|
||||||
schema: z.object({
|
|
||||||
success: z.boolean().openapi({example: true}),
|
|
||||||
message: z.string().openapi({example: "Starter"}),
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
description: "Response message",
|
|
||||||
},
|
|
||||||
400: {
|
|
||||||
content: {
|
|
||||||
"application/json": {
|
|
||||||
schema: z.object({message: z.string().optional().openapi({example: "Internal Server error"})}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
description: "Internal Server Error",
|
|
||||||
},
|
|
||||||
401: {
|
|
||||||
content: {
|
|
||||||
"application/json": {
|
|
||||||
schema: z.object({message: z.string().optional().openapi({example: "Unauthenticated"})}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
description: "Unauthorized",
|
|
||||||
},
|
|
||||||
500: {
|
|
||||||
content: {
|
|
||||||
"application/json": {
|
|
||||||
schema: z.object({message: z.string().optional().openapi({example: "Internal Server error"})}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
description: "Internal Server Error",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
}),
|
||||||
async (c) => {
|
async (c) => {
|
||||||
// make sure we have a vaid user being accessed thats really logged in
|
// make sure we have a vaid user being accessed thats really logged in
|
||||||
|
|||||||
@@ -52,25 +52,6 @@ app.openapi(
|
|||||||
}),
|
}),
|
||||||
async (c) => {
|
async (c) => {
|
||||||
// make sure we have a vaid user being accessed thats really logged in
|
// make sure we have a vaid user being accessed thats really logged in
|
||||||
const authHeader = c.req.header("Authorization");
|
|
||||||
|
|
||||||
if (authHeader?.includes("Basic")) {
|
|
||||||
return c.json({message: "You are a Basic user! Please login to get a token"}, 401);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!authHeader) {
|
|
||||||
return c.json({message: "Unauthorized"}, 401);
|
|
||||||
}
|
|
||||||
|
|
||||||
const token = authHeader?.split("Bearer ")[1] || "";
|
|
||||||
let user: User;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const payload = await verify(token, process.env.JWT_SECRET!);
|
|
||||||
user = payload.user as User;
|
|
||||||
} catch (error) {
|
|
||||||
return c.json({message: "Unauthorized"}, 401);
|
|
||||||
}
|
|
||||||
|
|
||||||
// now pass all the data over to update the user info
|
// now pass all the data over to update the user info
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -173,7 +173,7 @@
|
|||||||
"contactPhone": "6366970253",
|
"contactPhone": "6366970253",
|
||||||
"customerTiAcc": "ALPL01DAYTONINT",
|
"customerTiAcc": "ALPL01DAYTONINT",
|
||||||
"lstServerPort": "4000",
|
"lstServerPort": "4000",
|
||||||
"active": false,
|
"active": true,
|
||||||
"serverLoc": "E:\\LST\\lstv2",
|
"serverLoc": "E:\\LST\\lstv2",
|
||||||
"oldVersion": "E:\\LST\\lst_backend",
|
"oldVersion": "E:\\LST\\lst_backend",
|
||||||
"shippingHours": "[{\"early\": \"06:30\", \"late\": \"23:00\"}]",
|
"shippingHours": "[{\"early\": \"06:30\", \"late\": \"23:00\"}]",
|
||||||
|
|||||||
@@ -56,6 +56,12 @@ const newSettings = [
|
|||||||
description: "Dose the plant have 2 machines that go to 1?",
|
description: "Dose the plant have 2 machines that go to 1?",
|
||||||
moduleName: "ocp",
|
moduleName: "ocp",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "ocmeService",
|
||||||
|
value: "0",
|
||||||
|
description: "Is the ocme service enabled. this is gernerally only for Dayton.",
|
||||||
|
moduleName: "ocme",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "fifoCheck",
|
name: "fifoCheck",
|
||||||
value: "45",
|
value: "45",
|
||||||
@@ -80,12 +86,40 @@ const newSettings = [
|
|||||||
description: "What address is monitored to be limited to the amount of lots that can be added to a truck.",
|
description: "What address is monitored to be limited to the amount of lots that can be added to a truck.",
|
||||||
moduleName: "ocme",
|
moduleName: "ocme",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "ocmeCycleCount",
|
||||||
|
value: "1",
|
||||||
|
description: "Are we allowing ocme cycle counts?",
|
||||||
|
roles: "admin",
|
||||||
|
module: "ocme",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "devDir",
|
name: "devDir",
|
||||||
value: "C:\\Users\\matthes01\\Documents\\lstv2",
|
value: "C:\\Users\\matthes01\\Documents\\lstv2",
|
||||||
description: "This is the dev dir and strictly only for updating the servers.",
|
description: "This is the dev dir and strictly only for updating the servers.",
|
||||||
moduleName: "server",
|
moduleName: "server",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "demandMGTActivated",
|
||||||
|
value: "0",
|
||||||
|
description: "Do we allow for new fake edi?",
|
||||||
|
roles: "admin",
|
||||||
|
module: "logistics",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "qualityRequest",
|
||||||
|
value: "0",
|
||||||
|
description: "quality request module?",
|
||||||
|
roles: "admin",
|
||||||
|
module: "logistics",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ocpLogsCheck",
|
||||||
|
value: "4",
|
||||||
|
description: "How long do we want to allow logs to show that have not been cleared?",
|
||||||
|
roles: "admin",
|
||||||
|
module: "ocp",
|
||||||
|
},
|
||||||
];
|
];
|
||||||
export const areSettingsIn = async () => {
|
export const areSettingsIn = async () => {
|
||||||
// get the roles
|
// get the roles
|
||||||
|
|||||||
Reference in New Issue
Block a user