Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bump typescript from 5.3.3 to 5.6.2 #97

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"rehype-react": "^8.0.0",
"remark-math": "^6.0.0",
"ts-md5": "^1.3.1",
"typescript": "^5.3.3",
"typescript": "^5.6.2",
"uuid": "^9.0.1",
"web-vitals": "^2.1.4"
},
Expand Down
4 changes: 2 additions & 2 deletions src/Router.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import React, { Suspense, lazy } from "react";
import { BrowserRouter, Routes, Route, Navigate } from "react-router-dom";
import Layout from "@/layouts/Layout";
import RankList from "./pages/RankList";

const Problem = lazy(() => import("@/pages/problem/Problem"));
const AdminProblemList = lazy(() => import("@/pages/admin/ProblemList"));
Expand All @@ -10,6 +9,7 @@ const AdminUserList = lazy(() => import("@/pages/admin/UserList"));
const ProblemList = lazy(() => import("@/pages/problem/ProblemList"));
const JudgeList = lazy(() => import("@/pages//judge/JudgeList"));
const Judge = lazy(() => import("@/pages/judge/Judge"));
const RankList = lazy(() => import("@/pages/RankList"));
const Login = lazy(() => import("@/pages/Login"));

const Router: React.FC = () => {
Expand All @@ -24,11 +24,11 @@ const Router: React.FC = () => {
<Route path="" element={<ProblemList />} />
<Route path=":slug" element={<Problem />} />
</Route>
<Route path="rank" element={<RankList />} />
<Route path="judges">
<Route path="" element={<JudgeList />} />
<Route path=":uid" element={<Judge />} />
</Route>
<Route path="rank" element={<RankList />} />
<Route path="login" element={<Login />} />
{/* Admin */}
<Route path="admin">
Expand Down
8 changes: 7 additions & 1 deletion src/apis/judge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,14 @@ export async function postJudge(slug: string, code: string, language: string) {
return res.data;
}

export async function getJudgeList(limit?: number, offset?: number) {
export async function getJudgeList(
limit?: number,
offset?: number,
selfOnly?: boolean,
) {
limit = limit || 10;
offset = offset || 0;
selfOnly = selfOnly || false;

let res = await axiosClient.get<{
total: number;
Expand All @@ -30,6 +35,7 @@ export async function getJudgeList(limit?: number, offset?: number) {
params: {
limit,
offset,
self_only: selfOnly,
},
});
if (res.status !== 200) {
Expand Down
47 changes: 47 additions & 0 deletions src/apis/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,50 @@ export async function getUserInfoList(
}
return res.data;
}

export async function deleteUser(account: string) {
let res = await axiosClient.delete(`/api/v1/user/${account}`);
if (res.status !== 200) {
throw Error("failed to delete user");
}
}

export async function grantUserRole(
account: string,
role: string,
domain?: string,
) {
if (!domain) domain = "system";

let body = {
role,
domain,
};
let data = JSON.stringify(body);

let res = await axiosClient.post(`/api/v1/user/${account}/role`, data);
if (res.status !== 200) {
throw Error("failed to grant user role");
}
}

export async function revokeUserRole(
account: string,
role: string,
domain?: string,
) {
if (!domain) domain = "system";

let body = {
role,
domain,
};
let data = JSON.stringify(body);

let res = await axiosClient.delete(`/api/v1/user/${account}/role`, {
data,
});
if (res.status !== 200) {
throw Error("failed to revoke user role");
}
}
6 changes: 3 additions & 3 deletions src/components/control/ConfirmDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ export const ConfirmDialog: FC<ConfirmDialogProps> = (props) => {

return (
<dialog id={props.id} className="modal">
<div className="modal-box">
<div className="modal-box rounded">
{props.title && <h3 className="text-lg font-bold">{t(props.title)}</h3>}
<p className="py-4">{t(props.message)}</p>
<div className="modal-action">
<form method="dialog" className="flex gap-2">
<button className="btn btn-sm">{t("Cancel")}</button>
<button className="btn btn-sm rounded">{t("Cancel")}</button>
<button
className="btn btn-error btn-sm"
className="btn btn-primary btn-sm rounded"
onClick={props.onClickConfirm}
>
{t("Confirm")}
Expand Down
2 changes: 1 addition & 1 deletion src/components/control/ProblemSearch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ const ProblemSearch: React.FC<ProblemSearchProps> = (props): JSX.Element => {
)
}
>
<option value="all">{t("all")}</option>
<option value="all">{t("all difficulty")}</option>
<option value="easy">{t("easy")}</option>
<option value="medium">{t("medium")}</option>
<option value="hard">{t("hard")}</option>
Expand Down
22 changes: 17 additions & 5 deletions src/components/display/JudgeTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import BrandCPPIcon from "@/components/display/icons/tabler/BrandCPPIcon";
import BrandPythonIcon from "@/components/display/icons/tabler/BrandPythonIcon";
import { shortenString } from "@/utils/string";
import UserAvatar from "./UserAvatar";
import { useSelector } from "react-redux";
import { userInfoSelector } from "@/store/selectors";

export interface JudgeTableProps {
data: JudgeServiceModel.JudgeInfo[];
Expand All @@ -17,6 +19,7 @@ export interface JudgeTableProps {
const JudgeTable: React.FC<JudgeTableProps> = (props) => {
const { t } = useTranslation();
const navigate = useNavigate();
const userInfo = useSelector(userInfoSelector);

return (
<div className={props.className}>
Expand All @@ -37,10 +40,19 @@ const JudgeTable: React.FC<JudgeTableProps> = (props) => {
key={idx}
className={joinClasses(
props.data.length > 1 ? "border-base-content/10" : "border-0",
props.enableRouting && "hover cursor-pointer",
((props.enableRouting && userInfo?.roles?.includes("admin")) ||
userInfo?.roles?.includes("super") ||
userInfo?.account === judge.user?.account) &&
"hover cursor-pointer",
)}
onClick={() => {
if (props.enableRouting) navigate(judge.UID);
if (
(props.enableRouting && userInfo?.roles?.includes("admin")) ||
userInfo?.roles?.includes("super") ||
userInfo?.account === judge.user?.account
) {
navigate(`/judges/${judge.UID}`);
}
}}
>
<th>{shortenString(judge.UID, 8, false)}</th>
Expand Down Expand Up @@ -94,12 +106,12 @@ function getStatusBadageClass(status: string, verdict: string): string {
if (status === "finished" && verdict === "Accepted") {
return "bg-success/10 text-success";
}
if (status === "finished" && verdict === "WrongAnswer") {
return "bg-error/10 text-error";
}
if (status === "finished" && verdict === "CompileError") {
return "bg-warning/10 text-warning";
}
if (status === "finished") {
return "bg-error/10 text-error";
}
if (status === "pending") {
return "bg-primary/10 text-primary";
}
Expand Down
14 changes: 9 additions & 5 deletions src/components/display/ProblemTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ const ProblemTable: React.FC<ProblemTableProps> = (props) => {
<ConfirmDialog
id="problem_delete_confirm_modal"
title="Confirm"
message="Are you sure to delete this problem?"
message={t("Are you sure to delete this problem?")}
onClickConfirm={() => {
ProblemService.deleteProblem(deletingSlug).then((_) => {
window.location.reload();
Expand All @@ -100,21 +100,25 @@ const ProblemTable: React.FC<ProblemTableProps> = (props) => {
};

const ProblemTags: React.FC<{ tags: { name: string }[] }> = (props) => {
const { t } = useTranslation();

return (
<div className="space-x-2">
<div>
{props.tags.map((tag) => (
<div
key={tag.name}
className="badge border-0 bg-base-300 font-semibold text-base-content/80"
className="badge m-1 border-0 bg-base-300 font-semibold text-base-content/80"
>
{tag.name}
{t(tag.name)}
</div>
))}
</div>
);
};

const DifficultyBadge: React.FC<{ difficulty: string }> = (props) => {
const { t } = useTranslation();

return (
<div
className={joinClasses(
Expand All @@ -124,7 +128,7 @@ const DifficultyBadge: React.FC<{ difficulty: string }> = (props) => {
props.difficulty === "hard" && "bg-error/10 text-error",
)}
>
{props.difficulty}
{t(props.difficulty)}
</div>
);
};
Expand Down
57 changes: 51 additions & 6 deletions src/components/display/UserTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import ConfirmDialog from "../control/ConfirmDialog";
import TrashIcon from "./icons/tabler/TrashIcon";
import { joinClasses } from "@/utils/common";
import UserCogIcon from "./icons/tabler/UserCogIcon";
import * as UserService from "@/apis/user";
import { useSelector } from "react-redux";
import { userInfoSelector } from "@/store/selectors";

export interface UserTableProps {
data: UserServiceModel.UserInfo[];
Expand All @@ -15,6 +18,9 @@ export interface UserTableProps {

const UserTable: React.FC<UserTableProps> = (props) => {
const { t } = useTranslation();
const [deletingAccount, setDeletingAccount] = React.useState<string | null>(
null,
);

return (
<>
Expand Down Expand Up @@ -47,7 +53,12 @@ const UserTable: React.FC<UserTableProps> = (props) => {
</td>
{props.showActions && (
<td className="p-2">
<UserActions userInfo={userInfo} onClickDelete={() => {}} />
<UserActions
userInfo={userInfo}
onClickDelete={() => {
setDeletingAccount(userInfo.account);
}}
/>
</td>
)}
</tr>
Expand All @@ -58,9 +69,17 @@ const UserTable: React.FC<UserTableProps> = (props) => {
<ConfirmDialog
id="user_delete_confirm_modal"
title="Confirm"
message="Are you sure to delete this user?"
message={t("Are you sure to delete this user?")}
onClickConfirm={() => {
window.location.reload();
if (deletingAccount) {
UserService.deleteUser(deletingAccount)
.then(() => {
window.location.reload();
})
.catch((err) => {
console.error(err);
});
}
}}
/>
</>
Expand Down Expand Up @@ -92,24 +111,50 @@ interface ActionsProps {
}

const UserActions: React.FC<ActionsProps> = (props) => {
const userInfo = useSelector(userInfoSelector);

const onClickDelete = (e: React.MouseEvent) => {
e.preventDefault();
e.stopPropagation();

props.onClickDelete();
const modal = document.getElementById(
"delete_confirm_modal",
"user_delete_confirm_modal",
) as HTMLDialogElement;
modal?.showModal();
};

return (
<div className="flex space-x-1">
<button className="btn btn-square btn-ghost btn-sm rounded">
<button
className={joinClasses(
"btn btn-square btn-ghost btn-sm rounded",
(props.userInfo.roles?.includes("super") ||
props.userInfo.account === userInfo?.account) &&
"btn-disabled",
)}
onClick={() => {
if (props.userInfo.roles?.includes("admin")) {
UserService.revokeUserRole(props.userInfo.account, "admin").catch(
(err) => {
console.error(err);
},
);
} else if (!props.userInfo.roles?.includes("super")) {
UserService.grantUserRole(props.userInfo.account, "admin").catch(
(err) => {
console.error(err);
},
);
}
window.location.reload();
}}
>
<UserCogIcon
className={joinClasses(
"h-5 w-5",
props.userInfo.roles?.includes("admin")
props.userInfo.roles?.includes("admin") ||
props.userInfo.roles?.includes("super")
? "text-success"
: "text-base-content",
)}
Expand Down
2 changes: 1 addition & 1 deletion src/components/navigation/PageBreadcrumbs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const PageBreadcrumbs: React.FC = () => {
let paths = location.pathname.split("/").filter((x) => x);

return (
<div className="breadcrumbs overflow-visible text-sm">
<div className="breadcrumbs overflow-visible p-0 text-sm">
<ul>
{paths.map((path, index) => {
const url = `/${paths.slice(0, index + 1).join("/")}`;
Expand Down
Loading
Loading