refactor(old app): login migration to new app
This commit is contained in:
@@ -1,28 +1,26 @@
|
|||||||
import { getUsers } from "@/utils/querys/admin/users";
|
|
||||||
import { useQuery } from "@tanstack/react-query";
|
|
||||||
import UserCard from "./components/UserCard";
|
|
||||||
|
|
||||||
export default function UserPage() {
|
export default function UserPage() {
|
||||||
const { data, isError, error, isLoading } = useQuery(getUsers());
|
//const { data, isError, error, isLoading } = useQuery(getUsers());
|
||||||
|
|
||||||
if (isLoading) return <div className="m-auto">Loading users...</div>;
|
// if (isLoading) return <div className="m-auto">Loading users...</div>;
|
||||||
|
|
||||||
if (isError)
|
// if (isError)
|
||||||
return (
|
// return (
|
||||||
<div className="m-auto">
|
// <div className="m-auto">
|
||||||
There was an error getting the users.... {JSON.stringify(error)}
|
// There was an error getting the users.... {JSON.stringify(error)}
|
||||||
</div>
|
// </div>
|
||||||
);
|
// );
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="m-2 w-dvw">
|
<div className="m-2 w-dvw">
|
||||||
{data.map((u: any) => {
|
<span>This has been moved to the new system</span>
|
||||||
return (
|
{/* {data.map((u: any) => {
|
||||||
<div>
|
return (
|
||||||
<UserCard user={u} />
|
<div>
|
||||||
</div>
|
<UserCard user={u} />
|
||||||
);
|
|
||||||
})}
|
</div>
|
||||||
</div>
|
);
|
||||||
);
|
})} */}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,172 +1,177 @@
|
|||||||
import { useSessionStore } from "../../lib/store/sessionStore";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { LstCard } from "../extendedUI/LstCard";
|
|
||||||
import { CardHeader } from "../ui/card";
|
|
||||||
import { toast } from "sonner";
|
|
||||||
import { z } from "zod";
|
|
||||||
import { useRouter, useSearch } from "@tanstack/react-router";
|
import { useRouter, useSearch } from "@tanstack/react-router";
|
||||||
import { Controller, useForm } from "react-hook-form";
|
import { Controller, useForm } from "react-hook-form";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { toast } from "sonner";
|
||||||
import { Label } from "../ui/label";
|
import { z } from "zod";
|
||||||
import { Input } from "../ui/input";
|
import { useAuthStore } from "@/lib/store/useAuthStore";
|
||||||
import { Checkbox } from "../ui/checkbox";
|
import { useSessionStore } from "../../lib/store/sessionStore";
|
||||||
|
import { LstCard } from "../extendedUI/LstCard";
|
||||||
import { Button } from "../ui/button";
|
import { Button } from "../ui/button";
|
||||||
|
import { CardHeader } from "../ui/card";
|
||||||
|
import { Checkbox } from "../ui/checkbox";
|
||||||
|
import { Input } from "../ui/input";
|
||||||
|
import { Label } from "../ui/label";
|
||||||
|
|
||||||
const FormSchema = z.object({
|
const FormSchema = z.object({
|
||||||
username: z.string().min(1, "You must enter a valid username"),
|
username: z.string().min(1, "You must enter a valid username"),
|
||||||
password: z.string().min(4, "You must enter a valid password"),
|
password: z.string().min(4, "You must enter a valid password"),
|
||||||
rememberMe: z.boolean(),
|
rememberMe: z.boolean(),
|
||||||
});
|
});
|
||||||
|
|
||||||
const LoginForm = () => {
|
const LoginForm = () => {
|
||||||
const { setSession } = useSessionStore();
|
const { setSession } = useSessionStore();
|
||||||
const rememeberMe = localStorage.getItem("rememberMe") === "true";
|
const { setUserInfo } = useAuthStore();
|
||||||
const username = localStorage.getItem("username") || "";
|
const rememeberMe = localStorage.getItem("rememberMe") === "true";
|
||||||
const router = useRouter();
|
const username = localStorage.getItem("username") || "";
|
||||||
const search = useSearch({ from: "/login" });
|
const router = useRouter();
|
||||||
|
const search = useSearch({ from: "/login" });
|
||||||
|
|
||||||
const {
|
const {
|
||||||
register,
|
register,
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
control,
|
control,
|
||||||
formState: { errors },
|
formState: { errors },
|
||||||
} = useForm<z.infer<typeof FormSchema>>({
|
} = useForm<z.infer<typeof FormSchema>>({
|
||||||
resolver: zodResolver(FormSchema),
|
resolver: zodResolver(FormSchema),
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
username: username || "",
|
username: username || "",
|
||||||
password: "",
|
password: "",
|
||||||
rememberMe: rememeberMe,
|
rememberMe: rememeberMe,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const onSubmitLogin = async (value: z.infer<typeof FormSchema>) => {
|
const onSubmitLogin = async (value: z.infer<typeof FormSchema>) => {
|
||||||
// Do something with form data
|
// Do something with form data
|
||||||
|
|
||||||
// first update the rememberMe incase it was selected
|
// first update the rememberMe incase it was selected
|
||||||
if (value.rememberMe) {
|
if (value.rememberMe) {
|
||||||
localStorage.setItem("rememberMe", value.rememberMe.toString());
|
localStorage.setItem("rememberMe", value.rememberMe.toString());
|
||||||
localStorage.setItem("username", value.username);
|
localStorage.setItem("username", value.username);
|
||||||
} else {
|
} else {
|
||||||
localStorage.removeItem("rememberMe");
|
localStorage.removeItem("rememberMe");
|
||||||
localStorage.removeItem("username");
|
localStorage.removeItem("username");
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch("/api/auth/login", {
|
const response = await fetch("/api/auth/login", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
username: value.username,
|
username: value.username,
|
||||||
password: value.password,
|
password: value.password,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
|
||||||
// Store token in localStorage
|
// Store token in localStorage
|
||||||
// localStorage.setItem("auth_token", data.data.token);
|
// localStorage.setItem("auth_token", data.data.token);
|
||||||
if (data.success) {
|
if (data.success) {
|
||||||
const prod = btoa(
|
const prod = btoa(`${value.username.toLowerCase()}:${value.password}`);
|
||||||
`${value.username.toLowerCase()}:${value.password}`
|
const prodUser = { ...data.user, prod: prod };
|
||||||
);
|
setUserInfo(value.username.toLowerCase(), value.password);
|
||||||
const prodUser = { ...data.user, prod: prod };
|
setSession(prodUser, data.data.token);
|
||||||
|
toast.success(`You are logged in as ${data.data.user.username}`);
|
||||||
|
|
||||||
setSession(prodUser, data.token);
|
//console.log(search.redirect ? search.redirect : "oops");
|
||||||
toast.success(`You are logged in as ${data.user.username}`);
|
router.history.push(search.redirect ? search.redirect : "/");
|
||||||
|
}
|
||||||
|
|
||||||
console.log(search.redirect ? search.redirect : "oops");
|
if (!data.success) {
|
||||||
router.history.push(search.redirect ? search.redirect : "/");
|
toast.error(`${data.message}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!data.success) {
|
//console.log(data);
|
||||||
toast.error(`${data.message}`);
|
} catch (err) {
|
||||||
}
|
// @ts-ignore
|
||||||
|
if (!err.response.success) {
|
||||||
|
// @ts-ignore
|
||||||
|
toast.error(err.response.data.message);
|
||||||
|
} else {
|
||||||
|
// @ts-ignore
|
||||||
|
toast.error(err?.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
//console.log(data);
|
return (
|
||||||
} catch (err) {
|
<div className="ml-[25%]">
|
||||||
toast.error("Invalid credentials");
|
<LstCard className="p-3 w-96">
|
||||||
}
|
<CardHeader>
|
||||||
};
|
<div>
|
||||||
|
<p className="text-2xl">Login to LST</p>
|
||||||
|
</div>
|
||||||
|
</CardHeader>
|
||||||
|
<hr className="rounded"></hr>
|
||||||
|
<form onSubmit={handleSubmit(onSubmitLogin)}>
|
||||||
|
<div>
|
||||||
|
<Label htmlFor="username" className="m-1">
|
||||||
|
Username
|
||||||
|
</Label>
|
||||||
|
<Input
|
||||||
|
placeholder="smith001"
|
||||||
|
{...register("username")}
|
||||||
|
className={errors.username ? "border-red-500" : ""}
|
||||||
|
aria-invalid={!!errors.username}
|
||||||
|
/>
|
||||||
|
{errors.username && (
|
||||||
|
<p className="text-red-500 text-sm mt-1">
|
||||||
|
{errors.username.message}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<>
|
||||||
|
<Label htmlFor={"password"} className="m-1">
|
||||||
|
Password
|
||||||
|
</Label>
|
||||||
|
<Input
|
||||||
|
type="password"
|
||||||
|
{...register("password")}
|
||||||
|
className={errors.password ? "border-red-500" : ""}
|
||||||
|
aria-invalid={!!errors.password}
|
||||||
|
/>
|
||||||
|
{errors.password && (
|
||||||
|
<p className="text-red-500 text-sm mt-1">
|
||||||
|
{errors.password.message}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
</div>
|
||||||
|
<div className="flex justify-between pt-2">
|
||||||
|
<div className="flex">
|
||||||
|
<Controller
|
||||||
|
render={({ field }) => (
|
||||||
|
<>
|
||||||
|
<Checkbox
|
||||||
|
id="remember"
|
||||||
|
checked={field.value}
|
||||||
|
onCheckedChange={field.onChange}
|
||||||
|
/>
|
||||||
|
<label
|
||||||
|
htmlFor="remember"
|
||||||
|
className="pl-2 text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
|
||||||
|
>
|
||||||
|
remember me
|
||||||
|
</label>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
control={control}
|
||||||
|
name="rememberMe"
|
||||||
|
defaultValue={rememeberMe}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
return (
|
<div className="flex justify-end">
|
||||||
<div className="ml-[25%]">
|
<Button type="submit">Submit</Button>
|
||||||
<LstCard className="p-3 w-96">
|
</div>
|
||||||
<CardHeader>
|
</div>
|
||||||
<div>
|
</form>
|
||||||
<p className="text-2xl">Login to LST</p>
|
</LstCard>
|
||||||
</div>
|
</div>
|
||||||
</CardHeader>
|
);
|
||||||
<hr className="rounded"></hr>
|
|
||||||
<form onSubmit={handleSubmit(onSubmitLogin)}>
|
|
||||||
<div>
|
|
||||||
<Label htmlFor="username" className="m-1">
|
|
||||||
Username
|
|
||||||
</Label>
|
|
||||||
<Input
|
|
||||||
placeholder="smith001"
|
|
||||||
{...register("username")}
|
|
||||||
className={errors.username ? "border-red-500" : ""}
|
|
||||||
aria-invalid={!!errors.username}
|
|
||||||
/>
|
|
||||||
{errors.username && (
|
|
||||||
<p className="text-red-500 text-sm mt-1">
|
|
||||||
{errors.username.message}
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<>
|
|
||||||
<Label htmlFor={"password"} className="m-1">
|
|
||||||
Password
|
|
||||||
</Label>
|
|
||||||
<Input
|
|
||||||
type="password"
|
|
||||||
{...register("password")}
|
|
||||||
className={
|
|
||||||
errors.password ? "border-red-500" : ""
|
|
||||||
}
|
|
||||||
aria-invalid={!!errors.password}
|
|
||||||
/>
|
|
||||||
{errors.password && (
|
|
||||||
<p className="text-red-500 text-sm mt-1">
|
|
||||||
{errors.password.message}
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
</div>
|
|
||||||
<div className="flex justify-between pt-2">
|
|
||||||
<div className="flex">
|
|
||||||
<Controller
|
|
||||||
render={({ field }) => (
|
|
||||||
<>
|
|
||||||
<Checkbox
|
|
||||||
id="remember"
|
|
||||||
checked={field.value}
|
|
||||||
onCheckedChange={field.onChange}
|
|
||||||
/>
|
|
||||||
<label
|
|
||||||
htmlFor="remember"
|
|
||||||
className="pl-2 text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
|
|
||||||
>
|
|
||||||
remember me
|
|
||||||
</label>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
control={control}
|
|
||||||
name="rememberMe"
|
|
||||||
defaultValue={rememeberMe}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex justify-end">
|
|
||||||
<Button type="submit">Submit</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</LstCard>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default LoginForm;
|
export default LoginForm;
|
||||||
|
|||||||
@@ -1,61 +1,55 @@
|
|||||||
|
import { useSessionStore } from "../../lib/store/sessionStore";
|
||||||
|
import { useModuleStore } from "../../lib/store/useModuleStore";
|
||||||
|
import { moduleActive } from "../../utils/moduleActive";
|
||||||
|
import { hasAccess } from "../../utils/userAccess";
|
||||||
import {
|
import {
|
||||||
Sidebar,
|
Sidebar,
|
||||||
SidebarContent,
|
SidebarContent,
|
||||||
SidebarFooter,
|
SidebarFooter,
|
||||||
SidebarTrigger,
|
SidebarTrigger,
|
||||||
} from "../ui/sidebar";
|
} from "../ui/sidebar";
|
||||||
import { ProductionSideBar } from "./side-components/production";
|
import { AdminSideBar } from "./side-components/admin";
|
||||||
|
import { EomSideBar } from "./side-components/eom";
|
||||||
|
import { ForkliftSideBar } from "./side-components/forklift";
|
||||||
import { Header } from "./side-components/header";
|
import { Header } from "./side-components/header";
|
||||||
import { LogisticsSideBar } from "./side-components/logistics";
|
import { LogisticsSideBar } from "./side-components/logistics";
|
||||||
|
import { ProductionSideBar } from "./side-components/production";
|
||||||
import { QualitySideBar } from "./side-components/quality";
|
import { QualitySideBar } from "./side-components/quality";
|
||||||
import { ForkliftSideBar } from "./side-components/forklift";
|
|
||||||
import { EomSideBar } from "./side-components/eom";
|
|
||||||
import { AdminSideBar } from "./side-components/admin";
|
|
||||||
import { useSessionStore } from "../../lib/store/sessionStore";
|
|
||||||
import { hasAccess } from "../../utils/userAccess";
|
|
||||||
import { moduleActive } from "../../utils/moduleActive";
|
|
||||||
import { useModuleStore } from "../../lib/store/useModuleStore";
|
|
||||||
|
|
||||||
export function AppSidebar() {
|
export function AppSidebar() {
|
||||||
const { user } = useSessionStore();
|
const { user } = useSessionStore();
|
||||||
const { modules } = useModuleStore();
|
const { modules } = useModuleStore();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Sidebar collapsible="icon">
|
<Sidebar collapsible="icon">
|
||||||
<SidebarContent>
|
<SidebarContent>
|
||||||
<Header />
|
<Header />
|
||||||
{moduleActive("production") && (
|
{moduleActive("production") && (
|
||||||
<ProductionSideBar
|
<ProductionSideBar
|
||||||
user={user}
|
user={user}
|
||||||
moduleID={
|
moduleID={
|
||||||
modules.filter((n) => n.name === "production")[0]
|
modules.filter((n) => n.name === "production")[0]
|
||||||
.module_id as string
|
.module_id as string
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{moduleActive("logistics") && (
|
{moduleActive("logistics") && hasAccess(user, "logistics") && (
|
||||||
<LogisticsSideBar
|
<LogisticsSideBar user={user} />
|
||||||
user={user}
|
)}
|
||||||
moduleID={
|
{moduleActive("forklift") && hasAccess(user, "forklift") && (
|
||||||
modules.filter((n) => n.name === "logistics")[0]
|
<ForkliftSideBar />
|
||||||
.module_id as string
|
)}
|
||||||
}
|
{moduleActive("eom") && hasAccess(user, "eom") && <EomSideBar />}
|
||||||
/>
|
{moduleActive("quality") && hasAccess(user, "quality") && (
|
||||||
)}
|
<QualitySideBar />
|
||||||
{moduleActive("forklift") &&
|
)}
|
||||||
hasAccess(user, "forklift", modules) && <ForkliftSideBar />}
|
{moduleActive("admin") && hasAccess(user || [], "admin") && (
|
||||||
{moduleActive("eom") && hasAccess(user, "eom", modules) && (
|
<AdminSideBar />
|
||||||
<EomSideBar />
|
)}
|
||||||
)}
|
</SidebarContent>
|
||||||
{moduleActive("quality") &&
|
<SidebarFooter>
|
||||||
hasAccess(user, "quality", modules) && <QualitySideBar />}
|
<SidebarTrigger />
|
||||||
{moduleActive("admin") && hasAccess(user, "admin", modules) && (
|
</SidebarFooter>
|
||||||
<AdminSideBar />
|
</Sidebar>
|
||||||
)}
|
);
|
||||||
</SidebarContent>
|
|
||||||
<SidebarFooter>
|
|
||||||
<SidebarTrigger />
|
|
||||||
</SidebarFooter>
|
|
||||||
</Sidebar>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,64 +1,53 @@
|
|||||||
import { Barcode, Cylinder, Package, Truck, Command } from "lucide-react";
|
import { Barcode, Command, Cylinder, Package, Truck } from "lucide-react";
|
||||||
import {
|
|
||||||
SidebarGroup,
|
|
||||||
SidebarGroupContent,
|
|
||||||
SidebarGroupLabel,
|
|
||||||
SidebarMenu,
|
|
||||||
SidebarMenuButton,
|
|
||||||
SidebarMenuItem,
|
|
||||||
} from "../../ui/sidebar";
|
|
||||||
import { hasPageAccess } from "@/utils/userAccess";
|
|
||||||
import { User } from "@/types/users";
|
|
||||||
import { useSubModuleStore } from "@/lib/store/useSubModuleStore";
|
import { useSubModuleStore } from "@/lib/store/useSubModuleStore";
|
||||||
|
import { User } from "@/types/users";
|
||||||
|
import { hasPageAccess } from "@/utils/userAccess";
|
||||||
|
import {
|
||||||
|
SidebarGroup,
|
||||||
|
SidebarGroupContent,
|
||||||
|
SidebarGroupLabel,
|
||||||
|
SidebarMenu,
|
||||||
|
SidebarMenuButton,
|
||||||
|
SidebarMenuItem,
|
||||||
|
} from "../../ui/sidebar";
|
||||||
|
|
||||||
const iconMap: any = {
|
const iconMap: any = {
|
||||||
Package: Package,
|
Package: Package,
|
||||||
Truck: Truck,
|
Truck: Truck,
|
||||||
Cylinder: Cylinder,
|
Cylinder: Cylinder,
|
||||||
Barcode: Barcode,
|
Barcode: Barcode,
|
||||||
Command: Command,
|
Command: Command,
|
||||||
};
|
};
|
||||||
|
|
||||||
export function LogisticsSideBar({
|
export function LogisticsSideBar({ user }: { user: User | null }) {
|
||||||
user,
|
const { subModules } = useSubModuleStore();
|
||||||
moduleID,
|
|
||||||
}: {
|
|
||||||
user: User | null;
|
|
||||||
moduleID: string;
|
|
||||||
}) {
|
|
||||||
const { subModules } = useSubModuleStore();
|
|
||||||
|
|
||||||
const items = subModules.filter((m) => m.moduleName === "logistics");
|
const items = subModules.filter((m) => m.moduleName === "logistics");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SidebarGroup>
|
<SidebarGroup>
|
||||||
<SidebarGroupLabel>Logistics</SidebarGroupLabel>
|
<SidebarGroupLabel>Logistics</SidebarGroupLabel>
|
||||||
<SidebarGroupContent>
|
<SidebarGroupContent>
|
||||||
<SidebarMenu>
|
<SidebarMenu>
|
||||||
{items.map((item) => {
|
{items.map((item) => {
|
||||||
const Icon = iconMap[item.icon];
|
const Icon = iconMap[item.icon];
|
||||||
return (
|
return (
|
||||||
<SidebarMenuItem key={item.submodule_id}>
|
<SidebarMenuItem key={item.submodule_id}>
|
||||||
<>
|
<>
|
||||||
{hasPageAccess(
|
{hasPageAccess(user, item.roles, item.name) && (
|
||||||
user,
|
<SidebarMenuButton asChild>
|
||||||
item.roles,
|
<a href={item.link}>
|
||||||
moduleID
|
<Icon />
|
||||||
) &&
|
<span>{item.name}</span>
|
||||||
item.active && (
|
</a>
|
||||||
<SidebarMenuButton asChild>
|
</SidebarMenuButton>
|
||||||
<a href={item.link}>
|
)}
|
||||||
<Icon />
|
</>
|
||||||
<span>{item.name}</span>
|
</SidebarMenuItem>
|
||||||
</a>
|
);
|
||||||
</SidebarMenuButton>
|
})}
|
||||||
)}
|
</SidebarMenu>
|
||||||
</>
|
</SidebarGroupContent>
|
||||||
</SidebarMenuItem>
|
</SidebarGroup>
|
||||||
);
|
);
|
||||||
})}
|
|
||||||
</SidebarMenu>
|
|
||||||
</SidebarGroupContent>
|
|
||||||
</SidebarGroup>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,3 @@
|
|||||||
import { LstCard } from "@/components/extendedUI/LstCard";
|
|
||||||
import { Button } from "@/components/ui/button";
|
|
||||||
import { CardHeader } from "@/components/ui/card";
|
|
||||||
import { Input } from "@/components/ui/input";
|
|
||||||
import { Label } from "@/components/ui/label";
|
|
||||||
import {
|
|
||||||
Tooltip,
|
|
||||||
TooltipContent,
|
|
||||||
TooltipProvider,
|
|
||||||
TooltipTrigger,
|
|
||||||
} from "@/components/ui/tooltip";
|
|
||||||
import { getStockSilo } from "@/utils/querys/logistics/siloAdjustments/getStockSilo";
|
|
||||||
import { useForm } from "@tanstack/react-form";
|
import { useForm } from "@tanstack/react-form";
|
||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
import { Link } from "@tanstack/react-router";
|
import { Link } from "@tanstack/react-router";
|
||||||
@@ -18,246 +6,222 @@ import { format } from "date-fns";
|
|||||||
import { CircleAlert } from "lucide-react";
|
import { CircleAlert } from "lucide-react";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import ChartData from "./ChartData";
|
import { LstCard } from "@/components/extendedUI/LstCard";
|
||||||
import { AttachSilo } from "./AttachSilo";
|
import { Button } from "@/components/ui/button";
|
||||||
import { DetachSilo } from "./DetachSilo";
|
import { CardHeader } from "@/components/ui/card";
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
import { Label } from "@/components/ui/label";
|
||||||
|
import {
|
||||||
|
Tooltip,
|
||||||
|
TooltipContent,
|
||||||
|
TooltipProvider,
|
||||||
|
TooltipTrigger,
|
||||||
|
} from "@/components/ui/tooltip";
|
||||||
import { useSessionStore } from "@/lib/store/sessionStore";
|
import { useSessionStore } from "@/lib/store/sessionStore";
|
||||||
import { useModuleStore } from "@/lib/store/useModuleStore";
|
|
||||||
import { useGetUserRoles } from "@/lib/store/useGetRoles";
|
import { useGetUserRoles } from "@/lib/store/useGetRoles";
|
||||||
|
import { useModuleStore } from "@/lib/store/useModuleStore";
|
||||||
|
import { getStockSilo } from "@/utils/querys/logistics/siloAdjustments/getStockSilo";
|
||||||
|
import { AttachSilo } from "./AttachSilo";
|
||||||
|
import ChartData from "./ChartData";
|
||||||
|
import { DetachSilo } from "./DetachSilo";
|
||||||
|
|
||||||
export default function SiloCard(data: any) {
|
export default function SiloCard(data: any) {
|
||||||
const token = localStorage.getItem("auth_token");
|
const [submitting, setSubmitting] = useState(false);
|
||||||
const [submitting, setSubmitting] = useState(false);
|
const { refetch } = useQuery(getStockSilo());
|
||||||
const { refetch } = useQuery(getStockSilo());
|
const { user } = useSessionStore();
|
||||||
const { user } = useSessionStore();
|
const { userRoles } = useGetUserRoles();
|
||||||
const { userRoles } = useGetUserRoles();
|
const { modules } = useModuleStore();
|
||||||
const { modules } = useModuleStore();
|
const silo = data.silo;
|
||||||
const silo = data.silo;
|
|
||||||
|
|
||||||
// roles that can do the silo adjustments
|
// roles that can do the silo adjustments
|
||||||
const roles = ["systemAdmin", "technician", "admin", "manager"];
|
const roles = ["systemAdmin", "technician", "admin", "manager"];
|
||||||
|
|
||||||
const module = modules.filter((n) => n.name === "logistics");
|
const module = modules.filter((n) => n.name === "logistics");
|
||||||
|
|
||||||
const accessRoles = userRoles.filter(
|
const accessRoles = userRoles.filter(
|
||||||
(n) => n.module_id === module[0]?.module_id
|
(n: any) => n.module === module[0]?.name,
|
||||||
) as any;
|
) as any;
|
||||||
|
|
||||||
const form = useForm({
|
const form = useForm({
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
newLevel: "",
|
newLevel: "",
|
||||||
},
|
},
|
||||||
onSubmit: async ({ value }) => {
|
onSubmit: async ({ value }) => {
|
||||||
setSubmitting(true);
|
setSubmitting(true);
|
||||||
const dataToSubmit = {
|
const dataToSubmit = {
|
||||||
quantity: parseFloat(value.newLevel),
|
quantity: parseFloat(value.newLevel),
|
||||||
warehouseId: silo.WarehouseID,
|
warehouseId: silo.WarehouseID,
|
||||||
laneId: silo.LocationID,
|
laneId: silo.LocationID,
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const res = await axios.post(
|
const res = await axios.post(
|
||||||
"/api/logistics/createsiloadjustment",
|
"/api/logistics/createsiloadjustment",
|
||||||
dataToSubmit,
|
dataToSubmit,
|
||||||
{ headers: { Authorization: `Bearer ${token}` } }
|
{ withCredentials: true },
|
||||||
);
|
);
|
||||||
//console.log(res.data);
|
//console.log(res.data);
|
||||||
|
|
||||||
if (res.data.success) {
|
if (res.data.success) {
|
||||||
toast.success(res.data.message);
|
toast.success(res.data.message);
|
||||||
refetch();
|
refetch();
|
||||||
form.reset();
|
form.reset();
|
||||||
}
|
}
|
||||||
if (!res.data.success && res.data.data?.status === 400) {
|
if (!res.data.success && res.data.data?.status === 400) {
|
||||||
if (res.data.data.status === 400) {
|
if (res.data.data.status === 400) {
|
||||||
toast.error(res.data.data.data.errors[0].message);
|
toast.error(res.data.data.data.errors[0].message);
|
||||||
}
|
}
|
||||||
} else if (!res.data.success) {
|
} else if (!res.data.success) {
|
||||||
toast.error(res.data.message);
|
toast.error(res.data.message);
|
||||||
}
|
}
|
||||||
setSubmitting(false);
|
setSubmitting(false);
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
//console.log(error);
|
//console.log(error);
|
||||||
if (error.status === 401) {
|
if (error.status === 401) {
|
||||||
toast.error(error.response.statusText);
|
toast.error(error.response.statusText);
|
||||||
setSubmitting(false);
|
setSubmitting(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(accessRoles);
|
return (
|
||||||
return (
|
<LstCard>
|
||||||
<LstCard>
|
<div className="flex flex-row">
|
||||||
<div className="flex flex-row">
|
<LstCard className="grow m-1 max-w-[400px]">
|
||||||
<LstCard className="grow m-1 max-w-[400px]">
|
<CardHeader>{silo.Description}</CardHeader>
|
||||||
<CardHeader>{silo.Description}</CardHeader>
|
<div className="m-1">
|
||||||
<div className="m-1">
|
<hr className="m-2" />
|
||||||
<hr className="m-2" />
|
<span>Current Stock: </span>
|
||||||
<span>Current Stock: </span>
|
{silo.Stock_Total}
|
||||||
{silo.Stock_Total}
|
<hr className="m-2" />
|
||||||
<hr className="m-2" />
|
<span>Last date adjusted </span>
|
||||||
<span>Last date adjusted </span>
|
{format(silo.LastAdjustment, "M/dd/yyyy")}
|
||||||
{format(silo.LastAdjustment, "M/dd/yyyy")}
|
<hr className="m-2" />
|
||||||
<hr className="m-2" />
|
</div>
|
||||||
</div>
|
<div>
|
||||||
<div>
|
{silo.Stock_Total === 0 ? (
|
||||||
{silo.Stock_Total === 0 ? (
|
<div className="flex justify-center flex-col">
|
||||||
<div className="flex justify-center flex-col">
|
<span>
|
||||||
<span>
|
The silo is currently empty you will not be able to do an
|
||||||
The silo is currently empty you will not be
|
adjustment until you have received material in.
|
||||||
able to do an adjustment until you have
|
</span>
|
||||||
received material in.
|
<hr />
|
||||||
</span>
|
<ul>
|
||||||
<hr />
|
<li>
|
||||||
<ul>
|
-Someone click "Take inventory on a empty location" in
|
||||||
<li>
|
stock.
|
||||||
-Someone click "Take inventory on a
|
</li>
|
||||||
empty location" in stock.
|
<li>
|
||||||
</li>
|
-Silo virtualy ran empty due to production over consumption.
|
||||||
<li>
|
</li>
|
||||||
-Silo virtualy ran empty due to
|
<li>
|
||||||
production over consumption.
|
-Someone forgot to move a railcar compartment over to this
|
||||||
</li>
|
location.
|
||||||
<li>
|
</li>
|
||||||
-Someone forgot to move a railcar
|
</ul>
|
||||||
compartment over to this location.
|
</div>
|
||||||
</li>
|
) : (
|
||||||
</ul>
|
<>
|
||||||
</div>
|
{user && roles.includes(accessRoles[0]?.role) && (
|
||||||
) : (
|
<form
|
||||||
<>
|
onSubmit={(e) => {
|
||||||
{user &&
|
e.preventDefault();
|
||||||
roles.includes(accessRoles[0]?.role) && (
|
e.stopPropagation();
|
||||||
<form
|
}}
|
||||||
onSubmit={(e) => {
|
>
|
||||||
e.preventDefault();
|
<form.Field
|
||||||
e.stopPropagation();
|
name="newLevel"
|
||||||
}}
|
validators={{
|
||||||
>
|
// We can choose between form-wide and field-specific validators
|
||||||
<form.Field
|
onChange: ({ value }) =>
|
||||||
name="newLevel"
|
value.length > 1
|
||||||
validators={{
|
? undefined
|
||||||
// We can choose between form-wide and field-specific validators
|
: "You must enter a value greate than 1",
|
||||||
onChange: ({ value }) =>
|
}}
|
||||||
value.length > 1
|
children={(field) => {
|
||||||
? undefined
|
return (
|
||||||
: "You must enter a value greate than 1",
|
<div className="m-2 min-w-48 max-w-96 p-2">
|
||||||
}}
|
<div className="flex flex-row">
|
||||||
children={(field) => {
|
<Label htmlFor="newLevel">New level</Label>
|
||||||
return (
|
<div>
|
||||||
<div className="m-2 min-w-48 max-w-96 p-2">
|
<Disclaimer />
|
||||||
<div className="flex flex-row">
|
</div>
|
||||||
<Label htmlFor="newLevel">
|
</div>
|
||||||
New level
|
<div className="flex flex-row">
|
||||||
</Label>
|
<Input
|
||||||
<div>
|
name={field.name}
|
||||||
<Disclaimer />
|
value={field.state.value}
|
||||||
</div>
|
onBlur={field.handleBlur}
|
||||||
</div>
|
type="decimal"
|
||||||
<div className="flex flex-row">
|
onChange={(e) =>
|
||||||
<Input
|
field.handleChange(e.target.value)
|
||||||
name={
|
}
|
||||||
field.name
|
/>
|
||||||
}
|
<Button
|
||||||
value={
|
className="ml-1"
|
||||||
field
|
variant="outline"
|
||||||
.state
|
type="submit"
|
||||||
.value
|
onClick={form.handleSubmit}
|
||||||
}
|
disabled={submitting}
|
||||||
onBlur={
|
>
|
||||||
field.handleBlur
|
{submitting ? (
|
||||||
}
|
<span className="w-24">Submitting...</span>
|
||||||
type="decimal"
|
) : (
|
||||||
onChange={(
|
<span className="w-24">Submit</span>
|
||||||
e
|
)}
|
||||||
) =>
|
</Button>
|
||||||
field.handleChange(
|
</div>
|
||||||
e
|
|
||||||
.target
|
|
||||||
.value
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
className="ml-1"
|
|
||||||
variant="outline"
|
|
||||||
type="submit"
|
|
||||||
onClick={
|
|
||||||
form.handleSubmit
|
|
||||||
}
|
|
||||||
disabled={
|
|
||||||
submitting
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{submitting ? (
|
|
||||||
<span className="w-24">
|
|
||||||
Submitting...
|
|
||||||
</span>
|
|
||||||
) : (
|
|
||||||
<span className="w-24">
|
|
||||||
Submit
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{field.state.meta
|
{field.state.meta.errors.length ? (
|
||||||
.errors
|
<em>{field.state.meta.errors.join(",")}</em>
|
||||||
.length ? (
|
) : null}
|
||||||
<em>
|
</div>
|
||||||
{field.state.meta.errors.join(
|
);
|
||||||
","
|
}}
|
||||||
)}
|
/>
|
||||||
</em>
|
</form>
|
||||||
) : null}
|
)}
|
||||||
</div>
|
</>
|
||||||
);
|
)}
|
||||||
}}
|
</div>
|
||||||
/>
|
</LstCard>
|
||||||
</form>
|
<div className="grow max-w-[600px]">
|
||||||
)}
|
<ChartData laneId={silo.LocationID} />
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</LstCard>
|
|
||||||
<div className="grow max-w-[600px]">
|
|
||||||
<ChartData laneId={silo.LocationID} />
|
|
||||||
|
|
||||||
<div className="flex justify-end m-1 gap-3">
|
<div className="flex justify-end m-1 gap-3">
|
||||||
<AttachSilo silo={silo} />
|
<AttachSilo silo={silo} />
|
||||||
<DetachSilo silo={silo} />
|
<DetachSilo silo={silo} />
|
||||||
<Button variant="outline">
|
<Button variant="outline">
|
||||||
<Link
|
<Link
|
||||||
to={"/siloAdjustments/$hist"}
|
to={"/siloAdjustments/$hist"}
|
||||||
params={{ hist: silo.LocationID }}
|
params={{ hist: silo.LocationID }}
|
||||||
>
|
>
|
||||||
Historical Data
|
Historical Data
|
||||||
</Link>
|
</Link>
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</LstCard>
|
</LstCard>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Disclaimer = () => {
|
const Disclaimer = () => {
|
||||||
return (
|
return (
|
||||||
<TooltipProvider>
|
<TooltipProvider>
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<CircleAlert className="ml-1 w-[14px]" />
|
<CircleAlert className="ml-1 w-[14px]" />
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipContent className="max-w-48">
|
<TooltipContent className="max-w-48">
|
||||||
<p className="text-pretty">
|
<p className="text-pretty">
|
||||||
If you have had this page open for a period of time
|
If you have had this page open for a period of time before
|
||||||
before submitting your data, there is a chance that the
|
submitting your data, there is a chance that the stock levels will
|
||||||
stock levels will be different from the ones you see
|
be different from the ones you see above
|
||||||
above
|
</p>
|
||||||
</p>
|
</TooltipContent>
|
||||||
</TooltipContent>
|
</Tooltip>
|
||||||
</Tooltip>
|
</TooltipProvider>
|
||||||
</TooltipProvider>
|
);
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,273 +1,256 @@
|
|||||||
|
import { useQuery } from "@tanstack/react-query";
|
||||||
import { LstCard } from "@/components/extendedUI/LstCard";
|
import { LstCard } from "@/components/extendedUI/LstCard";
|
||||||
|
import { ScrollArea } from "@/components/ui/scroll-area";
|
||||||
import { Skeleton } from "@/components/ui/skeleton";
|
import { Skeleton } from "@/components/ui/skeleton";
|
||||||
import {
|
import {
|
||||||
Table,
|
Table,
|
||||||
TableBody,
|
TableBody,
|
||||||
TableCell,
|
TableCell,
|
||||||
TableHead,
|
TableHead,
|
||||||
TableHeader,
|
TableHeader,
|
||||||
TableRow,
|
TableRow,
|
||||||
} from "@/components/ui/table";
|
} from "@/components/ui/table";
|
||||||
import { useSessionStore } from "@/lib/store/sessionStore";
|
import { useSessionStore } from "@/lib/store/sessionStore";
|
||||||
|
import { useGetUserRoles } from "@/lib/store/useGetRoles";
|
||||||
|
import { useModuleStore } from "@/lib/store/useModuleStore";
|
||||||
import { useSettingStore } from "@/lib/store/useSettings";
|
import { useSettingStore } from "@/lib/store/useSettings";
|
||||||
import { LotType } from "@/types/lots";
|
import { LotType } from "@/types/lots";
|
||||||
import { getlots } from "@/utils/querys/production/lots";
|
import { getlots } from "@/utils/querys/production/lots";
|
||||||
import { useQuery } from "@tanstack/react-query";
|
|
||||||
import ManualPrint from "./ManualPrinting/ManualPrint";
|
import ManualPrint from "./ManualPrinting/ManualPrint";
|
||||||
import ManualPrintForm from "./ManualPrinting/ManualPrintForm";
|
import ManualPrintForm from "./ManualPrinting/ManualPrintForm";
|
||||||
import { ScrollArea } from "@/components/ui/scroll-area";
|
|
||||||
import { useGetUserRoles } from "@/lib/store/useGetRoles";
|
|
||||||
import { useModuleStore } from "@/lib/store/useModuleStore";
|
|
||||||
|
|
||||||
let lotColumns = [
|
let lotColumns = [
|
||||||
{
|
{
|
||||||
key: "MachineDescription",
|
key: "MachineDescription",
|
||||||
label: "Machine",
|
label: "Machine",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "AV",
|
key: "AV",
|
||||||
label: "AV",
|
label: "AV",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "Alias",
|
key: "Alias",
|
||||||
label: "AvDescription",
|
label: "AvDescription",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "lot",
|
key: "lot",
|
||||||
label: "LotNumber",
|
label: "LotNumber",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "ProlinkLot",
|
key: "ProlinkLot",
|
||||||
label: "ProlinkLot",
|
label: "ProlinkLot",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "PlannedQTY",
|
key: "PlannedQTY",
|
||||||
label: "PlannedQTY",
|
label: "PlannedQTY",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "Produced",
|
key: "Produced",
|
||||||
label: "Produced",
|
label: "Produced",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "Remaining",
|
key: "Remaining",
|
||||||
label: "Remaining",
|
label: "Remaining",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "overPrinting",
|
key: "overPrinting",
|
||||||
label: "Overprinting",
|
label: "Overprinting",
|
||||||
},
|
},
|
||||||
// {
|
// {
|
||||||
// key: "lastProlinkUpdate",
|
// key: "lastProlinkUpdate",
|
||||||
// label: "Last ProlinkCheck",
|
// label: "Last ProlinkCheck",
|
||||||
// },
|
// },
|
||||||
// {
|
// {
|
||||||
// key: "printLabel",
|
// key: "printLabel",
|
||||||
// label: "Print Label",
|
// label: "Print Label",
|
||||||
// },
|
// },
|
||||||
];
|
];
|
||||||
export default function Lots() {
|
export default function Lots() {
|
||||||
const { data, isError, isLoading } = useQuery(getlots());
|
const { data, isError, isLoading } = useQuery(getlots());
|
||||||
const { user } = useSessionStore();
|
const { user } = useSessionStore();
|
||||||
const { settings } = useSettingStore();
|
const { settings } = useSettingStore();
|
||||||
const { userRoles } = useGetUserRoles();
|
const { userRoles } = useGetUserRoles();
|
||||||
const { modules } = useModuleStore();
|
const { modules } = useModuleStore();
|
||||||
|
|
||||||
const server = settings.filter((n) => n.name === "server")[0]?.value || "";
|
const server = settings.filter((n) => n.name === "server")[0]?.value || "";
|
||||||
|
|
||||||
const roles = ["systemAdmin", "technician", "admin", "manager", "operator"];
|
const roles = ["systemAdmin", "technician", "admin", "manager", "operator"];
|
||||||
const lotdata = data ? data : [];
|
const lotdata = data ? data : [];
|
||||||
|
|
||||||
const module = modules.filter((n) => n.name === "logistics");
|
const module = modules.filter((n) => n.name === "logistics");
|
||||||
|
|
||||||
const accessRoles = userRoles.filter(
|
const accessRoles = userRoles.filter(
|
||||||
(n) => n.module_id === module[0]?.module_id
|
(n: any) => n.module === module[0]?.name,
|
||||||
) as any;
|
) as any;
|
||||||
|
|
||||||
if (user && roles.includes(accessRoles[0]?.role)) {
|
if (user && roles.includes(accessRoles[0]?.role)) {
|
||||||
//width = 1280;
|
//width = 1280;
|
||||||
const checkCol = lotColumns.some((l) => l.key === "printLabel");
|
const checkCol = lotColumns.some((l) => l.key === "printLabel");
|
||||||
if (!checkCol) {
|
if (!checkCol) {
|
||||||
lotColumns = [
|
lotColumns = [
|
||||||
...lotColumns,
|
...lotColumns,
|
||||||
{
|
{
|
||||||
key: "printLabel",
|
key: "printLabel",
|
||||||
label: "Print Label",
|
label: "Print Label",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isError) {
|
if (isError) {
|
||||||
return (
|
return (
|
||||||
<div className="m-2 p-2 min-h-2/5">
|
<div className="m-2 p-2 min-h-2/5">
|
||||||
<ScrollArea className="max-h-1/2 rounded-md border p-4">
|
<ScrollArea className="max-h-1/2 rounded-md border p-4">
|
||||||
<LstCard>
|
<LstCard>
|
||||||
<p className="text-center">Current Assigned lots</p>
|
<p className="text-center">Current Assigned lots</p>
|
||||||
<Table>
|
<Table>
|
||||||
<TableHeader>
|
<TableHeader>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
{lotColumns.map((l) => (
|
{lotColumns.map((l) => (
|
||||||
<TableHead key={l.key}>
|
<TableHead key={l.key}>{l.label}</TableHead>
|
||||||
{l.label}
|
))}
|
||||||
</TableHead>
|
</TableRow>
|
||||||
))}
|
</TableHeader>
|
||||||
</TableRow>
|
|
||||||
</TableHeader>
|
|
||||||
|
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{Array(10)
|
{Array(10)
|
||||||
.fill(0)
|
.fill(0)
|
||||||
.map((_, i) => (
|
.map((_, i) => (
|
||||||
<TableRow key={i}>
|
<TableRow key={i}>
|
||||||
<TableCell className="font-medium">
|
<TableCell className="font-medium">
|
||||||
<Skeleton className="h-4" />
|
<Skeleton className="h-4" />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<Skeleton className="h-4" />
|
<Skeleton className="h-4" />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<Skeleton className="h-4" />
|
<Skeleton className="h-4" />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<Skeleton className="h-4" />
|
<Skeleton className="h-4" />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<Skeleton className="h-4" />
|
<Skeleton className="h-4" />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<Skeleton className="h-4" />
|
<Skeleton className="h-4" />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<Skeleton className="h-4" />
|
<Skeleton className="h-4" />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<Skeleton className="h-4" />
|
<Skeleton className="h-4" />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<Skeleton className="h-4" />
|
<Skeleton className="h-4" />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
))}
|
))}
|
||||||
</TableBody>
|
</TableBody>
|
||||||
</Table>
|
</Table>
|
||||||
</LstCard>
|
</LstCard>
|
||||||
</ScrollArea>
|
</ScrollArea>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<LstCard className="m-2 p-2 min-h-2/5">
|
<LstCard className="m-2 p-2 min-h-2/5">
|
||||||
<ScrollArea className="h-[400px]">
|
<ScrollArea className="h-[400px]">
|
||||||
<p className="text-center">Current Assigned lots</p>
|
<p className="text-center">Current Assigned lots</p>
|
||||||
<Table>
|
<Table>
|
||||||
<TableHeader>
|
<TableHeader>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
{lotColumns.map((l) => (
|
{lotColumns.map((l) => (
|
||||||
<TableHead key={l.key}>{l.label}</TableHead>
|
<TableHead key={l.key}>{l.label}</TableHead>
|
||||||
))}
|
))}
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHeader>
|
</TableHeader>
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<>
|
<>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{Array(10)
|
{Array(10)
|
||||||
.fill(0)
|
.fill(0)
|
||||||
.map((_, i) => (
|
.map((_, i) => (
|
||||||
<TableRow key={i}>
|
<TableRow key={i}>
|
||||||
<TableCell className="font-medium">
|
<TableCell className="font-medium">
|
||||||
<Skeleton className="h-4" />
|
<Skeleton className="h-4" />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<Skeleton className="h-4" />
|
<Skeleton className="h-4" />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<Skeleton className="h-4" />
|
<Skeleton className="h-4" />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<Skeleton className="h-4" />
|
<Skeleton className="h-4" />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<Skeleton className="h-4" />
|
<Skeleton className="h-4" />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<Skeleton className="h-4" />
|
<Skeleton className="h-4" />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<Skeleton className="h-4" />
|
<Skeleton className="h-4" />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<Skeleton className="h-4" />
|
<Skeleton className="h-4" />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<Skeleton className="h-4" />
|
<Skeleton className="h-4" />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
))}
|
))}
|
||||||
</TableBody>
|
</TableBody>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{lotdata.map((lot: LotType) => (
|
{lotdata.map((lot: LotType) => (
|
||||||
<TableRow key={lot.LabelOnlineID}>
|
<TableRow key={lot.LabelOnlineID}>
|
||||||
<TableCell className="font-medium">
|
<TableCell className="font-medium">
|
||||||
{lot.MachineLocation}
|
{lot.MachineLocation}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className="font-medium">
|
<TableCell className="font-medium">{lot.AV}</TableCell>
|
||||||
{lot.AV}
|
<TableCell className="font-medium">{lot.Alias}</TableCell>
|
||||||
</TableCell>
|
<TableCell
|
||||||
<TableCell className="font-medium">
|
className={`font-medium ${lot.ProlinkLot != lot.lot ? "text-red-500" : ""}`}
|
||||||
{lot.Alias}
|
>
|
||||||
</TableCell>
|
{lot.lot}
|
||||||
<TableCell
|
</TableCell>
|
||||||
className={`font-medium ${lot.ProlinkLot != lot.lot ? "text-red-500" : ""}`}
|
<TableCell
|
||||||
>
|
className={`font-medium ${lot.ProlinkLot != lot.lot ? "text-red-500" : ""}`}
|
||||||
{lot.lot}
|
>
|
||||||
</TableCell>
|
{lot.ProlinkLot}
|
||||||
<TableCell
|
</TableCell>
|
||||||
className={`font-medium ${lot.ProlinkLot != lot.lot ? "text-red-500" : ""}`}
|
<TableCell className="font-medium">
|
||||||
>
|
{lot.PlannedQTY}
|
||||||
{lot.ProlinkLot}
|
</TableCell>
|
||||||
</TableCell>
|
<TableCell className="font-medium">{lot.Produced}</TableCell>
|
||||||
<TableCell className="font-medium">
|
<TableCell className="font-medium">{lot.Remaining}</TableCell>
|
||||||
{lot.PlannedQTY}
|
<TableCell className="font-medium">
|
||||||
</TableCell>
|
{lot.overPrinting}
|
||||||
<TableCell className="font-medium">
|
</TableCell>
|
||||||
{lot.Produced}
|
{user && roles.includes(accessRoles[0]?.role) && (
|
||||||
</TableCell>
|
<>
|
||||||
<TableCell className="font-medium">
|
{server === "usday1vms006" || server === "localhost" ? (
|
||||||
{lot.Remaining}
|
<>
|
||||||
</TableCell>
|
<TableCell className="flex justify-center">
|
||||||
<TableCell className="font-medium">
|
<ManualPrintForm />
|
||||||
{lot.overPrinting}
|
</TableCell>
|
||||||
</TableCell>
|
</>
|
||||||
{user &&
|
) : (
|
||||||
roles.includes(
|
<TableCell className="flex justify-center">
|
||||||
accessRoles[0]?.role
|
<ManualPrint lot={lot} />
|
||||||
) && (
|
</TableCell>
|
||||||
<>
|
)}
|
||||||
{server === "usday1vms006" ||
|
</>
|
||||||
server === "localhost" ? (
|
)}
|
||||||
<>
|
</TableRow>
|
||||||
<TableCell className="flex justify-center">
|
))}
|
||||||
<ManualPrintForm />
|
</TableBody>
|
||||||
</TableCell>
|
)}
|
||||||
</>
|
</Table>
|
||||||
) : (
|
</ScrollArea>
|
||||||
<TableCell className="flex justify-center">
|
</LstCard>
|
||||||
<ManualPrint
|
);
|
||||||
lot={lot}
|
|
||||||
/>
|
|
||||||
</TableCell>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</TableRow>
|
|
||||||
))}
|
|
||||||
</TableBody>
|
|
||||||
)}
|
|
||||||
</Table>
|
|
||||||
</ScrollArea>
|
|
||||||
</LstCard>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,32 +1,67 @@
|
|||||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||||
import { useModuleStore } from "../../lib/store/useModuleStore";
|
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { useSettingStore } from "@/lib/store/useSettings";
|
import { useSessionStore } from "@/lib/store/sessionStore";
|
||||||
|
import { useAuthStore } from "@/lib/store/useAuthStore";
|
||||||
import { useGetUserRoles } from "@/lib/store/useGetRoles";
|
import { useGetUserRoles } from "@/lib/store/useGetRoles";
|
||||||
|
import { useSettingStore } from "@/lib/store/useSettings";
|
||||||
import { useSubModuleStore } from "@/lib/store/useSubModuleStore";
|
import { useSubModuleStore } from "@/lib/store/useSubModuleStore";
|
||||||
|
import { useModuleStore } from "../../lib/store/useModuleStore";
|
||||||
|
|
||||||
const queryClient = new QueryClient();
|
const queryClient = new QueryClient();
|
||||||
|
|
||||||
export const SessionProvider = ({
|
const reAuth = async (username: string, password: string) => {
|
||||||
children,
|
const { setSession } = useSessionStore();
|
||||||
}: {
|
try {
|
||||||
children: React.ReactNode;
|
const response = await fetch("/api/auth/login", {
|
||||||
}) => {
|
method: "POST",
|
||||||
const { fetchModules } = useModuleStore();
|
headers: {
|
||||||
const { fetchSettings } = useSettingStore();
|
"Content-Type": "application/json",
|
||||||
const { fetchUserRoles } = useGetUserRoles();
|
},
|
||||||
const { fetchSubModules } = useSubModuleStore();
|
body: JSON.stringify({
|
||||||
|
username: username,
|
||||||
|
password: password,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
const data = await response.json();
|
||||||
fetchModules();
|
|
||||||
fetchSettings();
|
|
||||||
fetchUserRoles();
|
|
||||||
fetchSubModules();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
// Store token in localStorage
|
||||||
<QueryClientProvider client={queryClient}>
|
// localStorage.setItem("auth_token", data.data.token);
|
||||||
{children}
|
if (data.success) {
|
||||||
</QueryClientProvider>
|
const prod = btoa(`${username.toLowerCase()}:${password}`);
|
||||||
);
|
const prodUser = { ...data.user, prod: prod };
|
||||||
|
|
||||||
|
setSession(prodUser, data.data.token);
|
||||||
|
}
|
||||||
|
|
||||||
|
//console.log(data);
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
export const SessionProvider = ({
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
children: React.ReactNode;
|
||||||
|
}) => {
|
||||||
|
const { fetchModules } = useModuleStore();
|
||||||
|
const { fetchSettings } = useSettingStore();
|
||||||
|
const { fetchUserRoles } = useGetUserRoles();
|
||||||
|
const { fetchSubModules } = useSubModuleStore();
|
||||||
|
const { username, password } = useAuthStore();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (username !== "") {
|
||||||
|
reAuth(username, password);
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchModules();
|
||||||
|
fetchSettings();
|
||||||
|
fetchUserRoles();
|
||||||
|
fetchSubModules();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,16 +1,19 @@
|
|||||||
import {useSessionStore} from "@/lib/store/sessionStore";
|
import { useRouter } from "@tanstack/react-router";
|
||||||
import {useRouter} from "@tanstack/react-router";
|
import { useSessionStore } from "@/lib/store/sessionStore";
|
||||||
|
import { useAuthStore } from "@/lib/store/useAuthStore";
|
||||||
|
|
||||||
export const useLogout = () => {
|
export const useLogout = () => {
|
||||||
const {clearSession} = useSessionStore();
|
const { clearSession } = useSessionStore();
|
||||||
const router = useRouter();
|
const { clearUser } = useAuthStore();
|
||||||
const logout = async () => {
|
const router = useRouter();
|
||||||
router.invalidate();
|
const logout = async () => {
|
||||||
router.clearCache();
|
router.invalidate();
|
||||||
clearSession();
|
router.clearCache();
|
||||||
|
clearSession();
|
||||||
|
clearUser();
|
||||||
|
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
};
|
};
|
||||||
|
|
||||||
return logout;
|
return logout;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,60 +1,87 @@
|
|||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
import { useSessionStore } from "../lib/store/sessionStore";
|
import axios from "axios";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
|
import { useSessionStore } from "../lib/store/sessionStore";
|
||||||
|
|
||||||
const fetchSession = async () => {
|
const fetchSession = async () => {
|
||||||
const token = localStorage.getItem("auth_token");
|
const token = localStorage.getItem("auth_token");
|
||||||
|
|
||||||
if (!token) {
|
if (!token) {
|
||||||
throw new Error("No token found");
|
throw new Error("No token found");
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
const res = await axios.get("/api/auth/session", {
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
withCredentials: true,
|
||||||
|
});
|
||||||
|
|
||||||
const res = await fetch("/api/auth/session", {
|
if (res.status === 401) {
|
||||||
headers: {
|
localStorage.removeItem("auth_token");
|
||||||
"Content-Type": "application/json",
|
// remove these for a while if no session just until fully to 2.0 and clearly no one has ran lstv1 in a long time
|
||||||
Authorization: `Bearer ${token}`,
|
localStorage.removeItem("ally-supports-cache");
|
||||||
},
|
localStorage.removeItem("auth-storage");
|
||||||
});
|
localStorage.removeItem("nextauth.message");
|
||||||
// console.log(res);
|
localStorage.removeItem("prod");
|
||||||
if (!res.ok) {
|
|
||||||
localStorage.removeItem("auth_token");
|
|
||||||
// remove these for a while if no session just until fully to 2.0 and clearly no one has ran lstv1 in a long time
|
|
||||||
localStorage.removeItem("ally-supports-cache");
|
|
||||||
localStorage.removeItem("auth-storage");
|
|
||||||
localStorage.removeItem("nextauth.message");
|
|
||||||
localStorage.removeItem("prod");
|
|
||||||
|
|
||||||
throw new Error("Session not found");
|
throw new Error("Session not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
return res.json();
|
const userRoles = await axios.get("/api/auth/getuseraccess", {
|
||||||
|
withCredentials: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const userData = {
|
||||||
|
...res.data,
|
||||||
|
data: {
|
||||||
|
...res.data.data,
|
||||||
|
user: {
|
||||||
|
...res.data.data.user,
|
||||||
|
roles: userRoles.data.data,
|
||||||
|
},
|
||||||
|
token: "Just a token as this will be removed in the future",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return userData;
|
||||||
|
} catch (error) {
|
||||||
|
localStorage.removeItem("auth_token");
|
||||||
|
// remove these for a while if no session just until fully to 2.0 and clearly no one has ran lstv1 in a long time
|
||||||
|
localStorage.removeItem("ally-supports-cache");
|
||||||
|
localStorage.removeItem("auth-storage");
|
||||||
|
localStorage.removeItem("nextauth.message");
|
||||||
|
localStorage.removeItem("prod");
|
||||||
|
|
||||||
|
throw new Error("Session not found");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useSession = () => {
|
export const useSession = () => {
|
||||||
const { setSession, clearSession, token } = useSessionStore();
|
const { setSession, clearSession, token } = useSessionStore();
|
||||||
|
|
||||||
// Fetch session only if token is available
|
// Fetch session only if token is available
|
||||||
const { data, status, error } = useQuery({
|
const { data, status, error } = useQuery({
|
||||||
queryKey: ["session"],
|
queryKey: ["session"],
|
||||||
queryFn: fetchSession,
|
queryFn: fetchSession,
|
||||||
enabled: !!token, // Prevents query if token is null
|
enabled: !!token, // Prevents query if token is null
|
||||||
staleTime: 60 * 1000,
|
staleTime: 60 * 1000,
|
||||||
gcTime: 10 * 60 * 1000, // 10 mins
|
//gcTime: 10 * 60 * 1000, // 10 mins
|
||||||
refetchOnWindowFocus: true,
|
refetchOnWindowFocus: true,
|
||||||
//refetchInterval: 1000 * 60 * 2, // Auto-refetch every 2 minutes
|
refetchInterval: 1000 * 60 * 2, // Auto-refetch every 2 minutes
|
||||||
});
|
});
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (data) {
|
if (data) {
|
||||||
setSession(data.data.user, data.data.token);
|
setSession(data.data.user, data.data.token);
|
||||||
}
|
}
|
||||||
if (error) {
|
if (error) {
|
||||||
clearSession();
|
clearSession();
|
||||||
}
|
}
|
||||||
}, [data, error]);
|
}, [data, error]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
session: data && token ? { user: data.user, token: data.token } : null,
|
session: data && token ? { user: data.user, token: data.token } : null,
|
||||||
status,
|
status,
|
||||||
error,
|
error,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,43 +1,52 @@
|
|||||||
import {User} from "@/types/users";
|
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import {create} from "zustand";
|
import { create } from "zustand";
|
||||||
|
import { User } from "@/types/users";
|
||||||
|
|
||||||
export type SessionState = {
|
export type SessionState = {
|
||||||
user: User | null;
|
user: User | null;
|
||||||
token: string | null;
|
token: string | null;
|
||||||
setSession: (user: User | null, token: string | null) => void;
|
setSession: (user: User | null, token: string | null) => void;
|
||||||
clearSession: () => void;
|
clearSession: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useSessionStore = create<SessionState>((set) => {
|
export const useSessionStore = create<SessionState>((set) => {
|
||||||
// Initialize token from localStorage, but user remains in memory only
|
// Initialize token from localStorage, but user remains in memory only
|
||||||
const storedToken = localStorage.getItem("auth_token");
|
const storedToken = localStorage.getItem("auth_token");
|
||||||
|
|
||||||
return {
|
return {
|
||||||
user: null, // User is NOT stored in localStorage
|
user: null, // User is NOT stored in localStorage
|
||||||
token: storedToken || null,
|
token: storedToken || null,
|
||||||
|
|
||||||
setSession: async (user: any, 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", {
|
const response = await axios.get("/api/auth/session", {
|
||||||
headers: {Authorization: `Bearer ${token}`},
|
withCredentials: true,
|
||||||
});
|
});
|
||||||
const data = response.data; //await response.json();
|
const userRoles = await axios.get("/api/auth/getuseraccess", {
|
||||||
user = {...user, roles: data.data};
|
withCredentials: true,
|
||||||
} else {
|
});
|
||||||
localStorage.removeItem("auth_token");
|
const data = response.data; //await response.json();
|
||||||
}
|
|
||||||
|
|
||||||
//console.log("Setting session:", {user, token});
|
const rawUser = data.data.user;
|
||||||
set({user, token});
|
// user.map((u: any) => ({
|
||||||
},
|
// ...u,
|
||||||
|
// roles: userRoles.data.data,
|
||||||
|
// }));
|
||||||
|
user = { ...rawUser, roles: userRoles.data.data };
|
||||||
|
} else {
|
||||||
|
localStorage.removeItem("auth_token");
|
||||||
|
}
|
||||||
|
|
||||||
clearSession: () => {
|
//console.log("Setting session:", {user, token});
|
||||||
localStorage.removeItem("auth_token");
|
set({ user, token });
|
||||||
set({user: null, token: null});
|
},
|
||||||
},
|
|
||||||
};
|
clearSession: () => {
|
||||||
|
localStorage.removeItem("auth_token");
|
||||||
|
set({ user: null, token: null });
|
||||||
|
},
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
export type SessionType = ReturnType<typeof useSessionStore>;
|
export type SessionType = ReturnType<typeof useSessionStore>;
|
||||||
|
|||||||
15
lstV2/frontend/src/lib/store/useAuthStore.ts
Normal file
15
lstV2/frontend/src/lib/store/useAuthStore.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import { create } from "zustand";
|
||||||
|
|
||||||
|
interface SettingState {
|
||||||
|
username: string;
|
||||||
|
password: string;
|
||||||
|
clearUser: () => void;
|
||||||
|
setUserInfo: (username: string, password: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useAuthStore = create<SettingState>()((set) => ({
|
||||||
|
username: "",
|
||||||
|
password: "",
|
||||||
|
setUserInfo: (username, password) => set({ username, password }),
|
||||||
|
clearUser: () => set({ username: "", password: "" }),
|
||||||
|
}));
|
||||||
@@ -1,38 +1,41 @@
|
|||||||
|
import axios from "axios";
|
||||||
import { create } from "zustand";
|
import { create } from "zustand";
|
||||||
import { Modules } from "@/types/modules";
|
import { Modules } from "@/types/modules";
|
||||||
import axios from "axios";
|
|
||||||
|
|
||||||
interface SettingState {
|
interface SettingState {
|
||||||
userRoles: Modules[];
|
userRoles: Modules[];
|
||||||
|
|
||||||
fetchUserRoles: () => Promise<void>;
|
fetchUserRoles: () => Promise<void>;
|
||||||
setUserRoles: (userRoles: Modules[]) => void;
|
setUserRoles: (userRoles: Modules[]) => void;
|
||||||
}
|
}
|
||||||
interface FetchModulesResponse {
|
interface FetchModulesResponse {
|
||||||
data: Modules[];
|
data: Modules[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useGetUserRoles = create<SettingState>()((set) => ({
|
export const useGetUserRoles = create<SettingState>()((set) => ({
|
||||||
userRoles: [],
|
userRoles: [],
|
||||||
setUserRoles: (userRoles) => set({ userRoles }),
|
setUserRoles: (userRoles) => set({ userRoles }),
|
||||||
fetchUserRoles: async () => {
|
fetchUserRoles: 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 token = localStorage.getItem("auth_token");
|
const token = localStorage.getItem("auth_token");
|
||||||
if (token) {
|
if (token) {
|
||||||
const response = await axios.get("/api/auth/getuseraccess", {
|
const response = await axios.get("/api/auth/getuseraccess", {
|
||||||
headers: { Authorization: `Bearer ${token}` },
|
withCredentials: true,
|
||||||
});
|
});
|
||||||
const data: FetchModulesResponse = response.data; //await response.json();
|
const data: FetchModulesResponse = response?.data; //await response.json();
|
||||||
|
|
||||||
//console.log(data);
|
if (response.status === 401) {
|
||||||
set({ userRoles: data.data });
|
set({ userRoles: [] });
|
||||||
} else {
|
}
|
||||||
//console.log(data);
|
set({ userRoles: data?.data });
|
||||||
set({ userRoles: [] });
|
} else {
|
||||||
}
|
//console.log(data);
|
||||||
} catch (error) {
|
set({ userRoles: [] });
|
||||||
console.error("Failed to fetch settings:", error);
|
}
|
||||||
}
|
} catch (error) {
|
||||||
},
|
set({ userRoles: [] });
|
||||||
|
console.error("Failed to fetch settings:", error);
|
||||||
|
}
|
||||||
|
},
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -1,44 +1,52 @@
|
|||||||
import { Modules } from "@/types/modules";
|
|
||||||
import { User } from "@/types/users";
|
import { User } from "@/types/users";
|
||||||
|
|
||||||
// user will need access to the module.
|
// user will need access to the module.
|
||||||
// users role will determine there visual access
|
// users role will determine there visual access
|
||||||
export function hasAccess(
|
export function hasAccess(user: any, moduleName: string | null): boolean {
|
||||||
user: User | null,
|
//console.log("has access user", user, moduleName);
|
||||||
moduleName: string | null,
|
// get the modules for the id
|
||||||
modules: Modules[]
|
|
||||||
): boolean {
|
|
||||||
// get the modules for the id
|
|
||||||
const filteredModule = modules?.filter((f) => f.name === moduleName);
|
|
||||||
//console.log(filteredModule[0]);
|
|
||||||
// userroles and filter out by the module id,
|
|
||||||
|
|
||||||
const roleCheck: any = user?.roles.find(
|
const filteredModule = user?.roles?.filter(
|
||||||
(role) => role.module_id === filteredModule[0].module_id
|
(f: any) => f.module === moduleName,
|
||||||
);
|
);
|
||||||
|
//console.log(filteredModule[0]);
|
||||||
|
// userroles and filter out by the module id,
|
||||||
|
//console.log("Has Module access", filteredModule);
|
||||||
|
// const roleCheck: any = user?.roles.find(
|
||||||
|
// (role) => role.module_id === filteredModule[0].module_id,
|
||||||
|
// );
|
||||||
|
|
||||||
if (filteredModule[0].roles.includes(roleCheck?.role)) {
|
if (filteredModule && filteredModule.length > 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//if(filteredModule[0].roles.includes(roleCheck.))
|
//if(filteredModule[0].roles.includes(roleCheck.))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function hasPageAccess(
|
export function hasPageAccess(
|
||||||
user: User | null,
|
user: User | null,
|
||||||
role: any,
|
role: any,
|
||||||
module_id: string
|
moduleName: string,
|
||||||
): boolean {
|
): boolean {
|
||||||
if (role.includes("viewer")) return true;
|
if (role.includes("viewer")) return true;
|
||||||
if (!user) return false;
|
if (!user) return false;
|
||||||
|
|
||||||
// get only the module in the user profile
|
const userRole = user?.roles.filter(
|
||||||
//console.log(user);
|
(role: any) => role.module === moduleName,
|
||||||
const userRole = user?.roles.filter((role) => role.module_id === module_id);
|
);
|
||||||
//console.log(userRole[0]?.role);
|
|
||||||
// if (role.includes(userRole[0]?.role)) {
|
|
||||||
|
|
||||||
// return true};
|
//console.log(user);
|
||||||
if (userRole.length !== 0) return true;
|
|
||||||
return false;
|
// if (role.includes(userRole[0]?.role)) {
|
||||||
|
|
||||||
|
// return true};
|
||||||
|
//if (userRole.length > 0) return true;
|
||||||
|
if (userRole.length >= 1) {
|
||||||
|
//console.log(userRole);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,35 +1,34 @@
|
|||||||
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 { serveStatic } from "@hono/node-server/serve-static";
|
import { serveStatic } from "@hono/node-server/serve-static";
|
||||||
import { logger } from "hono/logger";
|
import { OpenAPIHono } from "@hono/zod-openapi";
|
||||||
import { cors } from "hono/cors";
|
import { cors } from "hono/cors";
|
||||||
import { createLog } from "./services/logger/logger.js";
|
import { logger } from "hono/logger";
|
||||||
|
import os from "os";
|
||||||
|
import auth from "./services/auth/authService.js";
|
||||||
|
import dataMart from "./services/dataMart/dataMartService.js";
|
||||||
|
import eom from "./services/eom/eomService.js";
|
||||||
// custom routes
|
// custom routes
|
||||||
import scalar from "./services/general/route/scalar.js";
|
import scalar from "./services/general/route/scalar.js";
|
||||||
import system from "./services/server/systemServer.js";
|
import { createLog } from "./services/logger/logger.js";
|
||||||
import auth from "./services/auth/authService.js";
|
|
||||||
import tcpServer from "./services/tcpServer/tcpServer.js";
|
|
||||||
import ocme from "./services/ocme/ocmeService.js";
|
|
||||||
import sqlService from "./services/sqlServer/sqlService.js";
|
|
||||||
import logistics from "./services/logistics/logisticsService.js";
|
|
||||||
import rfid from "./services/rfid/rfidService.js";
|
|
||||||
import printers from "./services/printers/printerService.js";
|
|
||||||
import loggerService from "./services/logger/loggerService.js";
|
import loggerService from "./services/logger/loggerService.js";
|
||||||
import ocpService from "./services/ocp/ocpService.js";
|
import logistics from "./services/logistics/logisticsService.js";
|
||||||
import os from "os";
|
|
||||||
import { sendEmail } from "./services/notifications/controller/sendMail.js";
|
import { sendEmail } from "./services/notifications/controller/sendMail.js";
|
||||||
import notify from "./services/notifications/notifyService.js";
|
import notify from "./services/notifications/notifyService.js";
|
||||||
import eom from "./services/eom/eomService.js";
|
import ocme from "./services/ocme/ocmeService.js";
|
||||||
import dataMart from "./services/dataMart/dataMartService.js";
|
import ocpService from "./services/ocp/ocpService.js";
|
||||||
import qualityRequest from "./services/quality/qualityService.js";
|
import printers from "./services/printers/printerService.js";
|
||||||
import produser from "./services/prodUser/prodUser.js";
|
import produser from "./services/prodUser/prodUser.js";
|
||||||
|
import qualityRequest from "./services/quality/qualityService.js";
|
||||||
|
import rfid from "./services/rfid/rfidService.js";
|
||||||
import {
|
import {
|
||||||
getSettings,
|
getSettings,
|
||||||
serverSettings,
|
serverSettings,
|
||||||
} from "./services/server/controller/settings/getSettings.js";
|
} from "./services/server/controller/settings/getSettings.js";
|
||||||
|
import system from "./services/server/systemServer.js";
|
||||||
|
import sqlService from "./services/sqlServer/sqlService.js";
|
||||||
|
import tcpServer from "./services/tcpServer/tcpServer.js";
|
||||||
|
|
||||||
// create the main prodlogin here
|
// create the main prodlogin here
|
||||||
const username = "lst_user";
|
const username = "lst_user";
|
||||||
@@ -48,28 +47,33 @@ export const lstAuth = btoa(`${username}:${password}`);
|
|||||||
const serverIntialized: any = await getSettings();
|
const serverIntialized: any = await getSettings();
|
||||||
|
|
||||||
export const installed =
|
export const installed =
|
||||||
serverIntialized.length === 0 && process.env.NODE_ENV !== "development"
|
serverIntialized.length === 0 && process.env.NODE_ENV !== "development"
|
||||||
? false
|
? false
|
||||||
: true;
|
: true;
|
||||||
createLog("info", "LST", "server", `Server is installed: ${installed}`);
|
createLog("info", "LST", "server", `Server is installed: ${installed}`);
|
||||||
|
|
||||||
const app = new OpenAPIHono({ strict: false });
|
const app = new OpenAPIHono({ strict: false });
|
||||||
|
|
||||||
// middle ware
|
// middle ware
|
||||||
if (process.env.NODE_ENV === "development") {
|
if (process.env.NODE_ENV === "development") {
|
||||||
app.use("*", logger());
|
app.use("*", logger());
|
||||||
}
|
}
|
||||||
|
|
||||||
app.use(
|
app.use(
|
||||||
"*",
|
"*",
|
||||||
cors({
|
cors({
|
||||||
origin: "*", // Allow all origins
|
origin: [
|
||||||
allowHeaders: ["Content-Type", "Authorization", "X-Requested-With"],
|
"http://localhost:3000",
|
||||||
allowMethods: ["GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"],
|
"http://localhost:5173",
|
||||||
//exposeHeaders: ["Content-Length", "X-Kuma-Revision"],
|
"http://localhost:4000",
|
||||||
credentials: true, // Allow credentials if needed
|
"http://localhost:4200",
|
||||||
maxAge: 600,
|
], // Allow all origins
|
||||||
})
|
allowHeaders: ["Content-Type", "Authorization", "X-Requested-With"],
|
||||||
|
allowMethods: ["GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"],
|
||||||
|
//exposeHeaders: ["Content-Length", "X-Kuma-Revision"],
|
||||||
|
credentials: true, // Allow credentials if needed
|
||||||
|
maxAge: 600,
|
||||||
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Middleware to normalize route case
|
// Middleware to normalize route case
|
||||||
@@ -86,34 +90,34 @@ app.use(
|
|||||||
// });
|
// });
|
||||||
|
|
||||||
app.doc("/api/ref", {
|
app.doc("/api/ref", {
|
||||||
openapi: "3.0.0",
|
openapi: "3.0.0",
|
||||||
info: {
|
info: {
|
||||||
version: "2.0.0",
|
version: "2.0.0",
|
||||||
title: "LST API",
|
title: "LST API",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
scalar,
|
scalar,
|
||||||
auth,
|
auth,
|
||||||
// apiHits,
|
// apiHits,
|
||||||
system,
|
system,
|
||||||
tcpServer,
|
tcpServer,
|
||||||
sqlService,
|
sqlService,
|
||||||
logistics,
|
logistics,
|
||||||
rfid,
|
rfid,
|
||||||
printers,
|
printers,
|
||||||
loggerService,
|
loggerService,
|
||||||
ocpService,
|
ocpService,
|
||||||
notify,
|
notify,
|
||||||
eom,
|
eom,
|
||||||
dataMart,
|
dataMart,
|
||||||
qualityRequest,
|
qualityRequest,
|
||||||
produser,
|
produser,
|
||||||
] 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);
|
app.route("/ocme/", ocme);
|
||||||
@@ -154,60 +158,60 @@ app.use("*", serveStatic({ path: "./frontend/dist/index.html" }));
|
|||||||
|
|
||||||
// Handle app exit signals
|
// Handle app exit signals
|
||||||
process.on("SIGINT", async () => {
|
process.on("SIGINT", async () => {
|
||||||
console.log("\nGracefully shutting down...");
|
console.log("\nGracefully shutting down...");
|
||||||
//await closePool();
|
//await closePool();
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
process.on("SIGTERM", async () => {
|
process.on("SIGTERM", async () => {
|
||||||
console.log("Received termination signal, closing database...");
|
console.log("Received termination signal, closing database...");
|
||||||
//await closePool();
|
//await closePool();
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
process.on("uncaughtException", async (err) => {
|
process.on("uncaughtException", async (err) => {
|
||||||
console.log("Uncaught Exception:", err);
|
console.log("Uncaught Exception:", err);
|
||||||
//await closePool();
|
//await closePool();
|
||||||
const emailData = {
|
const emailData = {
|
||||||
email: "blake.matthes@alpla.com", // should be moved to the db so it can be reused.
|
email: "blake.matthes@alpla.com", // should be moved to the db so it can be reused.
|
||||||
subject: `${os.hostname()} has just encountered a crash.`,
|
subject: `${os.hostname()} has just encountered a crash.`,
|
||||||
template: "serverCrash",
|
template: "serverCrash",
|
||||||
context: {
|
context: {
|
||||||
error: err,
|
error: err,
|
||||||
plant: `${os.hostname()}`,
|
plant: `${os.hostname()}`,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
await sendEmail(emailData);
|
await sendEmail(emailData);
|
||||||
//process.exit(1);
|
//process.exit(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
process.on("beforeExit", async () => {
|
process.on("beforeExit", async () => {
|
||||||
console.log("Process is about to exit...");
|
console.log("Process is about to exit...");
|
||||||
//await closePool();
|
//await closePool();
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
const port =
|
const port =
|
||||||
process.env.NODE_ENV === "development"
|
process.env.NODE_ENV === "development"
|
||||||
? process.env.VITE_SERVER_PORT
|
? process.env.VITE_SERVER_PORT
|
||||||
: process.env.PROD_PORT;
|
: process.env.PROD_PORT;
|
||||||
|
|
||||||
const ocmeport = process.env.OCME_PORT;
|
const ocmeport = process.env.OCME_PORT;
|
||||||
serve(
|
serve(
|
||||||
{
|
{
|
||||||
fetch: app.fetch,
|
fetch: app.fetch,
|
||||||
port: Number(port),
|
port: Number(port),
|
||||||
hostname: "0.0.0.0",
|
hostname: "0.0.0.0",
|
||||||
},
|
},
|
||||||
(info) => {
|
(info) => {
|
||||||
createLog(
|
createLog(
|
||||||
"info",
|
"info",
|
||||||
"LST",
|
"LST",
|
||||||
"server",
|
"server",
|
||||||
`Server is running on http://${info.address}:${info.port}`
|
`Server is running on http://${info.address}:${info.port}`,
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -217,21 +221,21 @@ serve(
|
|||||||
const setting = serverSettings;
|
const setting = serverSettings;
|
||||||
const isActive = setting.filter((n) => n.name === "ocmeService");
|
const isActive = setting.filter((n) => n.name === "ocmeService");
|
||||||
if (ocmeport && isActive[0]?.value === "1") {
|
if (ocmeport && isActive[0]?.value === "1") {
|
||||||
serve(
|
serve(
|
||||||
{
|
{
|
||||||
fetch: app.fetch,
|
fetch: app.fetch,
|
||||||
port: Number(ocmeport),
|
port: Number(ocmeport),
|
||||||
hostname: "0.0.0.0",
|
hostname: "0.0.0.0",
|
||||||
},
|
},
|
||||||
(info) => {
|
(info) => {
|
||||||
createLog(
|
createLog(
|
||||||
"info",
|
"info",
|
||||||
"LST",
|
"LST",
|
||||||
"server",
|
"server",
|
||||||
`Ocme section is listening on http://${info.address}:${info.port}`
|
`Ocme section is listening on http://${info.address}:${info.port}`,
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export type AppRoutes = typeof appRoutes;
|
export type AppRoutes = typeof appRoutes;
|
||||||
|
|||||||
@@ -1,45 +1,62 @@
|
|||||||
import {type MiddlewareHandler} from "hono";
|
import axios from "axios";
|
||||||
|
import { type MiddlewareHandler } from "hono";
|
||||||
import jwt from "jsonwebtoken";
|
import jwt from "jsonwebtoken";
|
||||||
|
|
||||||
const {sign, verify} = jwt;
|
const { sign, verify } = jwt;
|
||||||
|
|
||||||
export const authMiddleware: MiddlewareHandler = async (c, next) => {
|
export const authMiddleware: MiddlewareHandler = async (c, next) => {
|
||||||
const authHeader = c.req.header("Authorization");
|
console.log("middleware checked");
|
||||||
|
const cookieHeader = c.req.header("Cookie");
|
||||||
|
if (!cookieHeader) return c.json({ error: "Unauthorized" }, 401);
|
||||||
|
|
||||||
if (!authHeader || !authHeader.startsWith("Bearer ")) {
|
const res = await axios.get(`${process.env.LST_BASE_URL}/api/user/me`, {
|
||||||
return c.json({error: "Unauthorized"}, 401);
|
headers: { Cookie: cookieHeader },
|
||||||
}
|
});
|
||||||
|
|
||||||
const token = authHeader.split(" ")[1];
|
if (res.status === 401) return c.json({ error: "Unauthorized" }, 401);
|
||||||
|
|
||||||
try {
|
//const user = await resp.json();
|
||||||
const decoded = verify(token, process.env.JWT_SECRET!, {ignoreExpiration: false}) as {
|
c.set("user", res.data.user);
|
||||||
userId: number;
|
return next();
|
||||||
exp: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
const currentTime = Math.floor(Date.now() / 1000); // Get current timestamp
|
|
||||||
const timeLeft = decoded.exp - currentTime;
|
|
||||||
|
|
||||||
// If the token has less than REFRESH_THRESHOLD seconds left, refresh it
|
|
||||||
let newToken = null;
|
|
||||||
|
|
||||||
if (timeLeft < parseInt(process.env.REFRESH_THRESHOLD!)) {
|
|
||||||
newToken = sign({userId: decoded.userId}, process.env.JWT_SECRET!, {
|
|
||||||
expiresIn: parseInt(process.env.EXPIRATION_TIME!),
|
|
||||||
});
|
|
||||||
c.res.headers.set("Authorization", `Bearer ${newToken}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
c.set("user", {id: decoded.userId});
|
|
||||||
await next();
|
|
||||||
|
|
||||||
// If a new token was generated, send it in response headers
|
|
||||||
if (newToken) {
|
|
||||||
console.log("token was refreshed");
|
|
||||||
c.res.headers.set("X-Refreshed-Token", newToken);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
return c.json({error: "Invalid token"}, 401);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// export const authMiddleware: MiddlewareHandler = async (c, next) => {
|
||||||
|
// const authHeader = c.req.header("Authorization");
|
||||||
|
|
||||||
|
// if (!authHeader || !authHeader.startsWith("Bearer ")) {
|
||||||
|
// return c.json({error: "Unauthorized"}, 401);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const token = authHeader.split(" ")[1];
|
||||||
|
|
||||||
|
// try {
|
||||||
|
// const decoded = verify(token, process.env.JWT_SECRET!, {ignoreExpiration: false}) as {
|
||||||
|
// userId: number;
|
||||||
|
// exp: number;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// const currentTime = Math.floor(Date.now() / 1000); // Get current timestamp
|
||||||
|
// const timeLeft = decoded.exp - currentTime;
|
||||||
|
|
||||||
|
// // If the token has less than REFRESH_THRESHOLD seconds left, refresh it
|
||||||
|
// let newToken = null;
|
||||||
|
|
||||||
|
// if (timeLeft < parseInt(process.env.REFRESH_THRESHOLD!)) {
|
||||||
|
// newToken = sign({userId: decoded.userId}, process.env.JWT_SECRET!, {
|
||||||
|
// expiresIn: parseInt(process.env.EXPIRATION_TIME!),
|
||||||
|
// });
|
||||||
|
// c.res.headers.set("Authorization", `Bearer ${newToken}`);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// c.set("user", {id: decoded.userId});
|
||||||
|
// await next();
|
||||||
|
|
||||||
|
// // If a new token was generated, send it in response headers
|
||||||
|
// if (newToken) {
|
||||||
|
// console.log("token was refreshed");
|
||||||
|
// c.res.headers.set("X-Refreshed-Token", newToken);
|
||||||
|
// }
|
||||||
|
// } catch (err) {
|
||||||
|
// return c.json({error: "Invalid token"}, 401);
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|||||||
@@ -1,85 +1,111 @@
|
|||||||
|
import axios from "axios";
|
||||||
import { createMiddleware } from "hono/factory";
|
import { createMiddleware } from "hono/factory";
|
||||||
|
|
||||||
import type { CustomJwtPayload } from "../../../types/jwtToken.js";
|
// const hasCorrectRole = (requiredRole: string[], module: string) =>
|
||||||
import { verify } from "hono/jwt";
|
// createMiddleware(async (c, next) => {
|
||||||
import { db } from "../../../../database/dbclient.js";
|
// /**
|
||||||
import { modules } from "../../../../database/schema/modules.js";
|
// * We want to check to make sure you have the correct role to be here
|
||||||
import { and, eq } from "drizzle-orm";
|
// */
|
||||||
import { userRoles } from "../../../../database/schema/userRoles.js";
|
// const authHeader = c.req.header("Authorization");
|
||||||
import { tryCatch } from "../../../globalUtils/tryCatch.js";
|
|
||||||
|
// if (!authHeader || !authHeader.startsWith("Bearer ")) {
|
||||||
|
// return c.json({ error: "Unauthorized" }, 401);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const token = authHeader.split(" ")[1];
|
||||||
|
|
||||||
|
// // deal with token data
|
||||||
|
// const { data: tokenData, error: tokenError } = await tryCatch(
|
||||||
|
// verify(token, process.env.JWT_SECRET!),
|
||||||
|
// );
|
||||||
|
|
||||||
|
// if (tokenError) {
|
||||||
|
// return c.json({ error: "Invalid token" }, 401);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const customToken = tokenData as CustomJwtPayload;
|
||||||
|
|
||||||
|
// // Get the module
|
||||||
|
// const { data: mod, error: modError } = await tryCatch(
|
||||||
|
// db.select().from(modules).where(eq(modules.name, module)),
|
||||||
|
// );
|
||||||
|
// if (modError) {
|
||||||
|
// console.log(modError);
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (mod.length === 0) {
|
||||||
|
// return c.json({ error: "You have entered an invalid module name" }, 403);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // check if the user has the role needed to get into this module
|
||||||
|
// const { data: userRole, error: userRoleError } = await tryCatch(
|
||||||
|
// db
|
||||||
|
// .select()
|
||||||
|
// .from(userRoles)
|
||||||
|
// .where(
|
||||||
|
// and(
|
||||||
|
// eq(userRoles.module_id, mod[0].module_id),
|
||||||
|
// eq(userRoles.user_id, customToken.user?.user_id!),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// );
|
||||||
|
|
||||||
|
// if (userRoleError) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (!userRole) {
|
||||||
|
// return c.json(
|
||||||
|
// {
|
||||||
|
// error:
|
||||||
|
// "The module you are trying to access is not active or is invalid.",
|
||||||
|
// },
|
||||||
|
// 403,
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (!requiredRole.includes(userRole[0]?.role)) {
|
||||||
|
// return c.json(
|
||||||
|
// { error: "You do not have access to this part of the app." },
|
||||||
|
// 403,
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
|
// await next();
|
||||||
|
// });
|
||||||
|
|
||||||
|
interface UserRole {
|
||||||
|
userRoleId: string;
|
||||||
|
userId: string;
|
||||||
|
module: string;
|
||||||
|
role: string;
|
||||||
|
}
|
||||||
|
|
||||||
const hasCorrectRole = (requiredRole: string[], module: string) =>
|
const hasCorrectRole = (requiredRole: string[], module: string) =>
|
||||||
createMiddleware(async (c, next) => {
|
createMiddleware(async (c, next) => {
|
||||||
/**
|
const cookieHeader = c.req.header("Cookie");
|
||||||
* We want to check to make sure you have the correct role to be here
|
if (!cookieHeader) return c.json({ error: "Unauthorized" }, 401);
|
||||||
*/
|
|
||||||
const authHeader = c.req.header("Authorization");
|
|
||||||
|
|
||||||
if (!authHeader || !authHeader.startsWith("Bearer ")) {
|
const res = await axios.get(`${process.env.LST_BASE_URL}/api/user/roles`, {
|
||||||
return c.json({ error: "Unauthorized" }, 401);
|
headers: { Cookie: cookieHeader },
|
||||||
}
|
});
|
||||||
|
|
||||||
const token = authHeader.split(" ")[1];
|
const currentRoles: UserRole[] = res.data.data;
|
||||||
|
const canAccess = currentRoles.some(
|
||||||
|
(r) => r.module === module && requiredRole.includes(r.role),
|
||||||
|
);
|
||||||
|
if (!canAccess) {
|
||||||
|
return c.json(
|
||||||
|
{
|
||||||
|
error: "Unauthorized",
|
||||||
|
message: `You do not have access to ${module}`,
|
||||||
|
},
|
||||||
|
400,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// deal with token data
|
return next();
|
||||||
const { data: tokenData, error: tokenError } = await tryCatch(
|
});
|
||||||
verify(token, process.env.JWT_SECRET!)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (tokenError) {
|
|
||||||
return c.json({ error: "Invalid token" }, 401);
|
|
||||||
}
|
|
||||||
|
|
||||||
const customToken = tokenData as CustomJwtPayload;
|
|
||||||
|
|
||||||
// Get the module
|
|
||||||
const { data: mod, error: modError } = await tryCatch(
|
|
||||||
db.select().from(modules).where(eq(modules.name, module))
|
|
||||||
);
|
|
||||||
if (modError) {
|
|
||||||
console.log(modError);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mod.length === 0) {
|
|
||||||
return c.json({ error: "You have entered an invalid module name" }, 403);
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if the user has the role needed to get into this module
|
|
||||||
const { data: userRole, error: userRoleError } = await tryCatch(
|
|
||||||
db
|
|
||||||
.select()
|
|
||||||
.from(userRoles)
|
|
||||||
.where(
|
|
||||||
and(
|
|
||||||
eq(userRoles.module_id, mod[0].module_id),
|
|
||||||
eq(userRoles.user_id, customToken.user?.user_id!)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (userRoleError) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!userRole) {
|
|
||||||
return c.json(
|
|
||||||
{
|
|
||||||
error:
|
|
||||||
"The module you are trying to access is not active or is invalid.",
|
|
||||||
},
|
|
||||||
403
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!requiredRole.includes(userRole[0]?.role)) {
|
|
||||||
return c.json(
|
|
||||||
{ error: "You do not have access to this part of the app." },
|
|
||||||
403
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
await next();
|
|
||||||
});
|
|
||||||
|
|
||||||
export default hasCorrectRole;
|
export default hasCorrectRole;
|
||||||
|
|||||||
@@ -1,97 +1,117 @@
|
|||||||
import { z, createRoute, OpenAPIHono } from "@hono/zod-openapi";
|
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
|
||||||
|
import axios from "axios";
|
||||||
import { login } from "../controllers/login.js";
|
import { login } from "../controllers/login.js";
|
||||||
|
|
||||||
const app = new OpenAPIHono();
|
const app = new OpenAPIHono();
|
||||||
|
|
||||||
const UserSchema = z
|
const UserSchema = z
|
||||||
.object({
|
.object({
|
||||||
username: z.string().optional().openapi({ example: "smith002" }),
|
username: z.string().optional().openapi({ example: "smith002" }),
|
||||||
//email: z.string().optional().openapi({example: "s.smith@example.com"}),
|
//email: z.string().optional().openapi({example: "s.smith@example.com"}),
|
||||||
password: z.string().openapi({ example: "password123" }),
|
password: z.string().openapi({ example: "password123" }),
|
||||||
})
|
})
|
||||||
.openapi("User");
|
.openapi("User");
|
||||||
|
|
||||||
const route = createRoute({
|
const route = createRoute({
|
||||||
tags: ["Auth"],
|
tags: ["Auth"],
|
||||||
summary: "Login as user",
|
summary: "Login as user",
|
||||||
description: "Login as a user to get a JWT token",
|
description: "Login as a user to get a JWT token",
|
||||||
method: "post",
|
method: "post",
|
||||||
path: "/login",
|
path: "/login",
|
||||||
request: {
|
request: {
|
||||||
body: {
|
body: {
|
||||||
content: {
|
content: {
|
||||||
"application/json": { schema: UserSchema },
|
"application/json": { schema: UserSchema },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
responses: {
|
responses: {
|
||||||
200: {
|
200: {
|
||||||
content: {
|
content: {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
schema: z.object({
|
schema: z.object({
|
||||||
success: z.boolean().openapi({ example: true }),
|
success: z.boolean().openapi({ example: true }),
|
||||||
message: z.string().openapi({ example: "Logged in" }),
|
message: z.string().openapi({ example: "Logged in" }),
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
description: "Response message",
|
description: "Response message",
|
||||||
},
|
},
|
||||||
|
|
||||||
400: {
|
400: {
|
||||||
content: {
|
content: {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
schema: z.object({
|
schema: z.object({
|
||||||
success: z.boolean().openapi({ example: false }),
|
success: z.boolean().openapi({ example: false }),
|
||||||
message: z
|
message: z
|
||||||
.string()
|
.string()
|
||||||
.openapi({ example: "Username and password required" }),
|
.openapi({ example: "Username and password required" }),
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
description: "Bad request",
|
description: "Bad request",
|
||||||
},
|
},
|
||||||
401: {
|
401: {
|
||||||
content: {
|
content: {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
schema: z.object({
|
schema: z.object({
|
||||||
success: z.boolean().openapi({ example: false }),
|
success: z.boolean().openapi({ example: false }),
|
||||||
message: z
|
message: z
|
||||||
.string()
|
.string()
|
||||||
.openapi({ example: "Username and password required" }),
|
.openapi({ example: "Username and password required" }),
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
description: "Bad request",
|
description: "Bad request",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
app.openapi(route, async (c) => {
|
app.openapi(route, async (c: any) => {
|
||||||
const { username, password, email } = await c.req.json();
|
const { username, password, email } = await c.req.json();
|
||||||
|
|
||||||
if (!username || !password) {
|
if (!username || !password) {
|
||||||
return c.json(
|
return c.json(
|
||||||
{
|
{
|
||||||
success: false,
|
success: false,
|
||||||
message: "Username and password are required",
|
message: "Username and password are required",
|
||||||
},
|
},
|
||||||
400
|
400,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { token, user } = await login(username.toLowerCase(), password);
|
const loginResp = await axios.post(
|
||||||
|
`${process.env.LST_BASE_URL}/api/user/login`,
|
||||||
|
{ username: username.toLowerCase(), password },
|
||||||
|
{ withCredentials: true },
|
||||||
|
);
|
||||||
|
|
||||||
// Set the JWT as an HTTP-only cookie
|
// Set the JWT as an HTTP-only cookie
|
||||||
//c.header("Set-Cookie", `auth_token=${token}; HttpOnly; Secure; Path=/; SameSite=None; Max-Age=3600`);
|
//c.header("Set-Cookie", `auth_token=${token}; HttpOnly; Secure; Path=/; SameSite=None; Max-Age=3600`);
|
||||||
|
|
||||||
return c.json(
|
const setCookie = loginResp.headers["set-cookie"] as any;
|
||||||
{ success: true, message: "Login successful", user, token },
|
|
||||||
200
|
if (setCookie) {
|
||||||
);
|
c.header("Set-Cookie", setCookie);
|
||||||
} catch (err) {
|
}
|
||||||
return c.json({ success: false, message: "Incorrect Credentials" }, 401);
|
return c.json(
|
||||||
}
|
{ success: true, message: "Login successful", data: loginResp.data },
|
||||||
|
200,
|
||||||
|
);
|
||||||
|
} catch (err) {
|
||||||
|
// @ts-ignore
|
||||||
|
if (!err.response.data.success) {
|
||||||
|
// @ts-ignore
|
||||||
|
return c.json(
|
||||||
|
// @ts-ignore
|
||||||
|
{ success: false, message: err.response.data.message },
|
||||||
|
401,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return c.json({ success: false, message: "Incorrect Credentials" }, 401);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export default app;
|
export default app;
|
||||||
|
|||||||
@@ -1,110 +1,149 @@
|
|||||||
import { z, createRoute, OpenAPIHono } from "@hono/zod-openapi";
|
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
|
||||||
|
import axios from "axios";
|
||||||
import { verify } from "hono/jwt";
|
import { verify } from "hono/jwt";
|
||||||
|
|
||||||
import { authMiddleware } from "../middleware/authMiddleware.js";
|
|
||||||
import jwt from "jsonwebtoken";
|
import jwt from "jsonwebtoken";
|
||||||
|
import { authMiddleware } from "../middleware/authMiddleware.js";
|
||||||
|
|
||||||
const session = new OpenAPIHono();
|
const session = new OpenAPIHono();
|
||||||
const expiresIn = Number(process.env.JWT_EXPIRES!) || 60;
|
const expiresIn = Number(process.env.JWT_EXPIRES!) || 60;
|
||||||
const secret: string = process.env.JWT_SECRET!;
|
const secret: string = process.env.JWT_SECRET!;
|
||||||
|
|
||||||
const { sign } = jwt;
|
const { sign } = jwt;
|
||||||
|
|
||||||
const UserSchema = z.object({
|
const UserSchema = z.object({
|
||||||
username: z
|
username: z
|
||||||
.string()
|
.string()
|
||||||
.regex(/^[a-zA-Z0-9_]{3,30}$/)
|
.regex(/^[a-zA-Z0-9_]{3,30}$/)
|
||||||
.openapi({ example: "smith034" }),
|
.openapi({ example: "smith034" }),
|
||||||
email: z.string().email().openapi({ example: "smith@example.com" }),
|
email: z.string().email().openapi({ example: "smith@example.com" }),
|
||||||
password: z
|
password: z
|
||||||
.string()
|
.string()
|
||||||
.min(6, { message: "Passwords must be longer than 3 characters" })
|
.min(6, { message: "Passwords must be longer than 3 characters" })
|
||||||
.regex(/[A-Z]/, {
|
.regex(/[A-Z]/, {
|
||||||
message: "Password must contain at least one uppercase letter",
|
message: "Password must contain at least one uppercase letter",
|
||||||
})
|
})
|
||||||
.regex(/[\W_]/, {
|
.regex(/[\W_]/, {
|
||||||
message: "Password must contain at least one special character",
|
message: "Password must contain at least one special character",
|
||||||
})
|
})
|
||||||
.openapi({ example: "Password1!" }),
|
.openapi({ example: "Password1!" }),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const activeSessions: Record<string, { lastSeen: number; expiresAt: number }> =
|
||||||
|
{};
|
||||||
|
const SESSION_TIMEOUT_MS = 60 * 60 * 1000; // 1 hour
|
||||||
|
|
||||||
session.openapi(
|
session.openapi(
|
||||||
createRoute({
|
createRoute({
|
||||||
tags: ["Auth"],
|
tags: ["Auth"],
|
||||||
summary: "Checks a user session based on there token",
|
summary: "Checks a user session based on there token",
|
||||||
description: "Can post there via Authentiaction header or cookies",
|
description: "Can post there via Authentiaction header or cookies",
|
||||||
method: "get",
|
method: "get",
|
||||||
path: "/session",
|
path: "/session",
|
||||||
middleware: authMiddleware,
|
middleware: authMiddleware,
|
||||||
// request: {
|
// request: {
|
||||||
// body: {
|
// body: {
|
||||||
// content: {
|
// content: {
|
||||||
// "application/json": {schema: UserSchema},
|
// "application/json": {schema: UserSchema},
|
||||||
// },
|
// },
|
||||||
// },
|
// },
|
||||||
// },
|
// },
|
||||||
responses: {
|
responses: {
|
||||||
200: {
|
200: {
|
||||||
content: {
|
content: {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
schema: z.object({
|
schema: z.object({
|
||||||
data: z.object({
|
data: z.object({
|
||||||
token: z
|
token: z.string().openapi({
|
||||||
.string()
|
example: "sdkjhgsldkvhdakl;jvhs;adkjfhvds.kvnsad;ovhads",
|
||||||
.openapi({
|
}),
|
||||||
example: "sdkjhgsldkvhdakl;jvhs;adkjfhvds.kvnsad;ovhads",
|
// user: z.object({
|
||||||
}),
|
// user_id: z.string().openapi({example: "04316c86-f086-4cc6-b3d4-cca164a26f3f"}),
|
||||||
// user: z.object({
|
// username: z.string().openapi({example: "smith"}),
|
||||||
// user_id: z.string().openapi({example: "04316c86-f086-4cc6-b3d4-cca164a26f3f"}),
|
// email: z.string().openapi({example: "smith@example.com"}).optional(),
|
||||||
// username: z.string().openapi({example: "smith"}),
|
// }),
|
||||||
// email: z.string().openapi({example: "smith@example.com"}).optional(),
|
}),
|
||||||
// }),
|
}),
|
||||||
}),
|
},
|
||||||
}),
|
},
|
||||||
},
|
description: "Login successful",
|
||||||
},
|
},
|
||||||
description: "Login successful",
|
401: {
|
||||||
},
|
content: {
|
||||||
401: {
|
"application/json": {
|
||||||
content: {
|
schema: z.object({
|
||||||
"application/json": {
|
message: z.string().openapi({ example: "Unathenticated" }),
|
||||||
schema: z.object({
|
}),
|
||||||
message: z.string().openapi({ example: "Unathenticated" }),
|
},
|
||||||
}),
|
},
|
||||||
},
|
description: "Error of why you were not logged in.",
|
||||||
},
|
},
|
||||||
description: "Error of why you were not logged in.",
|
},
|
||||||
},
|
}),
|
||||||
},
|
async (c: any) => {
|
||||||
}),
|
const cookieHeader = c.req.header("Cookie");
|
||||||
async (c) => {
|
if (!cookieHeader) return c.json({ error: "Unauthorized" }, 401);
|
||||||
const authHeader = c.req.header("Authorization");
|
|
||||||
|
|
||||||
if (authHeader?.includes("Basic")) {
|
const res = await axios.get(`${process.env.LST_BASE_URL}/api/user/me`, {
|
||||||
return c.json(
|
headers: { Cookie: cookieHeader },
|
||||||
{ message: "You are a Basic user! Please login to get a token" },
|
withCredentials: true,
|
||||||
401
|
});
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!authHeader) {
|
if (res.status === 401) return c.json({ error: "Unauthorized" }, 401);
|
||||||
return c.json({ message: "Unauthorized" }, 401);
|
|
||||||
}
|
|
||||||
|
|
||||||
const token = authHeader?.split("Bearer ")[1] || "";
|
const user = res.data.user;
|
||||||
|
|
||||||
try {
|
// ── record session heartbeat ───────────────────────────────────────────
|
||||||
const payload = await verify(token, process.env.JWT_SECRET!);
|
activeSessions[user.id] = {
|
||||||
|
lastSeen: Date.now(),
|
||||||
|
expiresAt: Date.now() + SESSION_TIMEOUT_MS,
|
||||||
|
};
|
||||||
|
|
||||||
// If it's valid, return a new token
|
// clean up stale sessions in the background
|
||||||
const newToken = sign({ user: payload.user }, secret, {
|
for (const [key, sess] of Object.entries(activeSessions)) {
|
||||||
expiresIn: expiresIn * 60,
|
if (Date.now() > sess.expiresAt) delete activeSessions[key];
|
||||||
});
|
}
|
||||||
|
|
||||||
return c.json({ data: { token: newToken, user: payload.user } }, 200);
|
const setCookie =
|
||||||
} catch (error) {
|
res.headers &&
|
||||||
return c.json({ message: "Unauthorized" }, 401);
|
((res.headers["set-cookie"] || res.headers["Set-Cookie"]) as
|
||||||
}
|
| string[]
|
||||||
}
|
| undefined);
|
||||||
|
|
||||||
|
if (setCookie) c.header("Set-Cookie", setCookie);
|
||||||
|
|
||||||
|
return c.json(
|
||||||
|
{ data: { token: res.data.token, user: res.data.user } },
|
||||||
|
200,
|
||||||
|
);
|
||||||
|
|
||||||
|
// 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] || "";
|
||||||
|
|
||||||
|
// try {
|
||||||
|
// const payload = await verify(token, process.env.JWT_SECRET!);
|
||||||
|
|
||||||
|
// // If it's valid, return a new token
|
||||||
|
// const newToken = sign({ user: payload.user }, secret, {
|
||||||
|
// expiresIn: expiresIn * 60,
|
||||||
|
// });
|
||||||
|
|
||||||
|
// return c.json({ data: { token: newToken, user: payload.user } }, 200);
|
||||||
|
// } catch (error) {
|
||||||
|
// return c.json({ message: "Unauthorized" }, 401);
|
||||||
|
// }
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// const token = authHeader?.split("Bearer ")[1] || "";
|
// const token = authHeader?.split("Bearer ")[1] || "";
|
||||||
|
|||||||
@@ -1,59 +1,72 @@
|
|||||||
import { z, createRoute, OpenAPIHono } from "@hono/zod-openapi";
|
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
|
||||||
|
import axios from "axios";
|
||||||
import jwt from "jsonwebtoken";
|
import jwt from "jsonwebtoken";
|
||||||
import type { CustomJwtPayload } from "../../../../types/jwtToken.js";
|
import type { CustomJwtPayload } from "../../../../types/jwtToken.js";
|
||||||
import { authMiddleware } from "../../middleware/authMiddleware.js";
|
|
||||||
import { roleCheck } from "../../controllers/userRoles/getUserAccess.js";
|
import { roleCheck } from "../../controllers/userRoles/getUserAccess.js";
|
||||||
|
import { authMiddleware } from "../../middleware/authMiddleware.js";
|
||||||
|
|
||||||
const { verify } = jwt;
|
const { verify } = jwt;
|
||||||
const app = new OpenAPIHono();
|
const app = new OpenAPIHono();
|
||||||
|
|
||||||
const responseSchema = z.object({
|
const responseSchema = z.object({
|
||||||
message: z.string().optional().openapi({ example: "User Created" }),
|
message: z.string().optional().openapi({ example: "User Created" }),
|
||||||
});
|
});
|
||||||
|
|
||||||
app.openapi(
|
app.openapi(
|
||||||
createRoute({
|
createRoute({
|
||||||
tags: ["auth:user"],
|
tags: ["auth:user"],
|
||||||
summary: "returns the users access",
|
summary: "returns the users access",
|
||||||
method: "get",
|
method: "get",
|
||||||
path: "/getuseraccess",
|
path: "/getuseraccess",
|
||||||
middleware: [authMiddleware],
|
middleware: [authMiddleware],
|
||||||
responses: {
|
responses: {
|
||||||
200: {
|
200: {
|
||||||
content: { "application/json": { schema: responseSchema } },
|
content: { "application/json": { schema: responseSchema } },
|
||||||
description: "Retrieve the user",
|
description: "Retrieve the user",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
async (c) => {
|
async (c: any) => {
|
||||||
// apit hit
|
// apit hit
|
||||||
//apiHit(c, { endpoint: "api/auth/getUserRoles" });
|
//apiHit(c, { endpoint: "api/auth/getUserRoles" });
|
||||||
const authHeader = c.req.header("Authorization");
|
const authHeader = c.req.header("Authorization");
|
||||||
const token = authHeader?.split("Bearer ")[1] || "";
|
|
||||||
try {
|
|
||||||
const secret = process.env.JWT_SECRET!;
|
|
||||||
if (!secret) {
|
|
||||||
throw new Error("JWT_SECRET is not defined in environment variables");
|
|
||||||
}
|
|
||||||
|
|
||||||
const payload = verify(token, secret) as CustomJwtPayload;
|
const user = c.get("user");
|
||||||
|
|
||||||
const canAccess = await roleCheck(payload.user?.user_id);
|
if (!user) {
|
||||||
|
return c.json(
|
||||||
|
{
|
||||||
|
success: true,
|
||||||
|
message: `Unauthorized`,
|
||||||
|
},
|
||||||
|
401,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const cookieHeader = c.req.header("Cookie");
|
||||||
|
if (!cookieHeader) return c.json({ error: "Unauthorized" }, 401);
|
||||||
|
|
||||||
return c.json(
|
const res = await axios.get(
|
||||||
{
|
`${process.env.LST_BASE_URL}/api/user/roles`,
|
||||||
sucess: true,
|
{
|
||||||
message: `User ${payload.user?.username} can access`,
|
headers: { Cookie: cookieHeader },
|
||||||
data: canAccess,
|
},
|
||||||
},
|
);
|
||||||
200
|
|
||||||
);
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.json({ message: "UserRoles coming over" });
|
return c.json(
|
||||||
}
|
{
|
||||||
|
success: true,
|
||||||
|
message: `User ${user.username} can access`,
|
||||||
|
data: res.data.data,
|
||||||
|
},
|
||||||
|
200,
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.json({ message: "UserRoles coming over" });
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
export default app;
|
export default app;
|
||||||
|
|||||||
@@ -1,154 +1,152 @@
|
|||||||
|
import { eq } from "drizzle-orm";
|
||||||
import { db } from "../../../../../database/dbclient.js";
|
import { db } from "../../../../../database/dbclient.js";
|
||||||
|
import { settings } from "../../../../../database/schema/settings.js";
|
||||||
|
import { siloAdjustments } from "../../../../../database/schema/siloAdjustments.js";
|
||||||
|
import { greetingStuff } from "../../../../globalUtils/greetingEmail.js";
|
||||||
|
import { generateOneTimeKey } from "../../../../globalUtils/singleUseKey.js";
|
||||||
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
|
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
|
||||||
|
import { sendEmail } from "../../../notifications/controller/sendMail.js";
|
||||||
|
import {
|
||||||
|
getSettings,
|
||||||
|
serverSettings,
|
||||||
|
} from "../../../server/controller/settings/getSettings.js";
|
||||||
import { query } from "../../../sqlServer/prodSqlServer.js";
|
import { query } from "../../../sqlServer/prodSqlServer.js";
|
||||||
import { siloQuery } from "../../../sqlServer/querys/silo/siloQuery.js";
|
import { siloQuery } from "../../../sqlServer/querys/silo/siloQuery.js";
|
||||||
import { postAdjustment } from "./postAdjustment.js";
|
import { postAdjustment } from "./postAdjustment.js";
|
||||||
import { siloAdjustments } from "../../../../../database/schema/siloAdjustments.js";
|
|
||||||
import { greetingStuff } from "../../../../globalUtils/greetingEmail.js";
|
|
||||||
import { sendEmail } from "../../../notifications/controller/sendMail.js";
|
|
||||||
import { settings } from "../../../../../database/schema/settings.js";
|
|
||||||
import { generateOneTimeKey } from "../../../../globalUtils/singleUseKey.js";
|
|
||||||
import { eq } from "drizzle-orm";
|
|
||||||
import {
|
|
||||||
getSettings,
|
|
||||||
serverSettings,
|
|
||||||
} from "../../../server/controller/settings/getSettings.js";
|
|
||||||
|
|
||||||
export const createSiloAdjustment = async (
|
export const createSiloAdjustment = async (
|
||||||
data: any | null,
|
data: any | null,
|
||||||
user: any | null
|
user: any | null,
|
||||||
) => {
|
) => {
|
||||||
/**
|
/**
|
||||||
* Creates a silo adjustment based off warehouse, location, and qty.
|
* Creates a silo adjustment based off warehouse, location, and qty.
|
||||||
* qty will come from the hmi, prolink, or silo patrol
|
* qty will come from the hmi, prolink, or silo patrol
|
||||||
*/
|
*/
|
||||||
// const { data: set, error: setError } = await tryCatch(
|
// const { data: set, error: setError } = await tryCatch(
|
||||||
// db.select().from(settings)
|
// db.select().from(settings)
|
||||||
// );
|
// );
|
||||||
|
|
||||||
// const { data: set, error: setError } = await tryCatch(getSettings());
|
// const { data: set, error: setError } = await tryCatch(getSettings());
|
||||||
|
|
||||||
// if (setError) {
|
// if (setError) {
|
||||||
// return {
|
// return {
|
||||||
// success: false,
|
// success: false,
|
||||||
// message: `There was an error getting setting data to post to the server.`,
|
// message: `There was an error getting setting data to post to the server.`,
|
||||||
// data: setError,
|
// data: setError,
|
||||||
// };
|
// };
|
||||||
// }
|
// }
|
||||||
|
|
||||||
const set = serverSettings.length === 0 ? [] : serverSettings;
|
const set = serverSettings.length === 0 ? [] : serverSettings;
|
||||||
// getting stock data first so we have it prior to the adjustment
|
// getting stock data first so we have it prior to the adjustment
|
||||||
const { data: s, error: stockError } = await tryCatch(
|
const { data: s, error: stockError } = await tryCatch(
|
||||||
query(siloQuery, "Silo data Query")
|
query(siloQuery, "Silo data Query"),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (stockError) {
|
if (stockError) {
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
message: `There was an error getting stock data to post to the server.`,
|
message: `There was an error getting stock data to post to the server.`,
|
||||||
data: stockError,
|
data: stockError,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
const stock: any = s?.data as any;
|
const stock: any = s?.data as any;
|
||||||
const { data: a, error: errorAdj } = await tryCatch(
|
const { data: a, error: errorAdj } = await tryCatch(postAdjustment(data));
|
||||||
postAdjustment(data, user.prod)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (errorAdj) {
|
if (errorAdj) {
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
message: `There was an error doing the silo adjustment.`,
|
message: `There was an error doing the silo adjustment.`,
|
||||||
data: errorAdj,
|
data: errorAdj,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Checking to see the difference, and send email if +/- 5% will change later if needed
|
* Checking to see the difference, and send email if +/- 5% will change later if needed
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const sa: any = a;
|
const sa: any = a;
|
||||||
|
|
||||||
if (!sa.success) {
|
if (!sa.success) {
|
||||||
console.log(`insde error`);
|
console.log(`inside error`);
|
||||||
return {
|
return {
|
||||||
success: sa.success,
|
success: sa.success,
|
||||||
message: sa.message,
|
message: sa.message,
|
||||||
data: sa.data,
|
data: sa.data,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const stockNummy = stock.filter((s: any) => s.LocationID === data.laneId);
|
const stockNummy = stock.filter((s: any) => s.LocationID === data.laneId);
|
||||||
const theDiff =
|
const theDiff =
|
||||||
((data.quantity - stockNummy[0].Stock_Total) /
|
((data.quantity - stockNummy[0].Stock_Total) /
|
||||||
((data.quantity + stockNummy[0].Stock_Total) / 2)) *
|
((data.quantity + stockNummy[0].Stock_Total) / 2)) *
|
||||||
100;
|
100;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Post the data to our db.
|
* Post the data to our db.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//console.log(stockNummy);
|
//console.log(stockNummy);
|
||||||
const { data: postAdj, error: postAdjError } = await tryCatch(
|
const { data: postAdj, error: postAdjError } = await tryCatch(
|
||||||
db
|
db
|
||||||
.insert(siloAdjustments)
|
.insert(siloAdjustments)
|
||||||
.values({
|
.values({
|
||||||
warehouseID: data.warehouseId,
|
warehouseID: data.warehouseId,
|
||||||
locationID: data.laneId,
|
locationID: data.laneId,
|
||||||
currentStockLevel: stockNummy[0].Stock_Total,
|
currentStockLevel: stockNummy[0].Stock_Total,
|
||||||
newLevel: data.quantity,
|
newLevel: data.quantity,
|
||||||
lastDateAdjusted: new Date(stockNummy[0].LastAdjustment),
|
lastDateAdjusted: new Date(stockNummy[0].LastAdjustment),
|
||||||
add_user: user.username,
|
add_user: user.username,
|
||||||
})
|
})
|
||||||
.returning({ id: siloAdjustments.siloAdjust_id })
|
.returning({ id: siloAdjustments.siloAdjust_id }),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (postAdjError) {
|
if (postAdjError) {
|
||||||
//console.log(postAdjError);
|
//console.log(postAdjError);
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
message: `There was an error posting the new adjustment.`,
|
message: `There was an error posting the new adjustment.`,
|
||||||
data: postAdjError,
|
data: postAdjError,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
let adj: any = a;
|
let adj: any = a;
|
||||||
if (Math.abs(theDiff) > 5) {
|
if (Math.abs(theDiff) > 5) {
|
||||||
// console.log(`Send for comment due to being: ${theDiff.toFixed(2)}%`);
|
// console.log(`Send for comment due to being: ${theDiff.toFixed(2)}%`);
|
||||||
const server = set.filter((n: any) => n.name === "server");
|
const server = set.filter((n: any) => n.name === "server");
|
||||||
|
|
||||||
const port = set.filter((n: any) => n.name === "serverPort");
|
const port = set.filter((n: any) => n.name === "serverPort");
|
||||||
const key = await generateOneTimeKey();
|
const key = await generateOneTimeKey();
|
||||||
const updateKey = await db
|
const updateKey = await db
|
||||||
.update(siloAdjustments)
|
.update(siloAdjustments)
|
||||||
.set({ commentKey: key })
|
.set({ commentKey: key })
|
||||||
.where(eq(siloAdjustments.siloAdjust_id, postAdj[0].id));
|
.where(eq(siloAdjustments.siloAdjust_id, postAdj[0].id));
|
||||||
|
|
||||||
const emailSetup = {
|
const emailSetup = {
|
||||||
email: user.email,
|
email: user.email,
|
||||||
subject: `Alert - Siloadjustment was done with a descrepancy of 5% or greater`,
|
subject: `Alert - Siloadjustment was done with a descrepancy of 5% or greater`,
|
||||||
template: "siloAdjustmentComment",
|
template: "siloAdjustmentComment",
|
||||||
context: {
|
context: {
|
||||||
greeting: await greetingStuff(),
|
greeting: await greetingStuff(),
|
||||||
siloName: stockNummy[0].Description,
|
siloName: stockNummy[0].Description,
|
||||||
variance: `${theDiff.toFixed(2)}%`,
|
variance: `${theDiff.toFixed(2)}%`,
|
||||||
currentLevel: stockNummy[0].Stock_Total,
|
currentLevel: stockNummy[0].Stock_Total,
|
||||||
newLevel: data.quantity,
|
newLevel: data.quantity,
|
||||||
variancePer: 5,
|
variancePer: 5,
|
||||||
adjustID: `${postAdj[0].id}&${key}`,
|
adjustID: `${postAdj[0].id}&${key}`,
|
||||||
server: server[0].value,
|
server: server[0].value,
|
||||||
port: port[0].value,
|
port: port[0].value,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
//console.log(emailSetup);
|
//console.log(emailSetup);
|
||||||
|
|
||||||
await sendEmail(emailSetup);
|
await sendEmail(emailSetup);
|
||||||
return {
|
return {
|
||||||
success: adj.success,
|
success: adj.success,
|
||||||
message: `Silo adjustmnet was completed you will also receive and email due to the adjustment having a variation of ${Math.abs(
|
message: `Silo adjustmnet was completed you will also receive and email due to the adjustment having a variation of ${Math.abs(
|
||||||
theDiff
|
theDiff,
|
||||||
).toFixed(2)}%`,
|
).toFixed(2)}%`,
|
||||||
data: adj.data,
|
data: adj.data,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
return { success: adj.success, message: adj.message, data: adj.data };
|
return { success: adj.success, message: adj.message, data: adj.data };
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,99 +2,99 @@ import axios from "axios";
|
|||||||
import { prodEndpointCreation } from "../../../../globalUtils/createUrl.js";
|
import { prodEndpointCreation } from "../../../../globalUtils/createUrl.js";
|
||||||
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
|
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
|
||||||
|
|
||||||
export const postAdjustment = async (data: any, prod: any) => {
|
export const postAdjustment = async (data: any) => {
|
||||||
if (data.warehouseId === undefined) {
|
if (data.warehouseId === undefined) {
|
||||||
return {
|
return {
|
||||||
sucess: false,
|
sucess: false,
|
||||||
message: `Missing mandatory field: warehouseID`,
|
message: `Missing mandatory field: warehouseID`,
|
||||||
data: { error: `Missing mandatory field: warehouseID` },
|
data: { error: `Missing mandatory field: warehouseID` },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.laneId === undefined) {
|
if (data.laneId === undefined) {
|
||||||
return {
|
return {
|
||||||
sucess: false,
|
sucess: false,
|
||||||
message: `Missing mandatory field: locationID`,
|
message: `Missing mandatory field: locationID`,
|
||||||
data: { error: `Missing mandatory field: locationID` },
|
data: { error: `Missing mandatory field: locationID` },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.quantity == "0") {
|
if (data.quantity == "0") {
|
||||||
return {
|
return {
|
||||||
sucess: false,
|
sucess: false,
|
||||||
message: `You entered 0 for the quantity to post, quantity needs to be at leave 1`,
|
message: `You entered 0 for the quantity to post, quantity needs to be at leave 1`,
|
||||||
data: {
|
data: {
|
||||||
error: `You entered 0 for the quantity to post, quantity needs to be at leave 1`,
|
error: `You entered 0 for the quantity to post, quantity needs to be at leave 1`,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const siloAdjustment = {
|
const siloAdjustment = {
|
||||||
warehouseId: data.warehouseId,
|
warehouseId: data.warehouseId,
|
||||||
laneId: data.laneId,
|
laneId: data.laneId,
|
||||||
quantity: data.quantity,
|
quantity: data.quantity,
|
||||||
};
|
};
|
||||||
|
|
||||||
let url = await prodEndpointCreation(
|
let url = await prodEndpointCreation(
|
||||||
"/public/v1.0/Warehousing/AdjustSiloStockLevel"
|
"/public/v1.0/Warehousing/AdjustSiloStockLevel",
|
||||||
);
|
);
|
||||||
|
|
||||||
const { data: silo, error } = await tryCatch(
|
const { data: silo, error } = await tryCatch(
|
||||||
axios.post(url, siloAdjustment, {
|
axios.post(url, siloAdjustment, {
|
||||||
headers: {
|
headers: {
|
||||||
"X-API-Key": process.env.TEC_API_KEY || "",
|
"X-API-Key": process.env.TEC_API_KEY || "",
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
},
|
},
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
let e = error as any;
|
let e = error as any;
|
||||||
if (e) {
|
if (e) {
|
||||||
console.log(e.response);
|
console.log(e.response);
|
||||||
if (e.status === 401) {
|
if (e.status === 401) {
|
||||||
const data = {
|
const data = {
|
||||||
success: false,
|
success: false,
|
||||||
message: `There was error posting the data: ${JSON.stringify(
|
message: `There was error posting the data: ${JSON.stringify(
|
||||||
e.response?.data
|
e.response?.data,
|
||||||
)}`,
|
)}`,
|
||||||
data: {
|
data: {
|
||||||
status: e.response?.status,
|
status: e.response?.status,
|
||||||
statusText: e.response?.statusText,
|
statusText: e.response?.statusText,
|
||||||
data: e.response?.data,
|
data: e.response?.data,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
return data;
|
return data;
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
message: "Error in posting the silo adjustment.",
|
message: "Error in posting the silo adjustment.",
|
||||||
data: {
|
data: {
|
||||||
status: e.response?.status,
|
status: e.response?.status,
|
||||||
statusText: e.response?.statusText,
|
statusText: e.response?.statusText,
|
||||||
data: e.response?.data,
|
data: e.response?.data,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (silo?.status !== 200) {
|
if (silo?.status !== 200) {
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
message: "Error in posting the silo adjustment",
|
message: "Error in posting the silo adjustment",
|
||||||
data: {
|
data: {
|
||||||
status: silo?.status,
|
status: silo?.status,
|
||||||
statusText: silo?.statusText,
|
statusText: silo?.statusText,
|
||||||
data: silo?.data,
|
data: silo?.data,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
message: "Adjustment was completed",
|
message: "Adjustment was completed",
|
||||||
data: {
|
data: {
|
||||||
status: silo.status,
|
status: silo.status,
|
||||||
statusText: silo.statusText,
|
statusText: silo.statusText,
|
||||||
data: silo.data,
|
data: silo.data,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
|
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
|
||||||
import { responses } from "../../../../globalUtils/routeDefs/responses.js";
|
|
||||||
import { ordersIn } from "../../controller/dm/ordersIn/ordersIn.js";
|
|
||||||
import { verify } from "hono/jwt";
|
import { verify } from "hono/jwt";
|
||||||
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
|
|
||||||
import { apiHit } from "../../../../globalUtils/apiHits.js";
|
import { apiHit } from "../../../../globalUtils/apiHits.js";
|
||||||
|
import { responses } from "../../../../globalUtils/routeDefs/responses.js";
|
||||||
|
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
|
||||||
|
import { authMiddleware } from "../../../auth/middleware/authMiddleware.js";
|
||||||
|
import { ordersIn } from "../../controller/dm/ordersIn/ordersIn.js";
|
||||||
|
|
||||||
const app = new OpenAPIHono();
|
const app = new OpenAPIHono();
|
||||||
|
|
||||||
@@ -15,61 +16,53 @@ const app = new OpenAPIHono();
|
|||||||
// })
|
// })
|
||||||
// .openapi("User");
|
// .openapi("User");
|
||||||
app.openapi(
|
app.openapi(
|
||||||
createRoute({
|
createRoute({
|
||||||
tags: ["logistics"],
|
tags: ["logistics"],
|
||||||
summary: "Post orders to DM",
|
summary: "Post orders to DM",
|
||||||
method: "post",
|
method: "post",
|
||||||
path: "/postbulkorders",
|
path: "/postbulkorders",
|
||||||
// request: {
|
middleware: authMiddleware,
|
||||||
// body: {
|
// request: {
|
||||||
// content: {
|
// body: {
|
||||||
// "application/json": { schema: Body },
|
// content: {
|
||||||
// },
|
// "application/json": { schema: Body },
|
||||||
// },
|
// },
|
||||||
// },
|
// },
|
||||||
// description:
|
// },
|
||||||
// "Provided a running number and lot number you can consume material.",
|
// description:
|
||||||
responses: responses(),
|
// "Provided a running number and lot number you can consume material.",
|
||||||
}),
|
responses: responses(),
|
||||||
async (c) => {
|
}),
|
||||||
apiHit(c, { endpoint: "/postbulkorders" });
|
async (c) => {
|
||||||
const body = await c.req.parseBody();
|
apiHit(c, { endpoint: "/postbulkorders" });
|
||||||
const authHeader = c.req.header("Authorization");
|
const body = await c.req.parseBody();
|
||||||
const token = authHeader?.split("Bearer ")[1] || "";
|
//console.log(body); // File | string
|
||||||
//console.log(body); // File | string
|
|
||||||
|
|
||||||
// if (body["fileType"] === "standard") {
|
// if (body["fileType"] === "standard") {
|
||||||
// console.log(`doing standard orders in.`);
|
// console.log(`doing standard orders in.`);
|
||||||
// }
|
// }
|
||||||
const { data: payload, error: pe } = await tryCatch(
|
|
||||||
verify(token, process.env.JWT_SECRET!)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (pe) {
|
const { data: orders, error } = await tryCatch(
|
||||||
return c.json({ success: false, message: "Unauthorized" }, 401);
|
ordersIn(body, c.get("user")),
|
||||||
}
|
);
|
||||||
|
|
||||||
const { data: orders, error } = await tryCatch(
|
if (error) {
|
||||||
ordersIn(body, payload.user)
|
console.log(error);
|
||||||
);
|
return c.json(
|
||||||
|
{
|
||||||
|
success: false,
|
||||||
|
message: "Error posting Orders",
|
||||||
|
data: error,
|
||||||
|
},
|
||||||
|
400,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (error) {
|
return c.json({
|
||||||
console.log(error);
|
success: orders?.success ?? false,
|
||||||
return c.json(
|
message: orders?.message ?? "Error posting forecast",
|
||||||
{
|
data: orders?.data ?? [],
|
||||||
success: false,
|
});
|
||||||
message: "Error posting Orders",
|
},
|
||||||
data: error,
|
|
||||||
},
|
|
||||||
400
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.json({
|
|
||||||
success: orders?.success ?? false,
|
|
||||||
message: orders?.message ?? "Error posting forecast",
|
|
||||||
data: orders?.data ?? [],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
export default app;
|
export default app;
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
|
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
|
||||||
import { responses } from "../../../../globalUtils/routeDefs/responses.js";
|
|
||||||
import { ordersIn } from "../../controller/dm/ordersIn/ordersIn.js";
|
|
||||||
import { verify } from "hono/jwt";
|
import { verify } from "hono/jwt";
|
||||||
import { forecastIn } from "../../controller/dm/forecast/forecastIn.js";
|
|
||||||
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
|
|
||||||
import { apiHit } from "../../../../globalUtils/apiHits.js";
|
import { apiHit } from "../../../../globalUtils/apiHits.js";
|
||||||
|
import { responses } from "../../../../globalUtils/routeDefs/responses.js";
|
||||||
|
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
|
||||||
|
import { authMiddleware } from "../../../auth/middleware/authMiddleware.js";
|
||||||
|
import { forecastIn } from "../../controller/dm/forecast/forecastIn.js";
|
||||||
|
import { ordersIn } from "../../controller/dm/ordersIn/ordersIn.js";
|
||||||
|
|
||||||
const app = new OpenAPIHono();
|
const app = new OpenAPIHono();
|
||||||
|
|
||||||
@@ -16,61 +17,54 @@ const app = new OpenAPIHono();
|
|||||||
// })
|
// })
|
||||||
// .openapi("User");
|
// .openapi("User");
|
||||||
app.openapi(
|
app.openapi(
|
||||||
createRoute({
|
createRoute({
|
||||||
tags: ["logistics"],
|
tags: ["logistics"],
|
||||||
summary: "Post forecast to DM",
|
summary: "Post forecast to DM",
|
||||||
method: "post",
|
method: "post",
|
||||||
path: "/postforecastin",
|
path: "/postforecastin",
|
||||||
// request: {
|
middleware: authMiddleware,
|
||||||
// body: {
|
// request: {
|
||||||
// content: {
|
// body: {
|
||||||
// "application/json": { schema: Body },
|
// content: {
|
||||||
// },
|
// "application/json": { schema: Body },
|
||||||
// },
|
// },
|
||||||
// },
|
// },
|
||||||
// description:
|
// },
|
||||||
// "Provided a running number and lot number you can consume material.",
|
// description:
|
||||||
responses: responses(),
|
// "Provided a running number and lot number you can consume material.",
|
||||||
}),
|
responses: responses(),
|
||||||
async (c) => {
|
}),
|
||||||
apiHit(c, { endpoint: "/postforecastin" });
|
async (c) => {
|
||||||
const body = await c.req.parseBody();
|
apiHit(c, { endpoint: "/postforecastin" });
|
||||||
const authHeader = c.req.header("Authorization");
|
const body = await c.req.parseBody();
|
||||||
const token = authHeader?.split("Bearer ")[1] || "";
|
|
||||||
//console.log(body); // File | string
|
|
||||||
|
|
||||||
// if (body["fileType"] === "standard") {
|
//console.log(body); // File | string
|
||||||
// console.log(`doing standard orders in.`);
|
|
||||||
// }
|
|
||||||
const { data: payload, error: pe } = await tryCatch(
|
|
||||||
verify(token, process.env.JWT_SECRET!)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (pe) {
|
// if (body["fileType"] === "standard") {
|
||||||
return c.json({ success: false, message: "Unauthorized" }, 401);
|
// console.log(`doing standard orders in.`);
|
||||||
}
|
// }
|
||||||
|
|
||||||
const { data: orders, error } = await tryCatch(
|
const { data: orders, error } = await tryCatch(
|
||||||
forecastIn(body, payload.user)
|
forecastIn(body, c.get("user")),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
return c.json(
|
return c.json(
|
||||||
{
|
{
|
||||||
success: false,
|
success: false,
|
||||||
message: "Error posting forecast",
|
message: "Error posting forecast",
|
||||||
data: error,
|
data: error,
|
||||||
},
|
},
|
||||||
400
|
400,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.json({
|
return c.json({
|
||||||
success: orders?.success ?? false,
|
success: orders?.success ?? false,
|
||||||
message: orders?.message ?? "Error posting forecast",
|
message: orders?.message ?? "Error posting forecast",
|
||||||
data: orders?.data ?? [],
|
data: orders?.data ?? [],
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
export default app;
|
export default app;
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
|
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
|
||||||
import { format } from "date-fns";
|
import { format } from "date-fns";
|
||||||
import { responses } from "../../../../globalUtils/routeDefs/responses.js";
|
|
||||||
import { standardTemplate } from "../../controller/dm/ordersIn/createTemplate.js";
|
|
||||||
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
|
|
||||||
import { standardForCastTemplate } from "../../controller/dm/forecast/createTemplate.js";
|
|
||||||
import { apiHit } from "../../../../globalUtils/apiHits.js";
|
import { apiHit } from "../../../../globalUtils/apiHits.js";
|
||||||
|
import { responses } from "../../../../globalUtils/routeDefs/responses.js";
|
||||||
|
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
|
||||||
|
|
||||||
|
import { standardForCastTemplate } from "../../controller/dm/forecast/createTemplate.js";
|
||||||
|
|
||||||
const app = new OpenAPIHono();
|
const app = new OpenAPIHono();
|
||||||
|
|
||||||
@@ -16,52 +16,52 @@ const app = new OpenAPIHono();
|
|||||||
// })
|
// })
|
||||||
// .openapi("User");
|
// .openapi("User");
|
||||||
app.openapi(
|
app.openapi(
|
||||||
createRoute({
|
createRoute({
|
||||||
tags: ["logistics"],
|
tags: ["logistics"],
|
||||||
summary: "Gets the standard Forecast Template",
|
summary: "Gets the standard Forecast Template",
|
||||||
method: "get",
|
method: "get",
|
||||||
path: "/bulkforcasttemplate",
|
path: "/bulkforcasttemplate",
|
||||||
// request: {
|
// request: {
|
||||||
// body: {
|
// body: {
|
||||||
// content: {
|
// content: {
|
||||||
// "application/json": { schema: Body },
|
// "application/json": { schema: Body },
|
||||||
// },
|
// },
|
||||||
// },
|
// },
|
||||||
// },
|
// },
|
||||||
// description:
|
// description:
|
||||||
// "Provided a running number and lot number you can consume material.",
|
// "Provided a running number and lot number you can consume material.",
|
||||||
responses: responses(),
|
responses: responses(),
|
||||||
}),
|
}),
|
||||||
async (c: any) => {
|
async (c: any) => {
|
||||||
apiHit(c, { endpoint: "/bulkforcasttemplate" });
|
apiHit(c, { endpoint: "/bulkforcasttemplate" });
|
||||||
const defaultFilename = `bulkForcastTemplate-${format(
|
const defaultFilename = `bulkForcastTemplate-${format(
|
||||||
new Date(Date.now()),
|
new Date(Date.now()),
|
||||||
"M-d-yyyy"
|
"M-d-yyyy",
|
||||||
)}.xlsx`;
|
)}.xlsx`;
|
||||||
const filename = c.req.query("filename") || defaultFilename;
|
const filename = c.req.query("filename") || defaultFilename;
|
||||||
const { data, error } = await tryCatch(standardForCastTemplate());
|
const { data, error } = await tryCatch(standardForCastTemplate());
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
return c.json({
|
return c.json({
|
||||||
success: false,
|
success: false,
|
||||||
message: "Error creating template",
|
message: "Error creating template",
|
||||||
data: error,
|
data: error,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Response(data, {
|
return new Response(data, {
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type":
|
"Content-Type":
|
||||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||||
"Content-Disposition": `attachment; filename="${filename}"`,
|
"Content-Disposition": `attachment; filename="${filename}"`,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// return c.json({
|
// return c.json({
|
||||||
// success: data.success,
|
// success: data.success,
|
||||||
// message: data.message,
|
// message: data.message,
|
||||||
// data: data.data,
|
// data: data.data,
|
||||||
// });
|
// });
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
export default app;
|
export default app;
|
||||||
|
|||||||
@@ -1,78 +1,74 @@
|
|||||||
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
|
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
|
||||||
import { verify } from "hono/jwt";
|
import { verify } from "hono/jwt";
|
||||||
import { authMiddleware } from "../../../auth/middleware/authMiddleware.js";
|
|
||||||
import { responses } from "../../../../globalUtils/routeDefs/responses.js";
|
|
||||||
import { createSiloAdjustment } from "../../controller/siloAdjustments/createSiloAdjustment.js";
|
|
||||||
import { apiHit } from "../../../../globalUtils/apiHits.js";
|
import { apiHit } from "../../../../globalUtils/apiHits.js";
|
||||||
|
import { responses } from "../../../../globalUtils/routeDefs/responses.js";
|
||||||
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
|
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
|
||||||
|
import { authMiddleware } from "../../../auth/middleware/authMiddleware.js";
|
||||||
|
import { createSiloAdjustment } from "../../controller/siloAdjustments/createSiloAdjustment.js";
|
||||||
|
|
||||||
const app = new OpenAPIHono();
|
const app = new OpenAPIHono();
|
||||||
|
|
||||||
const responseSchema = z.object({
|
const responseSchema = z.object({
|
||||||
success: z.boolean().optional().openapi({ example: true }),
|
success: z.boolean().optional().openapi({ example: true }),
|
||||||
message: z.string().optional().openapi({ example: "user access" }),
|
message: z.string().optional().openapi({ example: "user access" }),
|
||||||
});
|
});
|
||||||
|
|
||||||
app.openapi(
|
app.openapi(
|
||||||
createRoute({
|
createRoute({
|
||||||
tags: ["logistics"],
|
tags: ["logistics"],
|
||||||
summary: "Creates silo adjustmennt",
|
summary: "Creates silo adjustmennt",
|
||||||
method: "post",
|
method: "post",
|
||||||
path: "/createsiloadjustment",
|
path: "/createsiloadjustment",
|
||||||
middleware: authMiddleware,
|
middleware: authMiddleware,
|
||||||
description:
|
description:
|
||||||
"Creates a silo adjustment for the silo if and stores the stock numbers.",
|
"Creates a silo adjustment for the silo if and stores the stock numbers.",
|
||||||
responses: responses(),
|
responses: responses(),
|
||||||
}),
|
}),
|
||||||
async (c) => {
|
async (c) => {
|
||||||
const { data, error } = await tryCatch(c.req.json());
|
const { data, error } = await tryCatch(c.req.json());
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
return c.json(
|
return c.json(
|
||||||
{
|
{
|
||||||
success: false,
|
success: false,
|
||||||
message: "Missing data please try again",
|
message: "Missing data please try again",
|
||||||
error,
|
error,
|
||||||
},
|
},
|
||||||
400
|
400,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
apiHit(c, { endpoint: "/createsiloadjustment", lastBody: data });
|
apiHit(c, { endpoint: "/createsiloadjustment", lastBody: data });
|
||||||
const authHeader = c.req.header("Authorization");
|
|
||||||
const token = authHeader?.split("Bearer ")[1] || "";
|
|
||||||
|
|
||||||
try {
|
const user = c.get("user");
|
||||||
const payload = await verify(token, process.env.JWT_SECRET!);
|
|
||||||
try {
|
|
||||||
//return apiReturn(c, true, access?.message, access?.data, 200);
|
|
||||||
const createSiloAdj = await createSiloAdjustment(
|
|
||||||
data,
|
|
||||||
payload.user
|
|
||||||
);
|
|
||||||
|
|
||||||
return c.json(
|
try {
|
||||||
{
|
try {
|
||||||
success: createSiloAdj.success,
|
//return apiReturn(c, true, access?.message, access?.data, 200);
|
||||||
message: createSiloAdj.message,
|
const createSiloAdj = await createSiloAdjustment(data, c.get("user"));
|
||||||
data: createSiloAdj.data,
|
|
||||||
},
|
return c.json(
|
||||||
200
|
{
|
||||||
);
|
success: createSiloAdj.success,
|
||||||
} catch (error) {
|
message: createSiloAdj.message,
|
||||||
//console.log(error);
|
data: createSiloAdj.data,
|
||||||
//return apiReturn(c, false, "Error in setting the user access", error, 400);
|
},
|
||||||
return c.json(
|
200,
|
||||||
{
|
);
|
||||||
success: false,
|
} catch (error) {
|
||||||
message: "Missing data please try again",
|
//console.log(error);
|
||||||
error,
|
//return apiReturn(c, false, "Error in setting the user access", error, 400);
|
||||||
},
|
return c.json(
|
||||||
400
|
{
|
||||||
);
|
success: false,
|
||||||
}
|
message: "Missing data please try again",
|
||||||
} catch (error) {
|
error,
|
||||||
return c.json({ success: false, message: "Unauthorized" }, 401);
|
},
|
||||||
}
|
400,
|
||||||
}
|
);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
return c.json({ success: false, message: "Unauthorized" }, 401);
|
||||||
|
}
|
||||||
|
},
|
||||||
);
|
);
|
||||||
export default app;
|
export default app;
|
||||||
|
|||||||
@@ -1,88 +1,85 @@
|
|||||||
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
|
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
|
||||||
import { verify } from "hono/jwt";
|
import { verify } from "hono/jwt";
|
||||||
import { authMiddleware } from "../../../auth/middleware/authMiddleware.js";
|
import { apiHit } from "../../../../globalUtils/apiHits.js";
|
||||||
import { responses } from "../../../../globalUtils/routeDefs/responses.js";
|
import { responses } from "../../../../globalUtils/routeDefs/responses.js";
|
||||||
|
import { authMiddleware } from "../../../auth/middleware/authMiddleware.js";
|
||||||
import { createSiloAdjustment } from "../../controller/siloAdjustments/createSiloAdjustment.js";
|
import { createSiloAdjustment } from "../../controller/siloAdjustments/createSiloAdjustment.js";
|
||||||
import { postSiloComment } from "../../controller/siloAdjustments/postComment.js";
|
import { postSiloComment } from "../../controller/siloAdjustments/postComment.js";
|
||||||
import { apiHit } from "../../../../globalUtils/apiHits.js";
|
|
||||||
|
|
||||||
const app = new OpenAPIHono();
|
const app = new OpenAPIHono();
|
||||||
|
|
||||||
const ParamsSchema = z.object({
|
const ParamsSchema = z.object({
|
||||||
adjId: z
|
adjId: z
|
||||||
.string()
|
.string()
|
||||||
.min(3)
|
.min(3)
|
||||||
.openapi({
|
.openapi({
|
||||||
param: {
|
param: {
|
||||||
name: "adjId",
|
name: "adjId",
|
||||||
in: "path",
|
in: "path",
|
||||||
},
|
},
|
||||||
example: "3b555052-a960-4301-8d38-a6f1acb98dbe",
|
example: "3b555052-a960-4301-8d38-a6f1acb98dbe",
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
const Body = z.object({
|
const Body = z.object({
|
||||||
comment: z
|
comment: z
|
||||||
.string()
|
.string()
|
||||||
.openapi({ example: "Reason to why i had a badd adjustment." }),
|
.openapi({ example: "Reason to why i had a badd adjustment." }),
|
||||||
});
|
});
|
||||||
|
|
||||||
app.openapi(
|
app.openapi(
|
||||||
createRoute({
|
createRoute({
|
||||||
tags: ["logistics"],
|
tags: ["logistics"],
|
||||||
summary: "Post a comment to why you had a discrepancy",
|
summary: "Post a comment to why you had a discrepancy",
|
||||||
method: "post",
|
method: "post",
|
||||||
path: "/postcomment/:adjId",
|
path: "/postcomment/:adjId",
|
||||||
middleware: authMiddleware,
|
middleware: authMiddleware,
|
||||||
request: {
|
request: {
|
||||||
params: ParamsSchema,
|
params: ParamsSchema,
|
||||||
body: { content: { "application/json": { schema: Body } } },
|
body: { content: { "application/json": { schema: Body } } },
|
||||||
},
|
},
|
||||||
// description:
|
// description:
|
||||||
// "Creates a silo adjustment for the silo if and stores the stock numbers.",
|
// "Creates a silo adjustment for the silo if and stores the stock numbers.",
|
||||||
responses: responses(),
|
responses: responses(),
|
||||||
}),
|
}),
|
||||||
async (c: any) => {
|
async (c: any) => {
|
||||||
apiHit(c, { endpoint: "/postcomment" });
|
apiHit(c, { endpoint: "/postcomment" });
|
||||||
const authHeader = c.req.header("Authorization");
|
const { adjId } = c.req.valid("param");
|
||||||
const token = authHeader?.split("Bearer ")[1] || "";
|
|
||||||
const { adjId } = c.req.valid("param");
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const payload = await verify(token, process.env.JWT_SECRET!);
|
try {
|
||||||
try {
|
//return apiReturn(c, true, access?.message, access?.data, 200);
|
||||||
//return apiReturn(c, true, access?.message, access?.data, 200);
|
const data = await c.req.json();
|
||||||
const data = await c.req.json();
|
|
||||||
|
|
||||||
const addComment = await postSiloComment(
|
const addComment = await postSiloComment(
|
||||||
adjId,
|
adjId,
|
||||||
data.comment,
|
data.comment,
|
||||||
data.key,
|
data.key,
|
||||||
payload.user
|
c.get("user"),
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log(addComment);
|
console.log(addComment);
|
||||||
return c.json(
|
return c.json(
|
||||||
{
|
{
|
||||||
success: addComment.success,
|
success: addComment.success,
|
||||||
message: addComment.message,
|
message: addComment.message,
|
||||||
data: addComment.data,
|
data: addComment.data,
|
||||||
},
|
},
|
||||||
200
|
200,
|
||||||
);
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return c.json(
|
return c.json(
|
||||||
{
|
{
|
||||||
success: false,
|
success: false,
|
||||||
message: "Missing data please try again",
|
message: "Missing data please try again",
|
||||||
error,
|
error,
|
||||||
},
|
},
|
||||||
400
|
400,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return c.json({ success: false, message: "Unauthorized" }, 401);
|
return c.json({ success: false, message: "Unauthorized" }, 401);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
export default app;
|
export default app;
|
||||||
|
|||||||
@@ -1,31 +1,33 @@
|
|||||||
// an external way to creating logs
|
// an external way to creating logs
|
||||||
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
|
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
|
||||||
import { responses } from "../../../globalUtils/routeDefs/responses.js";
|
|
||||||
import { getAllJobs } from "../utils/processNotifications.js";
|
|
||||||
import { apiHit } from "../../../globalUtils/apiHits.js";
|
import { apiHit } from "../../../globalUtils/apiHits.js";
|
||||||
|
import { responses } from "../../../globalUtils/routeDefs/responses.js";
|
||||||
|
import { authMiddleware } from "../../auth/middleware/authMiddleware.js";
|
||||||
|
import hasCorrectRole from "../../auth/middleware/roleCheck.js";
|
||||||
|
import { getAllJobs } from "../utils/processNotifications.js";
|
||||||
|
|
||||||
const app = new OpenAPIHono({ strict: false });
|
const app = new OpenAPIHono({ strict: false });
|
||||||
|
|
||||||
app.openapi(
|
app.openapi(
|
||||||
createRoute({
|
createRoute({
|
||||||
tags: ["server"],
|
tags: ["server"],
|
||||||
summary: "Returns current active notifications.",
|
summary: "Returns current active notifications.",
|
||||||
method: "get",
|
method: "get",
|
||||||
path: "/activenotifications",
|
path: "/activenotifications",
|
||||||
//middleware: authMiddleware,
|
middleware: [authMiddleware, hasCorrectRole(["systemAdmin"], "admin")],
|
||||||
responses: responses(),
|
responses: responses(),
|
||||||
}),
|
}),
|
||||||
async (c) => {
|
async (c) => {
|
||||||
apiHit(c, { endpoint: "/activenotifications" });
|
apiHit(c, { endpoint: "/activenotifications" });
|
||||||
const jobs = getAllJobs();
|
const jobs = getAllJobs();
|
||||||
return c.json({
|
return c.json({
|
||||||
success: true,
|
success: true,
|
||||||
message:
|
message:
|
||||||
jobs.length === 0
|
jobs.length === 0
|
||||||
? "There are no active Notifications Currently."
|
? "There are no active Notifications Currently."
|
||||||
: "Current Active notifications",
|
: "Current Active notifications",
|
||||||
data: jobs,
|
data: jobs,
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
export default app;
|
export default app;
|
||||||
|
|||||||
@@ -6,253 +6,254 @@
|
|||||||
import { db } from "../../../../database/dbclient.js";
|
import { db } from "../../../../database/dbclient.js";
|
||||||
import { subModules } from "../../../../database/schema/subModules.js";
|
import { subModules } from "../../../../database/schema/subModules.js";
|
||||||
import { createLog } from "../../logger/logger.js";
|
import { createLog } from "../../logger/logger.js";
|
||||||
|
|
||||||
// "view", "technician", "supervisor","manager", "admin", "systemAdmin"
|
// "view", "technician", "supervisor","manager", "admin", "systemAdmin"
|
||||||
const newSubModules = [
|
const newSubModules = [
|
||||||
{
|
{
|
||||||
name: "RFID",
|
name: "RFID",
|
||||||
moduleName: "prodcution",
|
moduleName: "prodcution",
|
||||||
description: "RFID stuff",
|
description: "RFID stuff",
|
||||||
link: "/rfid",
|
link: "/rfid",
|
||||||
icon: "Tags",
|
icon: "Tags",
|
||||||
active: true,
|
active: true,
|
||||||
roles: [
|
roles: [
|
||||||
"viewer",
|
"viewer",
|
||||||
"technician",
|
"technician",
|
||||||
"supervisor",
|
"supervisor",
|
||||||
"manager",
|
"manager",
|
||||||
"admin",
|
"admin",
|
||||||
"systemAdmin",
|
"systemAdmin",
|
||||||
],
|
],
|
||||||
subSubModule: [],
|
subSubModule: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Silo Adjustments",
|
name: "siloAdjustments",
|
||||||
moduleName: "logistics",
|
moduleName: "logistics",
|
||||||
description: "Do a silo adjustmnet",
|
description: "Do a silo adjustments",
|
||||||
link: "/siloAdjustments",
|
link: "/siloAdjustments",
|
||||||
icon: "Cylinder",
|
icon: "Cylinder",
|
||||||
active: false,
|
active: false,
|
||||||
roles: ["technician", "supervisor", "manager", "admin", "systemAdmin"],
|
roles: ["technician", "supervisor", "manager", "admin", "systemAdmin"],
|
||||||
subSubModule: [],
|
subSubModule: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Demand Management",
|
name: "demandManagement",
|
||||||
moduleName: "logistics",
|
moduleName: "logistics",
|
||||||
description: "Bulk order and Forecast imports",
|
description: "Bulk order and Forecast imports",
|
||||||
link: "/dm",
|
link: "/dm",
|
||||||
icon: "Truck",
|
icon: "Truck",
|
||||||
roles: ["technician", "supervisor", "manager", "admin", "systemAdmin"],
|
roles: ["technician", "supervisor", "manager", "admin", "systemAdmin"],
|
||||||
active: false,
|
active: false,
|
||||||
subSubModule: [],
|
subSubModule: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Forecast",
|
name: "Forecast",
|
||||||
moduleName: "logistics",
|
moduleName: "logistics",
|
||||||
description: "",
|
description: "",
|
||||||
link: "#",
|
link: "#",
|
||||||
icon: "Truck",
|
icon: "Truck",
|
||||||
roles: ["systemAdmin"],
|
roles: ["systemAdmin"],
|
||||||
active: false,
|
active: false,
|
||||||
subSubModule: [],
|
subSubModule: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Material Helper",
|
name: "Material Helper",
|
||||||
moduleName: "logistics",
|
moduleName: "logistics",
|
||||||
description: "",
|
description: "",
|
||||||
link: "/materialHelper/consumption",
|
link: "/materialHelper/consumption",
|
||||||
icon: "Package",
|
icon: "Package",
|
||||||
roles: [
|
roles: [
|
||||||
"viewer",
|
"viewer",
|
||||||
"technician",
|
"technician",
|
||||||
"supervisor",
|
"supervisor",
|
||||||
"manager",
|
"manager",
|
||||||
"admin",
|
"admin",
|
||||||
"systemAdmin",
|
"systemAdmin",
|
||||||
],
|
],
|
||||||
active: false,
|
active: false,
|
||||||
subSubModule: [],
|
subSubModule: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Ocme Cyclecount",
|
name: "Ocme Cyclecount",
|
||||||
moduleName: "logistics",
|
moduleName: "logistics",
|
||||||
description: "",
|
description: "",
|
||||||
link: "/cyclecount",
|
link: "/cyclecount",
|
||||||
icon: "Package",
|
icon: "Package",
|
||||||
roles: ["technician", "supervisor", "manager", "admin", "systemAdmin"],
|
roles: ["technician", "supervisor", "manager", "admin", "systemAdmin"],
|
||||||
active: false,
|
active: false,
|
||||||
subSubModule: [],
|
subSubModule: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Open Orders",
|
name: "Open Orders",
|
||||||
moduleName: "logistics",
|
moduleName: "logistics",
|
||||||
description: "Open orders",
|
description: "Open orders",
|
||||||
link: "/openOrders",
|
link: "/openOrders",
|
||||||
icon: "Truck",
|
icon: "Truck",
|
||||||
roles: [
|
roles: [
|
||||||
"viewer",
|
"viewer",
|
||||||
"technician",
|
"technician",
|
||||||
"supervisor",
|
"supervisor",
|
||||||
"manager",
|
"manager",
|
||||||
"admin",
|
"admin",
|
||||||
"systemAdmin",
|
"systemAdmin",
|
||||||
],
|
],
|
||||||
active: false,
|
active: false,
|
||||||
subSubModule: [],
|
subSubModule: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Barcodes",
|
name: "Barcodes",
|
||||||
moduleName: "logistics",
|
moduleName: "logistics",
|
||||||
description: "Barcodes, lanes and scanable",
|
description: "Barcodes, lanes and scanable",
|
||||||
link: "/barcodegen",
|
link: "/barcodegen",
|
||||||
icon: "Barcode",
|
icon: "Barcode",
|
||||||
roles: [
|
roles: [
|
||||||
"viewer",
|
"viewer",
|
||||||
"technician",
|
"technician",
|
||||||
"supervisor",
|
"supervisor",
|
||||||
"manager",
|
"manager",
|
||||||
"admin",
|
"admin",
|
||||||
"systemAdmin",
|
"systemAdmin",
|
||||||
],
|
],
|
||||||
active: true,
|
active: true,
|
||||||
subSubModule: [],
|
subSubModule: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Helper Commands",
|
name: "Helper Commands",
|
||||||
moduleName: "logistics",
|
moduleName: "logistics",
|
||||||
description: "Commands to assist when a scanner is not avalible",
|
description: "Commands to assist when a scanner is not avalible",
|
||||||
link: "/helpercommands",
|
link: "/helpercommands",
|
||||||
icon: "Command",
|
icon: "Command",
|
||||||
roles: ["technician", "supervisor", "manager", "admin", "systemAdmin"],
|
roles: ["technician", "supervisor", "manager", "admin", "systemAdmin"],
|
||||||
active: true,
|
active: true,
|
||||||
subSubModule: [],
|
subSubModule: [],
|
||||||
},
|
},
|
||||||
|
|
||||||
// admin module
|
// admin module
|
||||||
{
|
{
|
||||||
name: "Servers",
|
name: "Servers",
|
||||||
moduleName: "admin",
|
moduleName: "admin",
|
||||||
description: "Do a silo adjustmnet",
|
description: "Do a silo adjustmnet",
|
||||||
link: "/servers",
|
link: "/servers",
|
||||||
icon: "Server",
|
icon: "Server",
|
||||||
roles: ["tester", "systemAdmin"],
|
roles: ["tester", "systemAdmin"],
|
||||||
isActive: true,
|
isActive: true,
|
||||||
subSubModule: [],
|
subSubModule: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Admin",
|
name: "Admin",
|
||||||
moduleName: "admin",
|
moduleName: "admin",
|
||||||
description: "Do a silo adjustmnet",
|
description: "Do a silo adjustmnet",
|
||||||
link: "#", // when link is # this will mean its a button
|
link: "#", // when link is # this will mean its a button
|
||||||
icon: "ShieldCheck",
|
icon: "ShieldCheck",
|
||||||
active: true,
|
active: true,
|
||||||
roles: ["tester", "admin", "systemAdmin"],
|
roles: ["tester", "admin", "systemAdmin"],
|
||||||
subSubModule: [
|
subSubModule: [
|
||||||
{
|
{
|
||||||
name: "Settings",
|
name: "Settings",
|
||||||
link: "/settings",
|
link: "/settings",
|
||||||
icon: "Settings",
|
icon: "Settings",
|
||||||
newWindow: false,
|
newWindow: false,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Modules",
|
name: "Modules",
|
||||||
link: "/modules",
|
link: "/modules",
|
||||||
icon: "Settings",
|
icon: "Settings",
|
||||||
newWindow: false,
|
newWindow: false,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Sub Modules",
|
name: "Sub Modules",
|
||||||
link: "/subModules",
|
link: "/subModules",
|
||||||
icon: "Settings",
|
icon: "Settings",
|
||||||
newWindow: false,
|
newWindow: false,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Notifcations",
|
name: "Notifcations",
|
||||||
link: "notificationMGT",
|
link: "notificationMGT",
|
||||||
icon: "Webhook",
|
icon: "Webhook",
|
||||||
newWindow: false,
|
newWindow: false,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Swagger",
|
name: "Swagger",
|
||||||
link: "#",
|
link: "#",
|
||||||
icon: "Webhook",
|
icon: "Webhook",
|
||||||
newWindow: true,
|
newWindow: true,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Logs",
|
name: "Logs",
|
||||||
link: "#",
|
link: "#",
|
||||||
icon: "Logs",
|
icon: "Logs",
|
||||||
newWindow: false,
|
newWindow: false,
|
||||||
isActive: false,
|
isActive: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Users",
|
name: "Users",
|
||||||
link: "/users",
|
link: "/users",
|
||||||
icon: "Users",
|
icon: "Users",
|
||||||
newWindow: false,
|
newWindow: false,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Prod Perms",
|
name: "Prod Perms",
|
||||||
link: "/produsers",
|
link: "/produsers",
|
||||||
icon: "Users",
|
icon: "Users",
|
||||||
newWindow: false,
|
newWindow: false,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "UCD",
|
name: "UCD",
|
||||||
link: "https://ucd.alpla.net:8443/",
|
link: "https://ucd.alpla.net:8443/",
|
||||||
icon: "Atom",
|
icon: "Atom",
|
||||||
newWindow: false,
|
newWindow: false,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Lst Api",
|
name: "Lst Api",
|
||||||
link: "/api/docs",
|
link: "/api/docs",
|
||||||
icon: "Webhook",
|
icon: "Webhook",
|
||||||
newWindow: false,
|
newWindow: false,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
export const areSubModulesIn = async () => {
|
export const areSubModulesIn = async () => {
|
||||||
try {
|
try {
|
||||||
for (let i = 0; i < newSubModules.length; i++) {
|
for (let i = 0; i < newSubModules.length; i++) {
|
||||||
const subModuleUpdate = await db
|
const subModuleUpdate = await db
|
||||||
.insert(subModules)
|
.insert(subModules)
|
||||||
.values(newSubModules[i])
|
.values(newSubModules[i])
|
||||||
.onConflictDoUpdate({
|
.onConflictDoUpdate({
|
||||||
target: subModules.name,
|
target: subModules.name,
|
||||||
set: {
|
set: {
|
||||||
name: newSubModules[i].name,
|
name: newSubModules[i].name,
|
||||||
moduleName: newSubModules[i].moduleName,
|
moduleName: newSubModules[i].moduleName,
|
||||||
description: newSubModules[i].description,
|
description: newSubModules[i].description,
|
||||||
roles: newSubModules[i].roles,
|
roles: newSubModules[i].roles,
|
||||||
link: newSubModules[i].link,
|
link: newSubModules[i].link,
|
||||||
subSubModule: newSubModules[i].subSubModule,
|
subSubModule: newSubModules[i].subSubModule,
|
||||||
icon: newSubModules[i].icon,
|
icon: newSubModules[i].icon,
|
||||||
},
|
},
|
||||||
}) // this will only update the ones that are new :D
|
}) // this will only update the ones that are new :D
|
||||||
.returning({ name: subModules.name });
|
.returning({ name: subModules.name });
|
||||||
}
|
}
|
||||||
createLog(
|
createLog(
|
||||||
"info",
|
"info",
|
||||||
"lst",
|
"lst",
|
||||||
"server",
|
"server",
|
||||||
"SubModules were just added due to missing them on server startup"
|
"SubModules were just added due to missing them on server startup",
|
||||||
);
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
createLog(
|
createLog(
|
||||||
"error",
|
"error",
|
||||||
"lst",
|
"lst",
|
||||||
"server",
|
"server",
|
||||||
"There was an error adding new subModules to the db"
|
"There was an error adding new subModules to the db",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user