feat: 모듈API 권한관리 다이얼로그 작업
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
import { client } from "@/shared/api";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import type {
|
||||
RoleAuthorizationsService,
|
||||
RoleAuthorizationsParams,
|
||||
RoleAuthorizationsList,
|
||||
RoleAuthorizationsData,
|
||||
RoleAuthorizations,
|
||||
} from "../model/role-authorizations-interface";
|
||||
|
||||
export class RoleAuthorizationsApiService implements RoleAuthorizationsService {
|
||||
public async getRoleAuthorizationsList(
|
||||
params: RoleAuthorizationsParams,
|
||||
): Promise<RoleAuthorizationsList> {
|
||||
const response = await client.get<RoleAuthorizationsList>(
|
||||
`${ENDPOINT.USER_SERVICE.ROLE_AUTHORIZATIONS}/api`,
|
||||
{ params },
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async createRoleAuthorizations(
|
||||
data: RoleAuthorizationsData,
|
||||
): Promise<RoleAuthorizations> {
|
||||
const response = await client.post<RoleAuthorizations>(
|
||||
`${ENDPOINT.USER_SERVICE.ROLE_AUTHORIZATIONS}`,
|
||||
data,
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async updateRoleAuthorizations(
|
||||
authorizationNo: string,
|
||||
data: RoleAuthorizationsData,
|
||||
): Promise<RoleAuthorizations> {
|
||||
const response = await client.put<RoleAuthorizations>(
|
||||
`${ENDPOINT.USER_SERVICE.ROLE_AUTHORIZATIONS}/${authorizationNo}`,
|
||||
data,
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
}
|
||||
|
||||
export const RoleAuthorizationsApi = new RoleAuthorizationsApiService();
|
||||
@@ -4,6 +4,9 @@ import type { PageableList, PageableParams } from "@/shared/model";
|
||||
export interface AuthorizationsParams extends PageableParams {
|
||||
keywordType?: string;
|
||||
keyword?: string;
|
||||
authorizationName?: string;
|
||||
httpMethodCode?: string;
|
||||
useYn?: string;
|
||||
}
|
||||
|
||||
export interface Authorizations {
|
||||
@@ -17,16 +20,18 @@ export interface Authorizations {
|
||||
mdfcnDt: string;
|
||||
}
|
||||
|
||||
export interface RoleAuthorizations {
|
||||
roleId: string;
|
||||
authorizationNo: number;
|
||||
authorizationName: string;
|
||||
urlPatternValue: string;
|
||||
httpMethodCode: string;
|
||||
sortSeq: number;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface WithRoleAuthorizations extends Authorizations {
|
||||
roleAuthorizations: {
|
||||
roleId: string;
|
||||
authorizationNo: number;
|
||||
authorizationName: string;
|
||||
urlPatternValue: string;
|
||||
httpMethodCode: string;
|
||||
sortSeq: number;
|
||||
createdAt: string;
|
||||
}[];
|
||||
roleAuthorizations: RoleAuthorizations[];
|
||||
}
|
||||
|
||||
export const authorizationFormSchema = z.object({
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
import { z } from "zod";
|
||||
import type { PageableList, PageableParams } from "@/shared/model";
|
||||
|
||||
export interface RoleAuthorizationsParams extends PageableParams {
|
||||
keywordType?: string;
|
||||
keyword?: string;
|
||||
authorizationNo?: string;
|
||||
}
|
||||
|
||||
export interface RoleAuthorizations {
|
||||
roleId: string;
|
||||
roleName: string;
|
||||
roleContent: string;
|
||||
useYn: string;
|
||||
authorizationNo: number;
|
||||
}
|
||||
|
||||
export const roleAuthorizationsSchema = z.object({
|
||||
roleId: z.string(),
|
||||
authorizationNo: z.number(),
|
||||
});
|
||||
|
||||
export const roleAuthorizationsFormSchema = z.object({
|
||||
roleAuthorizations: z.array(roleAuthorizationsSchema),
|
||||
});
|
||||
|
||||
export type RoleAuthorizationsList = PageableList<RoleAuthorizations>;
|
||||
export type RoleAuthorizationsData = z.infer<typeof roleAuthorizationsSchema>[];
|
||||
export type RoleAuthorizationsFormData = z.infer<
|
||||
typeof roleAuthorizationsFormSchema
|
||||
>;
|
||||
|
||||
export interface RoleAuthorizationsService {
|
||||
getRoleAuthorizationsList: (
|
||||
params: RoleAuthorizationsParams,
|
||||
) => Promise<RoleAuthorizationsList>;
|
||||
createRoleAuthorizations: (
|
||||
data: RoleAuthorizationsData,
|
||||
) => Promise<RoleAuthorizations>;
|
||||
updateRoleAuthorizations: (
|
||||
authorizationNo: string,
|
||||
data: RoleAuthorizationsData,
|
||||
) => Promise<RoleAuthorizations>;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
import { type ColumnDef } from "@tanstack/react-table";
|
||||
import type { RoleAuthorizations } from "./role-authorizations-interface";
|
||||
import { Checkbox } from "@common/components/ui";
|
||||
|
||||
export const columns: ColumnDef<RoleAuthorizations>[] = [
|
||||
{
|
||||
id: "select",
|
||||
header: ({ table }) => (
|
||||
<Checkbox
|
||||
checked={table.getIsAllPageRowsSelected()}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
onCheckedChange={(checked) =>
|
||||
table.toggleAllPageRowsSelected(!!checked)
|
||||
}
|
||||
className="h-4 w-4 rounded border-gray-300"
|
||||
/>
|
||||
),
|
||||
cell: ({ row }) => (
|
||||
<Checkbox
|
||||
checked={row.getIsSelected()}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
onCheckedChange={(checked) => row.toggleSelected(!!checked)}
|
||||
className="h-4 w-4 rounded border-gray-300"
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "roleId",
|
||||
header: "권한ID",
|
||||
},
|
||||
{
|
||||
accessorKey: "roleName",
|
||||
header: "권한명",
|
||||
},
|
||||
{
|
||||
accessorKey: "roleContent",
|
||||
header: "권한설명",
|
||||
},
|
||||
];
|
||||
@@ -1,6 +1,7 @@
|
||||
import dayjs from "dayjs";
|
||||
import { type ColumnDef } from "@tanstack/react-table";
|
||||
import type { Authorizations } from "./authorizations-interface";
|
||||
import { ManagementAuthorityDialog } from "../ui/management-authority-dialog";
|
||||
|
||||
export const columns: ColumnDef<Authorizations>[] = [
|
||||
{
|
||||
@@ -36,4 +37,22 @@ export const columns: ColumnDef<Authorizations>[] = [
|
||||
return date.format("YYYY-MM-DD");
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "action",
|
||||
header: "권한관리",
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
<div
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
}}
|
||||
>
|
||||
<ManagementAuthorityDialog
|
||||
authorizationNo={row.original.authorizationNo.toString()}
|
||||
rowData={row.original}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
import { useState } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||
import {
|
||||
getCoreRowModel,
|
||||
useReactTable,
|
||||
type RowSelectionState,
|
||||
} from "@tanstack/react-table";
|
||||
import { useConfirm } from "@frontend-opensource/use-react-hooks";
|
||||
import {
|
||||
Button,
|
||||
DataTable,
|
||||
Dialog,
|
||||
DialogClose,
|
||||
DialogContent,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@common/components/ui";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import { useAlertStore } from "@/shared/lib/use-alert-store";
|
||||
import {
|
||||
roleAuthorizationFormSchema,
|
||||
type RoleAuthorizationFormData,
|
||||
type RoleAuthorizationData,
|
||||
} from "../model/role-authorizations-interface";
|
||||
import { columns } from "../model/role-authorizations-table-columns";
|
||||
import type { Authorizations } from "../model/authorizations-interface";
|
||||
import { RoleAuthorizationsApi } from "../api/role-authorization-service";
|
||||
|
||||
type ManagementAuthorityDialogProps = {
|
||||
authorizationNo?: string;
|
||||
rowData?: Authorizations;
|
||||
} & React.ComponentProps<typeof Dialog>;
|
||||
|
||||
function ManagementAuthorityDialog({
|
||||
authorizationNo,
|
||||
...props
|
||||
}: ManagementAuthorityDialogProps) {
|
||||
const { confirm } = useConfirm();
|
||||
const { setMessage: alert } = useAlertStore((state) => state);
|
||||
|
||||
const [isOpened, setIsOpened] = useState(false);
|
||||
const [rowSelection, setRowSelection] = useState<RowSelectionState>({});
|
||||
|
||||
const { data: roleAuthorizationList } = useQuery({
|
||||
queryKey: [ENDPOINT.USER_SERVICE.ROLE_AUTHORIZATIONS, authorizationNo],
|
||||
queryFn: () =>
|
||||
RoleAuthorizationsApi.getRoleAuthorizationsList({ authorizationNo }),
|
||||
enabled: !!authorizationNo && isOpened,
|
||||
});
|
||||
|
||||
const { mutateAsync: saveRoleAuthorization } = useMutation({
|
||||
mutationFn: (data: RoleAuthorizationData) =>
|
||||
RoleAuthorizationsApi.createRoleAuthorization(data),
|
||||
onSuccess: () => {
|
||||
alert("저장되었습니다.");
|
||||
},
|
||||
});
|
||||
|
||||
const form = useForm<RoleAuthorizationFormData>({
|
||||
resolver: zodResolver(roleAuthorizationFormSchema),
|
||||
values: {
|
||||
roleAuthorizations: roleAuthorizationList?.content ?? [],
|
||||
},
|
||||
});
|
||||
|
||||
const table = useReactTable({
|
||||
data: roleAuthorizationList?.content ?? [],
|
||||
columns,
|
||||
state: {
|
||||
rowSelection,
|
||||
},
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
onRowSelectionChange: setRowSelection,
|
||||
});
|
||||
|
||||
const handleSave = async () => {
|
||||
if (await confirm("선택한 권한을 허용하시겠습니까?")) {
|
||||
const data = form.getValues("roleAuthorizations");
|
||||
await saveRoleAuthorization(data);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog {...props}>
|
||||
<DialogTrigger asChild>
|
||||
<Button size="sm" onClick={() => setIsOpened(true)}>
|
||||
권한관리
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="max-w-[60rem]" aria-describedby={undefined}>
|
||||
<DialogHeader>
|
||||
<DialogTitle>모듈API 권한관리</DialogTitle>
|
||||
</DialogHeader>
|
||||
<DataTable table={table} />
|
||||
<DialogFooter className="!justify-center">
|
||||
<Button size="lg" onClick={handleSave}>
|
||||
허용
|
||||
</Button>
|
||||
<DialogClose asChild>
|
||||
<Button size="lg" color="white">
|
||||
취소
|
||||
</Button>
|
||||
</DialogClose>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
export { ManagementAuthorityDialog };
|
||||
@@ -23,8 +23,8 @@ function ModulePage() {
|
||||
|
||||
const [authorizationQuery, setAuthorizationQuery] =
|
||||
useState<AuthorizationsParams>({
|
||||
keywordType: "",
|
||||
keyword: "",
|
||||
authorizationName: "",
|
||||
httpMethodCode: "",
|
||||
});
|
||||
const [pagination, setPagination] = useState<PaginationState>({
|
||||
pageIndex: 0,
|
||||
@@ -32,7 +32,7 @@ function ModulePage() {
|
||||
});
|
||||
|
||||
const { data: authorizationsList, refetch } = useQuery({
|
||||
queryKey: [ENDPOINT.CMS_SERVICE.CONTENTS],
|
||||
queryKey: [ENDPOINT.USER_SERVICE.AUTHORIZATIONS],
|
||||
queryFn: () =>
|
||||
AuthorizationsApi.getAuthorizationsList({
|
||||
...authorizationQuery,
|
||||
@@ -79,24 +79,26 @@ function ModulePage() {
|
||||
<form onSubmit={handleSubmit} className="flex gap-2 p-2">
|
||||
<div className="flex space-x-6">
|
||||
<div className="flex items-center gap-2">
|
||||
<Label htmlFor="keywordType" className="text-label">
|
||||
<Label htmlFor="httpMethodCode" className="text-label">
|
||||
요청 메소드
|
||||
</Label>
|
||||
<CodeSelect
|
||||
upCd="HTTPMHD"
|
||||
onValueChange={handleAuthorizationQueryChange("keywordType")}
|
||||
onValueChange={handleAuthorizationQueryChange("httpMethodCode")}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Label htmlFor="keyword" className="text-label">
|
||||
<Label htmlFor="authorizationName" className="text-label">
|
||||
API명
|
||||
</Label>
|
||||
<Input
|
||||
id="keyword"
|
||||
className="h-[3.2rem] w-[24rem] rounded-sm !text-[1.3rem]"
|
||||
value={authorizationQuery.keyword}
|
||||
value={authorizationQuery.authorizationName}
|
||||
onChange={(e) =>
|
||||
handleAuthorizationQueryChange("keyword")(e.target.value)
|
||||
handleAuthorizationQueryChange("authorizationName")(
|
||||
e.target.value,
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
@@ -111,7 +113,7 @@ function ModulePage() {
|
||||
<h3 className="text-2xl font-medium text-label">모듈API 목록</h3>
|
||||
<Button onClick={() => router.push("/module/register")}>등록</Button>
|
||||
</div>
|
||||
<div className="card !m-[1.2rem] h-[49.5rem] overflow-auto !p-0">
|
||||
<div className="card !m-[1.2rem] h-[59rem] overflow-auto !p-0">
|
||||
<DataTable table={table} onRowClick={handleRowClick} viewPagination />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user