test(frontend): work on the frontend to have better admin
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
export default function DataMartStats() {
|
||||
return (
|
||||
<div>
|
||||
The stats for all the data mart querys out there and whos and when
|
||||
they are last used to understand if we want to keep them or not
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
export default function NotificationMGT() {
|
||||
return (
|
||||
<div>
|
||||
Manage all notifications from here instad of going to the db,
|
||||
locking some items that are auto updated on server restarts
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -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 <div>{JSON.stringify(error)}</div>;
|
||||
}
|
||||
const { data: set } = useQuery(getSettings(token ?? ""));
|
||||
const upgrade = async () => {
|
||||
let devDir = set.filter((n: any) => n.name === "devDir");
|
||||
toast.success("All Servers was just triggered.");
|
||||
|
||||
try {
|
||||
const result = await axios.post(
|
||||
`/api/server/update/localhost`,
|
||||
{ devDir: devDir[0].value, all: true },
|
||||
{
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
}
|
||||
);
|
||||
|
||||
if (result.data.success) {
|
||||
toast.success(result.data.message);
|
||||
}
|
||||
|
||||
if (!result.data.success) {
|
||||
toast.success(result.data.message);
|
||||
}
|
||||
} catch (error: any) {
|
||||
toast.error(
|
||||
`There was an error updating the server: ${error.data.message}`
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
//console.log(data);
|
||||
return (
|
||||
<LstCard className="m-2 flex place-content-center w-dvh">
|
||||
<div className="flex justify-end m-2">
|
||||
<Button
|
||||
onClick={upgrade}
|
||||
disabled={data?.some((d: any) => d.isUpgrading)}
|
||||
>
|
||||
Update All Servers
|
||||
</Button>
|
||||
</div>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
|
||||
@@ -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 (
|
||||
<div>
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}}
|
||||
>
|
||||
<form.Field
|
||||
name="username"
|
||||
validators={{
|
||||
// We can choose between form-wide and field-specific validators
|
||||
onChange: ({ value }) =>
|
||||
value.length > 3
|
||||
? undefined
|
||||
: "Username must be longer than 3 letters",
|
||||
}}
|
||||
children={(field) => {
|
||||
return (
|
||||
<div className="m-2 min-w-48 max-w-96 p-2">
|
||||
<Label htmlFor="username">Username</Label>
|
||||
<Input
|
||||
name={field.name}
|
||||
value={field.state.value}
|
||||
onBlur={field.handleBlur}
|
||||
//type="number"
|
||||
onChange={(e) =>
|
||||
field.handleChange(e.target.value)
|
||||
}
|
||||
/>
|
||||
{field.state.meta.errors.length ? (
|
||||
<em>{field.state.meta.errors.join(",")}</em>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<form.Field
|
||||
name="email"
|
||||
validators={{
|
||||
// We can choose between form-wide and field-specific validators
|
||||
onChange: ({ value }) =>
|
||||
value.length > 3
|
||||
? undefined
|
||||
: "You must enter a correct ",
|
||||
}}
|
||||
children={(field) => {
|
||||
return (
|
||||
<div className="m-2 min-w-48 max-w-96 p-2">
|
||||
<Label htmlFor="email">Email</Label>
|
||||
<Input
|
||||
name={field.name}
|
||||
value={field.state.value}
|
||||
onBlur={field.handleBlur}
|
||||
//type="number"
|
||||
onChange={(e) =>
|
||||
field.handleChange(e.target.value)
|
||||
}
|
||||
/>
|
||||
{field.state.meta.errors.length ? (
|
||||
<em>{field.state.meta.errors.join(",")}</em>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<form.Field
|
||||
name="role"
|
||||
//listeners={{onChange: ({value})=>{}}}
|
||||
children={(field) => {
|
||||
return (
|
||||
<div className="m-2 min-w-48 max-w-96 p-2">
|
||||
<Label htmlFor={field.name}>Select role</Label>
|
||||
<Select
|
||||
value={field.state.value}
|
||||
onValueChange={field.handleChange}
|
||||
>
|
||||
<SelectTrigger className="w-[180px]">
|
||||
<SelectValue
|
||||
id={field.name}
|
||||
placeholder="Select Role"
|
||||
<div className="flex flex-row">
|
||||
<div className="m-2">
|
||||
<LstCard>
|
||||
<CardHeader>User Profile</CardHeader>
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}}
|
||||
>
|
||||
<form.Field
|
||||
name="username"
|
||||
validators={{
|
||||
// We can choose between form-wide and field-specific validators
|
||||
onChange: ({ value }) =>
|
||||
value.length > 3
|
||||
? undefined
|
||||
: "Username must be longer than 3 letters",
|
||||
}}
|
||||
children={(field) => {
|
||||
return (
|
||||
<div className="m-2 min-w-48 max-w-96 p-2">
|
||||
<Label htmlFor="username">
|
||||
Username
|
||||
</Label>
|
||||
<Input
|
||||
name={field.name}
|
||||
value={field.state.value}
|
||||
onBlur={field.handleBlur}
|
||||
//type="number"
|
||||
onChange={(e) =>
|
||||
field.handleChange(
|
||||
e.target.value
|
||||
)
|
||||
}
|
||||
/>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
<SelectLabel>Roles</SelectLabel>
|
||||
<SelectItem value="viewer">
|
||||
Viewer
|
||||
</SelectItem>
|
||||
<SelectItem value="operator">
|
||||
Operator
|
||||
</SelectItem>
|
||||
<SelectItem value="manager">
|
||||
Manager
|
||||
</SelectItem>
|
||||
<SelectItem value="admin">
|
||||
Admin
|
||||
</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<form.Field
|
||||
name="password"
|
||||
validators={{
|
||||
onChangeAsyncDebounceMs: 500,
|
||||
onChangeAsync: ({ value }) => {
|
||||
if (
|
||||
window.location.pathname.includes("/users") &&
|
||||
value.length === 0
|
||||
) {
|
||||
return;
|
||||
}
|
||||
if (value.length < 4) {
|
||||
return "Password must be at least 4 characters long.";
|
||||
}
|
||||
{field.state.meta.errors.length ? (
|
||||
<em>
|
||||
{field.state.meta.errors.join(
|
||||
","
|
||||
)}
|
||||
</em>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<form.Field
|
||||
name="email"
|
||||
validators={{
|
||||
// We can choose between form-wide and field-specific validators
|
||||
onChange: ({ value }) =>
|
||||
value.length > 3
|
||||
? undefined
|
||||
: "You must enter a correct ",
|
||||
}}
|
||||
children={(field) => {
|
||||
return (
|
||||
<div className="m-2 min-w-48 max-w-96 p-2">
|
||||
<Label htmlFor="email">Email</Label>
|
||||
<Input
|
||||
name={field.name}
|
||||
value={field.state.value}
|
||||
onBlur={field.handleBlur}
|
||||
//type="number"
|
||||
onChange={(e) =>
|
||||
field.handleChange(
|
||||
e.target.value
|
||||
)
|
||||
}
|
||||
/>
|
||||
{field.state.meta.errors.length ? (
|
||||
<em>
|
||||
{field.state.meta.errors.join(
|
||||
","
|
||||
)}
|
||||
</em>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<form.Field
|
||||
name="role"
|
||||
//listeners={{onChange: ({value})=>{}}}
|
||||
children={(field) => {
|
||||
return (
|
||||
<div className="m-2 min-w-48 max-w-96 p-2">
|
||||
<Label htmlFor={field.name}>
|
||||
Select role
|
||||
</Label>
|
||||
<Select
|
||||
value={field.state.value}
|
||||
onValueChange={field.handleChange}
|
||||
>
|
||||
<SelectTrigger className="w-[180px]">
|
||||
<SelectValue
|
||||
id={field.name}
|
||||
placeholder="Select Role"
|
||||
/>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
<SelectLabel>
|
||||
Roles
|
||||
</SelectLabel>
|
||||
<SelectItem value="viewer">
|
||||
Viewer
|
||||
</SelectItem>
|
||||
<SelectItem value="operator">
|
||||
Operator
|
||||
</SelectItem>
|
||||
<SelectItem value="manager">
|
||||
Manager
|
||||
</SelectItem>
|
||||
<SelectItem value="admin">
|
||||
Admin
|
||||
</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<form.Field
|
||||
name="password"
|
||||
validators={{
|
||||
onChangeAsyncDebounceMs: 500,
|
||||
onChangeAsync: ({ value }) => {
|
||||
if (
|
||||
window.location.pathname.includes(
|
||||
"/users"
|
||||
) &&
|
||||
value.length === 0
|
||||
) {
|
||||
return;
|
||||
}
|
||||
if (value.length < 4) {
|
||||
return "Password must be at least 4 characters long.";
|
||||
}
|
||||
|
||||
if (!/[A-Z]/.test(value)) {
|
||||
return "Password must contain at least one uppercase letter.";
|
||||
}
|
||||
if (!/[A-Z]/.test(value)) {
|
||||
return "Password must contain at least one 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 (
|
||||
<div className="m-2 p-2">
|
||||
<Label htmlFor="password">
|
||||
Change Password
|
||||
</Label>
|
||||
<div className="mt-2 flex flex-row">
|
||||
<Input
|
||||
className="min-w-48 max-w-96"
|
||||
name={field.name}
|
||||
value={field.state.value}
|
||||
onBlur={field.handleBlur}
|
||||
//type="number"
|
||||
onChange={(e) =>
|
||||
field.handleChange(e.target.value)
|
||||
}
|
||||
/>
|
||||
<Button
|
||||
className="ml-2"
|
||||
onClick={() =>
|
||||
field.handleChange(
|
||||
generatePassword(8)
|
||||
)
|
||||
}
|
||||
>
|
||||
Random password
|
||||
</Button>
|
||||
<DebugButton data={form.state.values} />
|
||||
</div>
|
||||
{field.state.meta.errors.length ? (
|
||||
<em>{field.state.meta.errors.join(",")}</em>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</form>
|
||||
<div>
|
||||
<Button onClick={form.handleSubmit}>Save</Button>
|
||||
if (
|
||||
!/[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/.test(
|
||||
value
|
||||
)
|
||||
) {
|
||||
return "Password must contain at least one special character.";
|
||||
}
|
||||
},
|
||||
}}
|
||||
children={(field) => {
|
||||
return (
|
||||
<div className="m-2 p-2">
|
||||
<Label htmlFor="password">
|
||||
Change Password
|
||||
</Label>
|
||||
<div className="mt-2 flex flex-row">
|
||||
<Input
|
||||
className="min-w-48 max-w-96"
|
||||
name={field.name}
|
||||
value={field.state.value}
|
||||
onBlur={field.handleBlur}
|
||||
//type="number"
|
||||
onChange={(e) =>
|
||||
field.handleChange(
|
||||
e.target.value
|
||||
)
|
||||
}
|
||||
/>
|
||||
<Button
|
||||
className="ml-2"
|
||||
onClick={() =>
|
||||
field.handleChange(
|
||||
generatePassword(8)
|
||||
)
|
||||
}
|
||||
>
|
||||
Random password
|
||||
</Button>
|
||||
<DebugButton
|
||||
data={form.state.values}
|
||||
/>
|
||||
</div>
|
||||
{field.state.meta.errors.length ? (
|
||||
<em>
|
||||
{field.state.meta.errors.join(
|
||||
","
|
||||
)}
|
||||
</em>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</form>
|
||||
</LstCard>
|
||||
<div>
|
||||
<Button onClick={form.handleSubmit}>Save</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="m-2">
|
||||
<LstCard>
|
||||
<CardHeader>User Module / Role Access</CardHeader>
|
||||
<UserRoles user={data.user} />
|
||||
</LstCard>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
16
frontend/src/components/admin/user/components/UserRoles.tsx
Normal file
16
frontend/src/components/admin/user/components/UserRoles.tsx
Normal file
@@ -0,0 +1,16 @@
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { useModuleStore } from "@/lib/store/useModuleStore";
|
||||
//import { Checkbox } from "@radix-ui/react-checkbox";
|
||||
|
||||
export default function UserRoles(user: any) {
|
||||
const { modules } = useModuleStore();
|
||||
console.log(user);
|
||||
return (
|
||||
<div>
|
||||
{modules?.map((m: any) => {
|
||||
console.log(m);
|
||||
return <Label>{m.name}</Label>;
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user