From ad5e77028d59c31405df6cc17fc0c8084dddad5a Mon Sep 17 00:00:00 2001 From: Blake Matthes Date: Fri, 4 Apr 2025 17:09:30 -0500 Subject: [PATCH] test(frontend): work on the frontend to have better admin --- .../admin/dataMartStats/DataMartStats.tsx | 8 + .../admin/notificationMGT/NotificationMGT.tsx | 8 + .../components/admin/servers/ServerPage.tsx | 41 ++ .../admin/user/components/UserCard.tsx | 395 ++++++++++-------- .../admin/user/components/UserRoles.tsx | 16 + .../layout/side-components/logistics.tsx | 71 ++-- .../src/components/production/ocp/Lots.tsx | 12 +- .../src/components/providers/Providers.tsx | 30 +- frontend/src/components/ui/checkbox.tsx | 2 +- frontend/src/lib/store/useGetRoles.ts | 15 +- frontend/src/types/lots.ts | 2 +- 11 files changed, 375 insertions(+), 225 deletions(-) create mode 100644 frontend/src/components/admin/dataMartStats/DataMartStats.tsx create mode 100644 frontend/src/components/admin/notificationMGT/NotificationMGT.tsx create mode 100644 frontend/src/components/admin/user/components/UserRoles.tsx diff --git a/frontend/src/components/admin/dataMartStats/DataMartStats.tsx b/frontend/src/components/admin/dataMartStats/DataMartStats.tsx new file mode 100644 index 0000000..958298e --- /dev/null +++ b/frontend/src/components/admin/dataMartStats/DataMartStats.tsx @@ -0,0 +1,8 @@ +export default function DataMartStats() { + return ( +
+ The stats for all the data mart querys out there and whos and when + they are last used to understand if we want to keep them or not +
+ ); +} diff --git a/frontend/src/components/admin/notificationMGT/NotificationMGT.tsx b/frontend/src/components/admin/notificationMGT/NotificationMGT.tsx new file mode 100644 index 0000000..77af83f --- /dev/null +++ b/frontend/src/components/admin/notificationMGT/NotificationMGT.tsx @@ -0,0 +1,8 @@ +export default function NotificationMGT() { + return ( +
+ Manage all notifications from here instad of going to the db, + locking some items that are auto updated on server restarts +
+ ); +} diff --git a/frontend/src/components/admin/servers/ServerPage.tsx b/frontend/src/components/admin/servers/ServerPage.tsx index 9df2e89..38b8ffb 100644 --- a/frontend/src/components/admin/servers/ServerPage.tsx +++ b/frontend/src/components/admin/servers/ServerPage.tsx @@ -19,6 +19,11 @@ import { adminUrlCheck } from "@/utils/adminUrlCheck"; import RestartServer from "./RestartServer"; import StopServer from "./StopServer"; import StartServer from "./StartServer"; +import { Button } from "@/components/ui/button"; +import { getSettings } from "@/utils/querys/settings"; +import { toast } from "sonner"; +import axios from "axios"; +//import { useState } from "react"; export type Servers = { server_id?: string; @@ -33,6 +38,7 @@ export type Servers = { export default function ServerPage() { const { user, token } = useSessionStore(); const { modules } = useModuleStore(); + //const [upgrading, setUpgrading] = useState(false); const router = useRouter(); const { data, isError, error, isLoading } = useQuery( @@ -51,10 +57,45 @@ export default function ServerPage() { if (isError) { return
{JSON.stringify(error)}
; } + const { data: set } = useQuery(getSettings(token ?? "")); + const upgrade = async () => { + let devDir = set.filter((n: any) => n.name === "devDir"); + toast.success("All Servers was just triggered."); + + try { + const result = await axios.post( + `/api/server/update/localhost`, + { devDir: devDir[0].value, all: true }, + { + headers: { Authorization: `Bearer ${token}` }, + } + ); + + if (result.data.success) { + toast.success(result.data.message); + } + + if (!result.data.success) { + toast.success(result.data.message); + } + } catch (error: any) { + toast.error( + `There was an error updating the server: ${error.data.message}` + ); + } + }; //console.log(data); return ( +
+ +
diff --git a/frontend/src/components/admin/user/components/UserCard.tsx b/frontend/src/components/admin/user/components/UserCard.tsx index 449eec0..a90333b 100644 --- a/frontend/src/components/admin/user/components/UserCard.tsx +++ b/frontend/src/components/admin/user/components/UserCard.tsx @@ -1,3 +1,4 @@ +import { LstCard } from "@/components/extendedUI/LstCard"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; @@ -10,6 +11,7 @@ import { SelectTrigger, SelectValue, } from "@/components/ui/select"; + import { DebugButton } from "@/utils/formStuff/debugButton"; import { userFormOptions } from "@/utils/formStuff/options/userformOptions"; import { generatePassword } from "@/utils/passwordGen"; @@ -18,10 +20,16 @@ import { useForm } from "@tanstack/react-form"; import { useQuery } from "@tanstack/react-query"; import axios from "axios"; import { toast } from "sonner"; +import UserRoles from "./UserRoles"; +import { CardHeader } from "@/components/ui/card"; export default function UserCard(data: any) { const token = localStorage.getItem("auth_token"); const { refetch } = useQuery(getUsers()); + + //console.log(modules); + //console.log(data.user); + //console.log(userRoles); const form = useForm({ ...userFormOptions(data.user), onSubmit: async ({ value }) => { @@ -53,185 +61,224 @@ export default function UserCard(data: any) { }, }); return ( -
-
{ - e.preventDefault(); - e.stopPropagation(); - }} - > - - value.length > 3 - ? undefined - : "Username must be longer than 3 letters", - }} - children={(field) => { - return ( -
- - - field.handleChange(e.target.value) - } - /> - {field.state.meta.errors.length ? ( - {field.state.meta.errors.join(",")} - ) : null} -
- ); - }} - /> - - value.length > 3 - ? undefined - : "You must enter a correct ", - }} - children={(field) => { - return ( -
- - - field.handleChange(e.target.value) - } - /> - {field.state.meta.errors.length ? ( - {field.state.meta.errors.join(",")} - ) : null} -
- ); - }} - /> - {}}} - children={(field) => { - return ( -
- - + field.handleChange( + e.target.value + ) + } /> - - - - Roles - - Viewer - - - Operator - - - Manager - - - Admin - - - - -
- ); - }} - /> - { - if ( - window.location.pathname.includes("/users") && - value.length === 0 - ) { - return; - } - if (value.length < 4) { - return "Password must be at least 4 characters long."; - } + {field.state.meta.errors.length ? ( + + {field.state.meta.errors.join( + "," + )} + + ) : null} +
+ ); + }} + /> + + value.length > 3 + ? undefined + : "You must enter a correct ", + }} + children={(field) => { + return ( +
+ + + field.handleChange( + e.target.value + ) + } + /> + {field.state.meta.errors.length ? ( + + {field.state.meta.errors.join( + "," + )} + + ) : null} +
+ ); + }} + /> + {}}} + children={(field) => { + return ( +
+ + +
+ ); + }} + /> + { + if ( + window.location.pathname.includes( + "/users" + ) && + value.length === 0 + ) { + return; + } + if (value.length < 4) { + return "Password must be at least 4 characters long."; + } - if (!/[A-Z]/.test(value)) { - return "Password must contain at least one uppercase letter."; - } + if (!/[A-Z]/.test(value)) { + return "Password must contain at least one uppercase letter."; + } - if (!/[a-z]/.test(value)) { - return "Password must contain at least one lower case letter."; - } + if (!/[a-z]/.test(value)) { + return "Password must contain at least one lower case letter."; + } - if (!/[0-9]/.test(value)) { - return "Password must contain at least one number."; - } + if (!/[0-9]/.test(value)) { + return "Password must contain at least one number."; + } - if ( - !/[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/.test( - value - ) - ) { - return "Password must contain at least one special character."; - } - }, - }} - children={(field) => { - return ( -
- -
- - field.handleChange(e.target.value) - } - /> - - -
- {field.state.meta.errors.length ? ( - {field.state.meta.errors.join(",")} - ) : null} -
- ); - }} - /> - -
- + if ( + !/[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/.test( + value + ) + ) { + return "Password must contain at least one special character."; + } + }, + }} + children={(field) => { + return ( +
+ +
+ + field.handleChange( + e.target.value + ) + } + /> + + +
+ {field.state.meta.errors.length ? ( + + {field.state.meta.errors.join( + "," + )} + + ) : null} +
+ ); + }} + /> + + +
+ +
+
+
+ + User Module / Role Access + +
); diff --git a/frontend/src/components/admin/user/components/UserRoles.tsx b/frontend/src/components/admin/user/components/UserRoles.tsx new file mode 100644 index 0000000..70657d0 --- /dev/null +++ b/frontend/src/components/admin/user/components/UserRoles.tsx @@ -0,0 +1,16 @@ +import { Label } from "@/components/ui/label"; +import { useModuleStore } from "@/lib/store/useModuleStore"; +//import { Checkbox } from "@radix-ui/react-checkbox"; + +export default function UserRoles(user: any) { + const { modules } = useModuleStore(); + console.log(user); + return ( +
+ {modules?.map((m: any) => { + console.log(m); + return ; + })} +
+ ); +} diff --git a/frontend/src/components/layout/side-components/logistics.tsx b/frontend/src/components/layout/side-components/logistics.tsx index 7362477..0317662 100644 --- a/frontend/src/components/layout/side-components/logistics.tsx +++ b/frontend/src/components/layout/side-components/logistics.tsx @@ -1,4 +1,4 @@ -import {Cylinder, Package, Truck} from "lucide-react"; +import { Cylinder, Package, Truck } from "lucide-react"; import { SidebarGroup, SidebarGroupContent, @@ -7,8 +7,8 @@ import { SidebarMenuButton, SidebarMenuItem, } from "../../ui/sidebar"; -import {hasPageAccess} from "@/utils/userAccess"; -import {User} from "@/types/users"; +import { hasPageAccess } from "@/utils/userAccess"; +import { User } from "@/types/users"; // this will need to be moved to a links section the db to make it more easy to remove and add const items = [ { @@ -20,48 +20,64 @@ const items = [ active: true, }, { - title: "Bulk orders", - url: "#", + name: "Bulk orders", + moduleName: "logistics", + description: "", + link: "#", icon: Truck, role: ["systemAdmin"], - module: "logistics", active: true, + subSubModule: [], }, { - title: "Forecast", - url: "#", + name: "Forecast", + moduleName: "logistics", + description: "", + link: "#", icon: Truck, role: ["systemAdmin"], - module: "logistics", active: true, + subSubModule: [], }, { - title: "Ocme cycle counts", - url: "#", + name: "Ocme cycle counts", + moduleName: "logistics", + description: "", + link: "#", icon: Package, role: ["technician", "supervisor", "manager", "admin", "systemAdmin"], - module: "logistics", active: false, + subSubModule: [], }, { - title: "Material Helper", - url: "/materialHelper/consumption", + name: "Material Helper", + moduleName: "logistics", + description: "", + link: "/materialHelper/consumption", icon: Package, role: ["technician", "supervisor", "manager", "admin", "systemAdmin"], - module: "logistics", active: true, + subSubModule: [], }, { - title: "Ocme Cyclecount", - url: "/cyclecount", + name: "Ocme Cyclecount", + moduleName: "logistics", + description: "", + link: "/cyclecount", icon: Package, role: ["technician", "supervisor", "manager", "admin", "systemAdmin"], - module: "logistics", active: true, + subSubModule: [], }, ]; -export function LogisticsSideBar({user, moduleID}: {user: User | null; moduleID: string}) { +export function LogisticsSideBar({ + user, + moduleID, +}: { + user: User | null; + moduleID: string; +}) { return ( Logistics @@ -70,14 +86,15 @@ export function LogisticsSideBar({user, moduleID}: {user: User | null; moduleID: {items.map((item) => ( <> - {hasPageAccess(user, item.role, moduleID) && item.active && ( - - - - {item.title} - - - )} + {hasPageAccess(user, item.role, moduleID) && + item.active && ( + + + + {item.title} + + + )} ))} diff --git a/frontend/src/components/production/ocp/Lots.tsx b/frontend/src/components/production/ocp/Lots.tsx index fcff5fd..72b9b6d 100644 --- a/frontend/src/components/production/ocp/Lots.tsx +++ b/frontend/src/components/production/ocp/Lots.tsx @@ -32,7 +32,7 @@ let lotColumns = [ label: "AvDescription", }, { - key: "LOT", + key: "lot", label: "LotNumber", }, { @@ -208,10 +208,14 @@ export default function Lots() { {lot.Alias} - - {lot.LOT} + + {lot.lot} - + {lot.ProlinkLot} diff --git a/frontend/src/components/providers/Providers.tsx b/frontend/src/components/providers/Providers.tsx index 0bd34a5..675f076 100644 --- a/frontend/src/components/providers/Providers.tsx +++ b/frontend/src/components/providers/Providers.tsx @@ -1,20 +1,28 @@ -import {QueryClient, QueryClientProvider} from "@tanstack/react-query"; -import {useModuleStore} from "../../lib/store/useModuleStore"; -import {useEffect} from "react"; -import {useSettingStore} from "@/lib/store/useSettings"; -//import {useGetUserRoles} from "@/lib/store/useGetRoles"; +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; +import { useModuleStore } from "../../lib/store/useModuleStore"; +import { useEffect } from "react"; +import { useSettingStore } from "@/lib/store/useSettings"; +import { useGetUserRoles } from "@/lib/store/useGetRoles"; const queryClient = new QueryClient(); -export const SessionProvider = ({children}: {children: React.ReactNode}) => { - const {fetchModules} = useModuleStore(); - const {fetchSettings} = useSettingStore(); - //const {fetchUserRoles} = useGetUserRoles(); +export const SessionProvider = ({ + children, +}: { + children: React.ReactNode; +}) => { + const { fetchModules } = useModuleStore(); + const { fetchSettings } = useSettingStore(); + const { fetchUserRoles } = useGetUserRoles(); useEffect(() => { fetchModules(); fetchSettings(); - //fetchUserRoles(); + fetchUserRoles(); }, []); - return {children}; + return ( + + {children} + + ); }; diff --git a/frontend/src/components/ui/checkbox.tsx b/frontend/src/components/ui/checkbox.tsx index eac008b..defeb01 100644 --- a/frontend/src/components/ui/checkbox.tsx +++ b/frontend/src/components/ui/checkbox.tsx @@ -12,7 +12,7 @@ function Checkbox({ ()((set) => ({ userRoles: [], - setUserRoles: (userRoles) => set({userRoles}), + setUserRoles: (userRoles) => set({ userRoles }), fetchUserRoles: async () => { try { //const response = await axios.get<{data: Setting[]}>(`${process.env.NEXT_PUBLIC_URL}/api/settings/client`); - const {token} = useSessionStore(); - const response = await axios.get("/api/auth/getuseraccess", {headers: {Authorization: `Bearer ${token}`}}); + const token = localStorage.getItem("auth_token"); + const response = await axios.get("/api/auth/getuseraccess", { + headers: { Authorization: `Bearer ${token}` }, + }); const data: FetchModulesResponse = response.data; //await response.json(); //console.log(data); - set({userRoles: data.data}); + set({ userRoles: data.data }); } catch (error) { console.error("Failed to fetch settings:", error); } diff --git a/frontend/src/types/lots.ts b/frontend/src/types/lots.ts index 15d6f21..bdebf3b 100644 --- a/frontend/src/types/lots.ts +++ b/frontend/src/types/lots.ts @@ -1,7 +1,7 @@ export type LotType = { AV: number; Alias: string; - LOT: number; + lot: number; LabelOnlineID: number; MachineDescription: string; MachineID: number;