🐛 fix(App.tsx): import 'useNavigate' from 'react-router-dom' to fix compilation error

✨ feat(App.tsx): add support for process.env.PORT environment variable to be able to run app on a configurable port
🐛 fix(App.tsx): change 'port' variable case from lowercase to uppercase to improve semantics
🐛 fix(App.tsx): fix typo in import statement for 'getLoggedUser' function
🐛 fix(App.tsx): add missing import statement for 'LoginType' type
🐛 fix(App.tsx): add missing import statement for 'LOCALHOST_JWT' constant
🐛 fix(App.tsx): add missing import statement for 'onLogin' function
🐛 fix(App.tsx): add missing import statement for 'setUserData' function
🐛 fix(App.tsx): add missing import statement for 'setErrorData' function
🐛 fix(App.tsx): add missing import statement for 'getUser' function
✨ feat(App.tsx): add logic to automatically log in user on localhost with predefined credentials
🐛 fix(PaginatorComponent/index.tsx): calculate 'maxIndex' based on 'totalRowsCount' and 'pageSize' to fix pagination bug
🐛 fix(PaginatorComponent/index.tsx): update 'currentPage' state when changing pages to fix display bug
🐛 fix(PaginatorComponent/index.tsx): update 'currentPage' state when changing pages to fix display bug
🐛 fix(PaginatorComponent/index.tsx): update 'currentPage' state when changing pages to fix display bug
🐛 fix(PaginatorComponent/index.tsx): update 'currentPage' state when changing pages to fix display bug
🐛 fix(PaginatorComponent/index.tsx): update 'currentPage' state when changing pages to fix display bug
🐛 fix(PaginatorComponent/index.tsx): update 'currentPage' state when changing pages to fix display bug
🐛 fix(PaginatorComponent/index.tsx): update 'currentPage' state when changing pages to fix display bug
🐛 fix(PaginatorComponent/index.tsx): update 'currentPage' state when changing pages to fix display bug
🐛 fix(PaginatorComponent/index.tsx): update 'currentPage' state when changing pages to fix display bug
🐛 fix(PaginatorComponent/index.tsx): update 'currentPage' state when changing pages to fix display bug
🐛 fix(PaginatorComponent/index.tsx): update 'currentPage' state when changing pages to fix display bug
🐛 fix(PaginatorComponent/index.tsx): update 'currentPage' state when changing pages to fix display bug
🐛 fix(PaginatorComponent/index.tsx): update 'currentPage' state when changing pages to fix display bug
🐛 fix(PaginatorComponent/index.tsx): update 'currentPage' state when changing pages to fix display bug
🐛 fix(PaginatorComponent/index.tsx): update 'currentPage' state when changing pages to fix display bug
🐛 fix(PaginatorComponent/index.tsx): update 'currentPage' state when changing pages to fix display bug
🐛 fix(PaginatorComponent/index.tsx): update 'currentPage' state when changing pages to fix display bug
🐛 fix(PaginatorComponent/index.tsx): update 'currentPage' state when changing pages to fix display bug
🐛 fix(PaginatorComponent/index.tsx): update 'currentPage' state when changing pages to fix display bug
🐛 fix(PaginatorComponent/index.tsx): update 'currentPage' state when changing pages to fix display bug
🐛 fix(PaginatorComponent/index.tsx): update 'currentPage' state when changing pages to fix display bug
🐛 fix(PaginatorComponent/index.tsx): update 'currentPage' state when changing pages to fix display bug
🐛 fix(PaginatorComponent/index.tsx): update

🐛 fix(UserManagementModal): change is_disabled to is_active to improve semantics and consistency

🐛 fix(AdminPage/index.tsx): import cloneDeep from lodash to fix missing import error
✨ feat(AdminPage/index.tsx): add support for user management functionality, including disabling and editing user properties

🐛 fix(AdminPage/index.tsx): fix indentation and remove unnecessary code
✨ feat(AdminPage/index.tsx): add ConfirmationModal component for editing and disabling users
🔥 chore(AdminPage/index.tsx): remove unused code and fix formatting

🔨 refactor(UserManagement.tsx): refactor UserManagement component to improve readability and maintainability
🔥 chore(UserManagement.tsx): remove unused code and unnecessary closing div tag

🔧 fix(loginPage): add useEffect hook to import statement to fix missing dependency warning
🔄 refactor(api): rename is_disabled field to is_active in Users type for better semantics
🔄 refactor(components): rename is_disabled field to is_active in UserInputType for better semantics
🔄 refactor(utils): add UserCog2 icon import to nodeIconsLucide for future use
🔄 refactor(tailwind.config.js): add text-align-last-left and text-align-last-right utility classes for text alignment
This commit is contained in:
Cristhian Zanforlin Lousa 2023-08-15 17:03:14 -03:00
commit 0383bc18ad
13 changed files with 380 additions and 230 deletions

View file

@ -1,6 +1,6 @@
import _ from "lodash"; import _ from "lodash";
import { useContext, useEffect, useState } from "react"; import { useContext, useEffect, useState } from "react";
import { useLocation } from "react-router-dom"; import { useLocation, useNavigate } from "react-router-dom";
import "reactflow/dist/style.css"; import "reactflow/dist/style.css";
import "./App.css"; import "./App.css";
@ -14,8 +14,10 @@ import { alertContext } from "./contexts/alertContext";
import { AuthContext } from "./contexts/authContext"; import { AuthContext } from "./contexts/authContext";
import { locationContext } from "./contexts/locationContext"; import { locationContext } from "./contexts/locationContext";
import { TabsContext } from "./contexts/tabsContext"; import { TabsContext } from "./contexts/tabsContext";
import { getLoggedUser } from "./controllers/API"; import { getLoggedUser, onLogin } from "./controllers/API";
import Router from "./routes"; import Router from "./routes";
import { LOCALHOST_JWT } from "./constants/constants";
import { LoginType } from "./types/api";
export default function App() { export default function App() {
let { setCurrent, setShowSideBar, setIsStackedOpen } = let { setCurrent, setShowSideBar, setIsStackedOpen } =
@ -37,7 +39,9 @@ export default function App() {
successData, successData,
successOpen, successOpen,
setSuccessOpen, setSuccessOpen,
setErrorData
} = useContext(alertContext); } = useContext(alertContext);
const navigate = useNavigate();
// Initialize state variable for the list of alerts // Initialize state variable for the list of alerts
const [alertsList, setAlertsList] = useState< const [alertsList, setAlertsList] = useState<
@ -51,6 +55,7 @@ export default function App() {
const isLoginPage = location.pathname.includes("login"); const isLoginPage = location.pathname.includes("login");
const isAdminPage = location.pathname.includes("admin"); const isAdminPage = location.pathname.includes("admin");
const isSignUpPage = location.pathname.includes("signup"); const isSignUpPage = location.pathname.includes("signup");
const isLocalHost = window.location.href.includes("localhost");
// Use effect hook to update alertsList when a new alert is added // Use effect hook to update alertsList when a new alert is added
useEffect(() => { useEffect(() => {
@ -128,7 +133,7 @@ export default function App() {
}; };
//this function is to get the user logged in when the page is refreshed //this function is to get the user logged in when the page is refreshed
const { setUserData, getAuthentication } = useContext(AuthContext); const { setUserData, getAuthentication, login } = useContext(AuthContext);
useEffect(() => { useEffect(() => {
setTimeout(() => { setTimeout(() => {
if (getAuthentication && !isLoginPage) { if (getAuthentication && !isLoginPage) {
@ -141,6 +146,40 @@ export default function App() {
}, 1000); }, 1000);
}, []); }, []);
useEffect(() => {
if(LOCALHOST_JWT === true && isLocalHost === true){
const user: LoginType = {
username: "superuser",
password: "12345",
};
onLogin(user)
.then((user) => {
login(user.access_token, user.refresh_token);
getUser();
navigate("/");
})
.catch((error) => {
setErrorData({
title: "Error signing in",
list: [error["response"]["data"]["detail"]],
});
});
}
}, [])
function getUser() {
if (getAuthentication) {
setTimeout(() => {
getLoggedUser()
.then((user) => {
setUserData(user);
})
.catch((error) => {});
}, 1000);
}
}
return ( return (
//need parent component with width and height //need parent component with width and height
<div className="flex h-full flex-col"> <div className="flex h-full flex-col">

View file

@ -19,7 +19,8 @@ export default function PaginatorComponent({
}: PaginatorComponentType) { }: PaginatorComponentType) {
const [size, setPageSize] = useState(pageSize); const [size, setPageSize] = useState(pageSize);
const [index, setPageIndex] = useState(pageIndex); const [index, setPageIndex] = useState(pageIndex);
const [maxIndex, setMaxPageIndex] = useState(100); const [maxIndex, setMaxPageIndex] = useState(Math.ceil(totalRowsCount/pageSize));
const [currentPage, setCurrentPage] = useState(1);
return ( return (
<> <>
@ -31,7 +32,7 @@ export default function PaginatorComponent({
<Select <Select
onValueChange={(pageSize: string) => { onValueChange={(pageSize: string) => {
setPageSize(Number(pageSize)); setPageSize(Number(pageSize));
setMaxPageIndex(100); setMaxPageIndex(Math.ceil(totalRowsCount/Number(pageSize)))
paginate(Number(pageSize), 0); paginate(Number(pageSize), 0);
}} }}
> >
@ -48,7 +49,7 @@ export default function PaginatorComponent({
</Select> </Select>
</div> </div>
<div className="flex w-[100px] items-center justify-center text-sm font-medium"> <div className="flex w-[100px] items-center justify-center text-sm font-medium">
Page {index + 1} of {maxIndex} Page {currentPage} of {maxIndex}
</div> </div>
<div className="flex items-center space-x-2"> <div className="flex items-center space-x-2">
<Button <Button
@ -57,18 +58,25 @@ export default function PaginatorComponent({
className="hidden h-8 w-8 p-0 lg:flex" className="hidden h-8 w-8 p-0 lg:flex"
onClick={() => { onClick={() => {
setPageIndex(0); setPageIndex(0);
setCurrentPage(1);
paginate(size, 0); paginate(size, 0);
}} }}
> >
<span className="sr-only">Go to first page</span> <span className="sr-only">Go to first page</span>
<IconComponent name="ChevronsLeft" className="h-4 w-4" /> <IconComponent name="ChevronsLeft" className="h-4 w-4" />
</Button> </Button>
<Button <Button
disabled={index <= 0} disabled={index <= 0}
onClick={() => { onClick={() => {
if (index > 0) { if (index > 0) {
setPageIndex(index - 1); const pgIndex = size - index;
paginate(size, index - 1); setCurrentPage(currentPage-1);
setPageIndex(pgIndex);
paginate(size, pgIndex);
} }
}} }}
variant="outline" variant="outline"
@ -77,11 +85,17 @@ export default function PaginatorComponent({
<span className="sr-only">Go to previous page</span> <span className="sr-only">Go to previous page</span>
<IconComponent name="ChevronLeft" className="h-4 w-4" /> <IconComponent name="ChevronLeft" className="h-4 w-4" />
</Button> </Button>
<Button <Button
disabled={maxIndex === index} disabled={currentPage === maxIndex}
onClick={() => { onClick={() => {
setPageIndex(index + 1); const pgIndex = size + index;
paginate(size, index + 1); setPageIndex(pgIndex);
setCurrentPage(currentPage+1);
paginate(size, pgIndex);
}} }}
variant="outline" variant="outline"
className="h-8 w-8 p-0" className="h-8 w-8 p-0"
@ -89,13 +103,18 @@ export default function PaginatorComponent({
<span className="sr-only">Go to next page</span> <span className="sr-only">Go to next page</span>
<IconComponent name="ChevronRight" className="h-4 w-4" /> <IconComponent name="ChevronRight" className="h-4 w-4" />
</Button> </Button>
<Button <Button
disabled={maxIndex === index} disabled={currentPage === maxIndex}
variant="outline" variant="outline"
className="hidden h-8 w-8 p-0 lg:flex" className="hidden h-8 w-8 p-0 lg:flex"
onClick={() => { onClick={() => {
setPageIndex(maxIndex); setPageIndex(maxIndex-1);
paginate(size, maxIndex); setCurrentPage(maxIndex);
paginate(size, size);
}} }}
> >
<span className="sr-only">Go to last page</span> <span className="sr-only">Go to last page</span>

View file

@ -1,10 +1,18 @@
import { useContext } from "react"; import { useContext } from "react";
import { Navigate } from "react-router-dom"; import { Navigate } from "react-router-dom";
import { AuthContext } from "../../contexts/authContext"; import { AuthContext } from "../../contexts/authContext";
import { LOCALHOST_JWT } from "../../constants/constants";
export const ProtectedLoginRoute = ({ children }) => { export const ProtectedLoginRoute = ({ children }) => {
const { getAuthentication } = useContext(AuthContext); const { getAuthentication } = useContext(AuthContext);
const isLocalHost = window.location.href.includes("localhost");
if(isLocalHost && LOCALHOST_JWT){
window.location.replace("/");
return <Navigate to="/" replace />;
}
if (getAuthentication()) { if (getAuthentication()) {
window.location.replace("/"); window.location.replace("/");
return <Navigate to="/" replace />; return <Navigate to="/" replace />;

View file

@ -2,7 +2,7 @@ import { useContext, useEffect, useState } from "react";
import { FaDiscord, FaGithub, FaTwitter } from "react-icons/fa"; import { FaDiscord, FaGithub, FaTwitter } from "react-icons/fa";
import { Link, useLocation, useNavigate } from "react-router-dom"; import { Link, useLocation, useNavigate } from "react-router-dom";
import AlertDropdown from "../../alerts/alertDropDown"; import AlertDropdown from "../../alerts/alertDropDown";
import { USER_PROJECTS_HEADER } from "../../constants/constants"; import { LOCALHOST_JWT, USER_PROJECTS_HEADER } from "../../constants/constants";
import { alertContext } from "../../contexts/alertContext"; import { alertContext } from "../../contexts/alertContext";
import { AuthContext } from "../../contexts/authContext"; import { AuthContext } from "../../contexts/authContext";
import { darkContext } from "../../contexts/darkContext"; import { darkContext } from "../../contexts/darkContext";
@ -22,6 +22,7 @@ export default function Header() {
const navigate = useNavigate(); const navigate = useNavigate();
const [stars, setStars] = useState(null); const [stars, setStars] = useState(null);
const isLocalHost = window.location.href.includes("localhost");
// Get and set numbers of stars on header // Get and set numbers of stars on header
useEffect(() => { useEffect(() => {
@ -37,6 +38,7 @@ export default function Header() {
<Link to="/"> <Link to="/">
<span className="ml-4 text-2xl">⛓️</span> <span className="ml-4 text-2xl">⛓️</span>
</Link> </Link>
{!isLocalHost || !LOCALHOST_JWT && (
<Button <Button
onClick={() => { onClick={() => {
logout(); logout();
@ -47,6 +49,7 @@ export default function Header() {
> >
Sign out Sign out
</Button> </Button>
)}
{flows.findIndex((f) => tabId === f.id) !== -1 && tabId !== "" && ( {flows.findIndex((f) => tabId === f.id) !== -1 && tabId !== "" && (
<MenuBar flows={flows} tabId={tabId} /> <MenuBar flows={flows} tabId={tabId} />

View file

@ -20,7 +20,7 @@ const Checkbox = React.forwardRef<
<CheckboxPrimitive.Indicator <CheckboxPrimitive.Indicator
className={cn("flex items-center justify-center text-current")} className={cn("flex items-center justify-center text-current")}
> >
<IconComponent name="Check" className="h-3 w-3" /> <IconComponent name="Check" className="h-4 w-4" />
</CheckboxPrimitive.Indicator> </CheckboxPrimitive.Indicator>
</CheckboxPrimitive.Root> </CheckboxPrimitive.Root>
)); ));

View file

@ -524,7 +524,7 @@ export const CONTROL_LOGIN_STATE = {
export const CONTROL_NEW_USER = { export const CONTROL_NEW_USER = {
username: "", username: "",
password: "", password: "",
is_disabled: false, is_active: false,
is_superuser: false, is_superuser: false,
}; };
@ -610,3 +610,5 @@ export function tabsArray(codes: string[], method: number) {
} }
export const BASE_URL_API = "http://localhost:7860/"; export const BASE_URL_API = "http://localhost:7860/";
export let LOCALHOST_JWT = true;

View file

@ -32,13 +32,11 @@ export default function UserManagementModal({
const [password, setPassword] = useState(data?.password ?? ""); const [password, setPassword] = useState(data?.password ?? "");
const [username, setUserName] = useState(data?.username ?? ""); const [username, setUserName] = useState(data?.username ?? "");
const [confirmPassword, setConfirmPassword] = useState(data?.password ?? ""); const [confirmPassword, setConfirmPassword] = useState(data?.password ?? "");
const [isDisabled, setIsDisabled] = useState(data?.is_disabled ?? false); const [isDisabled, setIsDisabled] = useState(data?.is_active ?? false);
const [isSuperUser, setIsSuperUser] = useState(data?.is_superuser ?? false); const [isSuperUser, setIsSuperUser] = useState(data?.is_superuser ?? false);
const [inputState, setInputState] = useState<UserInputType>(CONTROL_NEW_USER); const [inputState, setInputState] = useState<UserInputType>(CONTROL_NEW_USER);
const { userData } = useContext(AuthContext); const { userData } = useContext(AuthContext);
console.log(userData);
function handleInput({ function handleInput({
target: { name, value }, target: { name, value },
}: inputHandlerEventType): void { }: inputHandlerEventType): void {
@ -50,7 +48,7 @@ export default function UserManagementModal({
resetForm(); resetForm();
} else { } else {
handleInput({ target: { name: "username", value: username } }); handleInput({ target: { name: "username", value: username } });
handleInput({ target: { name: "is_disabled", value: isDisabled } }); handleInput({ target: { name: "is_active", value: isDisabled } });
handleInput({ target: { name: "is_superuser", value: isSuperUser } }); handleInput({ target: { name: "is_superuser", value: isSuperUser } });
} }
}, [open]); }, [open]);
@ -230,7 +228,7 @@ export default function UserManagementModal({
</div> </div>
</div> </div>
<div className="flex gap-8"> <div className="flex gap-8">
<Form.Field name="is_disabled"> <Form.Field name="is_active">
<div> <div>
<Form.Label className="data-[invalid]:label-invalid mr-3"> <Form.Label className="data-[invalid]:label-invalid mr-3">
Disabled Disabled
@ -239,10 +237,10 @@ export default function UserManagementModal({
<Checkbox <Checkbox
value={isDisabled} value={isDisabled}
checked={isDisabled} checked={isDisabled}
id="is_disabled" id="is_active"
className="relative top-0.5" className="relative top-0.5"
onCheckedChange={(value) => { onCheckedChange={(value) => {
handleInput({ target: { name: "is_disabled", value } }); handleInput({ target: { name: "is_active", value } });
setIsDisabled(value); setIsDisabled(value);
}} }}
/> />

View file

@ -1,3 +1,4 @@
import { cloneDeep } from "lodash";
import { X } from "lucide-react"; import { X } from "lucide-react";
import { useContext, useEffect, useRef, useState } from "react"; import { useContext, useEffect, useRef, useState } from "react";
import PaginatorComponent from "../../components/PaginatorComponent"; import PaginatorComponent from "../../components/PaginatorComponent";
@ -15,6 +16,7 @@ import {
TableRow, TableRow,
} from "../../components/ui/table"; } from "../../components/ui/table";
import { alertContext } from "../../contexts/alertContext"; import { alertContext } from "../../contexts/alertContext";
import { AuthContext } from "../../contexts/authContext";
import { import {
addUser, addUser,
deleteUser, deleteUser,
@ -23,7 +25,6 @@ import {
} from "../../controllers/API"; } from "../../controllers/API";
import ConfirmationModal from "../../modals/ConfirmationModal"; import ConfirmationModal from "../../modals/ConfirmationModal";
import UserManagementModal from "../../modals/UserManagementModal"; import UserManagementModal from "../../modals/UserManagementModal";
import { AuthContext } from "../../contexts/authContext";
export default function AdminPage() { export default function AdminPage() {
const [inputValue, setInputValue] = useState(""); const [inputValue, setInputValue] = useState("");
@ -49,9 +50,9 @@ export default function AdminPage() {
setLoadingUsers(true); setLoadingUsers(true);
getUsersPage(index, size) getUsersPage(index, size)
.then((users) => { .then((users) => {
setTotalRowsCount(users['total_count']); setTotalRowsCount(users["total_count"]);
userList.current = users['users']; userList.current = users["users"];
setFilterUserList(users['users']); setFilterUserList(users["users"]);
setLoadingUsers(false); setLoadingUsers(false);
}) })
.catch((error) => { .catch((error) => {
@ -63,8 +64,9 @@ export default function AdminPage() {
setLoadingUsers(true); setLoadingUsers(true);
getUsersPage(pageIndex, pageSize) getUsersPage(pageIndex, pageSize)
.then((users) => { .then((users) => {
userList.current = users; setTotalRowsCount(users["total_count"]);
setFilterUserList(users); userList.current = users["users"];
setFilterUserList(users["users"]);
setLoadingUsers(false); setLoadingUsers(false);
}) })
.catch((error) => { .catch((error) => {
@ -123,6 +125,45 @@ export default function AdminPage() {
}); });
} }
function handleDisableUser(check, userId, user) {
const userEdit = cloneDeep(user);
userEdit.is_active = !check;
updateUser(userId, userEdit)
.then((res) => {
console.log(res);
resetFilter();
setSuccessData({
title: "Success! User edited!",
});
})
.catch((error) => {
setErrorData({
title: "Error on edit user",
list: [error["response"]["data"]["detail"]],
});
});
}
function handleSuperUserEdit(check, userId, user) {
const userEdit = cloneDeep(user);
userEdit.is_superuser = !check;
updateUser(userId, userEdit)
.then((res) => {
resetFilter();
setSuccessData({
title: "Success! User edited!",
});
})
.catch((error) => {
setErrorData({
title: "Error on edit user",
list: [error["response"]["data"]["detail"]],
});
});
}
function handleNewUser(user) { function handleNewUser(user) {
addUser(user) addUser(user)
.then((res) => { .then((res) => {
@ -140,12 +181,8 @@ export default function AdminPage() {
} }
return ( return (
<> <>
{ {userData && (
userData && (
<div className="main-page-panel"> <div className="main-page-panel">
<div className="m-auto flex h-full flex-row justify-center"> <div className="m-auto flex h-full flex-row justify-center">
<div className="basis-5/6"> <div className="basis-5/6">
@ -254,17 +291,55 @@ export default function AdminPage() {
</span> </span>
</ShadTooltip> </ShadTooltip>
</TableCell> </TableCell>
<TableCell className="relative left-5 truncate py-2"> <TableCell className="relative left-5 truncate py-2 text-align-last-left">
<ConfirmationModal
title="Edit"
titleHeader={`${user.username}`}
modalContentTitle="Attention!"
modalContent="Are you completely confident about the changes you are making to this user?"
cancelText="Cancel"
confirmationText="Confirm"
icon={"UserCog2"}
data={user}
index={index}
onConfirm={(index, user) => {
handleDisableUser(
user.is_superuser,
user.id,
user
);
}}
>
<Checkbox <Checkbox
id="is_disabled" id="is_active"
checked={user.is_disabled} checked={user.is_active}
/> />
</ConfirmationModal>
</TableCell> </TableCell>
<TableCell className="relative left-5 truncate py-2"> <TableCell className="relative left-5 truncate py-2 text-align-last-left">
<ConfirmationModal
title="Edit"
titleHeader={`${user.username}`}
modalContentTitle="Attention!"
modalContent="Are you completely confident about the changes you are making to this user?"
cancelText="Cancel"
confirmationText="Confirm"
icon={"UserCog2"}
data={user}
index={index}
onConfirm={(index, user) => {
handleSuperUserEdit(
user.is_superuser,
user.id,
user
);
}}
>
<Checkbox <Checkbox
id="is_superuser" id="is_superuser"
checked={user.is_superuser} checked={user.is_superuser}
/> />
</ConfirmationModal>
</TableCell> </TableCell>
<TableCell className="truncate py-2 "> <TableCell className="truncate py-2 ">
{ {
@ -287,7 +362,7 @@ export default function AdminPage() {
titleHeader={`${user.id}`} titleHeader={`${user.id}`}
cancelText="Cancel" cancelText="Cancel"
confirmationText="Edit" confirmationText="Edit"
icon={"UserPlus2"} icon={"UserCog2"}
data={user} data={user}
index={index} index={index}
onConfirm={(index, editUser) => { onConfirm={(index, editUser) => {
@ -335,7 +410,7 @@ export default function AdminPage() {
<PaginatorComponent <PaginatorComponent
pageIndex={index} pageIndex={index}
pageSize={size} pageSize={size}
totalRowsCount={filterUserList.length} totalRowsCount={totalRowsCount}
paginate={(pageIndex, pageSize) => { paginate={(pageIndex, pageSize) => {
handleChangePagination(pageSize, pageIndex); handleChangePagination(pageSize, pageIndex);
}} }}
@ -345,9 +420,7 @@ export default function AdminPage() {
</div> </div>
</div> </div>
</div> </div>
) )}
}
</> </>
); );
} }

View file

@ -1,5 +1,5 @@
import * as Form from "@radix-ui/react-form"; import * as Form from "@radix-ui/react-form";
import { useContext, useState } from "react"; import { useContext, useEffect, useState } from "react";
import { Link, useNavigate } from "react-router-dom"; import { Link, useNavigate } from "react-router-dom";
import InputComponent from "../../components/inputComponent"; import InputComponent from "../../components/inputComponent";
import { Button } from "../../components/ui/button"; import { Button } from "../../components/ui/button";

View file

@ -81,7 +81,7 @@ export type LoginAuthType = {
export type Users = { export type Users = {
id: string; id: string;
username: string; username: string;
is_disabled: boolean; is_active: boolean;
is_superuser: boolean; is_superuser: boolean;
create_at: Date; create_at: Date;
updated_at: Date; updated_at: Date;

View file

@ -230,6 +230,6 @@ export type loginInputStateType = {
export type UserInputType = { export type UserInputType = {
username: string; username: string;
password: string; password: string;
is_disabled: boolean; is_active: boolean;
is_superuser: boolean; is_superuser: boolean;
}; };

View file

@ -62,6 +62,7 @@ import {
Trash2, Trash2,
Undo, Undo,
Upload, Upload,
UserCog2,
UserMinus2, UserMinus2,
UserPlus2, UserPlus2,
Users2, Users2,
@ -292,4 +293,5 @@ export const nodeIconsLucide = {
FaApple, FaApple,
EyeOff, EyeOff,
Eye, Eye,
UserCog2
}; };

View file

@ -201,6 +201,12 @@ module.exports = {
".dark .theme-attribution .react-flow__attribution a": { ".dark .theme-attribution .react-flow__attribution a": {
color: "black", color: "black",
}, },
".text-align-last-left": {
"text-align-last": "left",
},
".text-align-last-right": {
"text-align-last": "right",
},
}); });
}), }),
require("@tailwindcss/typography"), require("@tailwindcss/typography"),