From 5c9ad9b7d96bbaf45625dae8d5814559c5730b18 Mon Sep 17 00:00:00 2001 From: bicochan Date: Mon, 14 Apr 2025 11:22:10 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EA=B2=8C=EC=8B=9C=ED=8C=90=20=EA=B4=80?= =?UTF-8?q?=EB=A6=AC=20=ED=8E=98=EC=9D=B4=EC=A7=80=20rewrites=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cs/app/(with-base-layout)/apiman/page.tsx | 5 - .../apiman/register/[id]/page.tsx | 12 - .../apiman/register/page.tsx | 4 - apps/cs/app/(with-base-layout)/group/page.tsx | 5 - .../group/register/[id]/page.tsx | 10 - .../group/register/page.tsx | 4 - apps/cs/next.config.ts | 13 +- apps/cs/src/pages/apiman/api/apiman-api.ts | 63 ----- apps/cs/src/pages/apiman/index.ts | 5 - .../apiman/model/apiman-table-columns.tsx | 111 -------- .../src/pages/apiman/ui/api-role-dialog.tsx | 201 -------------- apps/cs/src/pages/apiman/ui/apiman-form.tsx | 256 ----------------- apps/cs/src/pages/apiman/ui/apiman-page.tsx | 213 --------------- apps/cs/src/pages/apiman/ui/create-page.tsx | 76 ------ apps/cs/src/pages/apiman/ui/modify-page.tsx | 104 ------- apps/cs/src/pages/apirole/api/apirole-api.ts | 77 ------ apps/cs/src/pages/group/api/group-api.ts | 64 ----- apps/cs/src/pages/group/index.ts | 1 - .../pages/group/model/group-table-columns.tsx | 73 ----- apps/cs/src/pages/group/ui/create-page.tsx | 71 ----- apps/cs/src/pages/group/ui/group-form.tsx | 258 ------------------ apps/cs/src/pages/group/ui/group-page.tsx | 145 ---------- apps/cs/src/shared/config/env.ts | 3 - pnpm-lock.yaml | 141 +++++++++- pnpm-workspace.yaml | 1 + 25 files changed, 150 insertions(+), 1766 deletions(-) delete mode 100644 apps/cs/app/(with-base-layout)/apiman/page.tsx delete mode 100644 apps/cs/app/(with-base-layout)/apiman/register/[id]/page.tsx delete mode 100644 apps/cs/app/(with-base-layout)/apiman/register/page.tsx delete mode 100644 apps/cs/app/(with-base-layout)/group/page.tsx delete mode 100644 apps/cs/app/(with-base-layout)/group/register/[id]/page.tsx delete mode 100644 apps/cs/app/(with-base-layout)/group/register/page.tsx delete mode 100644 apps/cs/src/pages/apiman/api/apiman-api.ts delete mode 100644 apps/cs/src/pages/apiman/index.ts delete mode 100644 apps/cs/src/pages/apiman/model/apiman-table-columns.tsx delete mode 100644 apps/cs/src/pages/apiman/ui/api-role-dialog.tsx delete mode 100644 apps/cs/src/pages/apiman/ui/apiman-form.tsx delete mode 100644 apps/cs/src/pages/apiman/ui/apiman-page.tsx delete mode 100644 apps/cs/src/pages/apiman/ui/create-page.tsx delete mode 100644 apps/cs/src/pages/apiman/ui/modify-page.tsx delete mode 100644 apps/cs/src/pages/apirole/api/apirole-api.ts delete mode 100644 apps/cs/src/pages/group/api/group-api.ts delete mode 100644 apps/cs/src/pages/group/index.ts delete mode 100644 apps/cs/src/pages/group/model/group-table-columns.tsx delete mode 100644 apps/cs/src/pages/group/ui/create-page.tsx delete mode 100644 apps/cs/src/pages/group/ui/group-form.tsx delete mode 100644 apps/cs/src/pages/group/ui/group-page.tsx diff --git a/apps/cs/app/(with-base-layout)/apiman/page.tsx b/apps/cs/app/(with-base-layout)/apiman/page.tsx deleted file mode 100644 index 1e3b023df..000000000 --- a/apps/cs/app/(with-base-layout)/apiman/page.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import { ApimanPage } from "@/pages/apiman"; - -export default function Page() { - return ; -} diff --git a/apps/cs/app/(with-base-layout)/apiman/register/[id]/page.tsx b/apps/cs/app/(with-base-layout)/apiman/register/[id]/page.tsx deleted file mode 100644 index 6d382c878..000000000 --- a/apps/cs/app/(with-base-layout)/apiman/register/[id]/page.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { ModifyPage as VModifyPage } from "@/pages/apiman/ui/modify-page"; - - -export default async function ModifyPage({ - params, -}: { - params: Promise<{ id: number}>; -}) { - const { id } = await params; - return ; -} - \ No newline at end of file diff --git a/apps/cs/app/(with-base-layout)/apiman/register/page.tsx b/apps/cs/app/(with-base-layout)/apiman/register/page.tsx deleted file mode 100644 index cfd796314..000000000 --- a/apps/cs/app/(with-base-layout)/apiman/register/page.tsx +++ /dev/null @@ -1,4 +0,0 @@ -"use client"; - -import { CreatePage } from "@/pages/apiman/ui/create-page"; -export default CreatePage; diff --git a/apps/cs/app/(with-base-layout)/group/page.tsx b/apps/cs/app/(with-base-layout)/group/page.tsx deleted file mode 100644 index 97c32aeb7..000000000 --- a/apps/cs/app/(with-base-layout)/group/page.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import { GroupPage } from "@/pages/group"; - -export default function Page() { - return ; -} \ No newline at end of file diff --git a/apps/cs/app/(with-base-layout)/group/register/[id]/page.tsx b/apps/cs/app/(with-base-layout)/group/register/[id]/page.tsx deleted file mode 100644 index 9b77a8408..000000000 --- a/apps/cs/app/(with-base-layout)/group/register/[id]/page.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import { ModifyPage as VModifyPage } from "@/pages/group/ui/modify-page"; - -export default async function ModifyPage({ - params, -}: { - params: Promise<{ id: string }>; -}) { - const { id } = await params; - return ; -} diff --git a/apps/cs/app/(with-base-layout)/group/register/page.tsx b/apps/cs/app/(with-base-layout)/group/register/page.tsx deleted file mode 100644 index d1ed3f7a4..000000000 --- a/apps/cs/app/(with-base-layout)/group/register/page.tsx +++ /dev/null @@ -1,4 +0,0 @@ -"use client"; - -import { CreatePage } from "@/pages/group/ui/create-page"; -export default CreatePage; diff --git a/apps/cs/next.config.ts b/apps/cs/next.config.ts index cb651cdc0..c669bebf6 100644 --- a/apps/cs/next.config.ts +++ b/apps/cs/next.config.ts @@ -1,5 +1,16 @@ import type { NextConfig } from "next"; -const nextConfig: NextConfig = {}; +const subDomain = process.env.NEXT_PUBLIC_SUB_DOMAIN; + +const nextConfig: NextConfig = { + async rewrites() { + return [ + { + source: "/board/:path*", + destination: `${subDomain}/board/:path*`, + }, + ]; + }, +}; export default nextConfig; diff --git a/apps/cs/src/pages/apiman/api/apiman-api.ts b/apps/cs/src/pages/apiman/api/apiman-api.ts deleted file mode 100644 index ce9a8e189..000000000 --- a/apps/cs/src/pages/apiman/api/apiman-api.ts +++ /dev/null @@ -1,63 +0,0 @@ -import type { Page } from "@/shared/types"; -import { client } from "@/shared/api"; -import { ENDPOINT } from "@/shared/config"; - -export interface Api { - authorizationNo: number; // API 일련번호 - authorizationName: string; // API 명 - urlPatternValue: string; // URL 패턴 - httpMethodCode: string; // 하이퍼텍스트 전송 프로토콜 메쏘드 값 (예: GET, POST) - sortSeq: number; // 정렬 순서 - useYn: string; // 사용 여부 (Y/N) - regDt: string; // 등록 일시 - rgtr: string; // 등록자 UUID - mdfcnDt: string | null; // 갱신 일시 - mdfr: string | null; // 갱신자 UUID -} - -export interface ApiParams { - authorizationName?: string; // API 명 검색 - httpMethodCode?: string; // HTTP 메소드 검색 - useYn?: string; // 사용 여부 검색 - page?: number; // 페이지 번호 - size?: number; // 페이지 크기 -} - -export interface ApiFormData { - authorizationNo: number | null; // API 일련번호 (신규 등록 시 null) - authorizationName: string; // API 명 - urlPatternValue: string; // URL 패턴 - httpMethodCode: string; // HTTP 메소드 - sortSeq: number; // 정렬 순서 - useYn: string; // 사용 여부 -} - -export const ApimanApi = { - getApiList: async (params: ApiParams) => { - const { data } = await client.get>( - `${ENDPOINT.USER_SERVICE.AUTHRTS}`, - { params } - ); - return data; - }, - - getApi: async (authorizationNo: number) => { - const { data } = await client.get(`${ENDPOINT.USER_SERVICE.AUTHRTS}/${authorizationNo}`); - return data; - }, - - createApi: async (apiData: ApiFormData) => { - const { data } = await client.post(ENDPOINT.USER_SERVICE.AUTHRTS, apiData); - return data; - }, - - updateApi: async (authorizationNo: number, apiData: ApiFormData) => { - const { data } = await client.put(`${ENDPOINT.USER_SERVICE.AUTHRTS}/${authorizationNo}`, apiData); - return data; - }, - - deleteApi: async (authorizationNo: number) => { - const { data } = await client.delete(`${ENDPOINT.USER_SERVICE.AUTHRTS}/${authorizationNo}`); - return data; - }, -}; diff --git a/apps/cs/src/pages/apiman/index.ts b/apps/cs/src/pages/apiman/index.ts deleted file mode 100644 index 3d28d26f1..000000000 --- a/apps/cs/src/pages/apiman/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export { ApimanPage } from "./ui/apiman-page"; -export { ApimanForm } from "./ui/apiman-form"; -export { CreatePage } from "./ui/create-page"; -export { ModifyPage } from "./ui/modify-page"; -export { ApimanApi } from "./api/apiman-api"; diff --git a/apps/cs/src/pages/apiman/model/apiman-table-columns.tsx b/apps/cs/src/pages/apiman/model/apiman-table-columns.tsx deleted file mode 100644 index 22c0ba701..000000000 --- a/apps/cs/src/pages/apiman/model/apiman-table-columns.tsx +++ /dev/null @@ -1,111 +0,0 @@ -import { ColumnDef } from "@tanstack/react-table"; -import { Badge, Button } from "@common/components"; -import type { Api } from "../api/apiman-api"; -import dayjs from "dayjs"; - -// API 권한 관리를 위한 타입 정의 -type ApiTableMeta = { - openRoleDialog: (api: Api) => void; -}; - -export const columns: ColumnDef[] = [ - { - accessorKey: "authorizationNo", - header: "번호", - cell: ({ row }) =>
{row.original.authorizationNo}
, - }, - { - accessorKey: "authorizationName", - header: "API 명", - cell: ({ row }) =>
{row.original.authorizationName}
, - }, - { - accessorKey: "urlPatternValue", - header: "URL 패턴", - cell: ({ row }) => ( -
- {row.original.urlPatternValue} -
- ), - }, - { - accessorKey: "httpMethodCode", - header: "HTTP 메소드", - cell: ({ row }) => { - const method = row.original.httpMethodCode; - let color = "bg-gray-500"; - - switch (method) { - case "GET": - color = "bg-blue-500"; - break; - case "POST": - color = "bg-green-500"; - break; - case "PUT": - color = "bg-orange-500"; - break; - case "DELETE": - color = "bg-red-500"; - break; - } - - return ( - - {method} - - ); - }, - }, - { - accessorKey: "sortSeq", - header: "정렬 순서", - cell: ({ row }) =>
{row.original.sortSeq}
, - }, - { - accessorKey: "useYn", - header: "사용 여부", - cell: ({ row }) => { - const useYn = row.original.useYn; - return ( - - {useYn === "Y" ? "사용" : "미사용"} - - ); - }, - }, - { - accessorKey: "mdfrNm", - header: "수정자", - }, - { - accessorKey: "mdfcnDt", - header: "수정일시", - cell: ({ row }) => dayjs(row.original.mdfcnDt).format("YYYY-MM-DD"), - }, - { - id: "actions", - header: "권한", - cell: ({ row, table }) => { - // 메타 데이터에서 권한 다이얼로그 열기 함수 가져오기 - const meta = table.options.meta as ApiTableMeta | undefined; - - return ( - - ); - }, - }, -]; diff --git a/apps/cs/src/pages/apiman/ui/api-role-dialog.tsx b/apps/cs/src/pages/apiman/ui/api-role-dialog.tsx deleted file mode 100644 index 8c78fc5c0..000000000 --- a/apps/cs/src/pages/apiman/ui/api-role-dialog.tsx +++ /dev/null @@ -1,201 +0,0 @@ -"use client"; - -import { useState, useEffect } from "react"; -import { - Dialog, - DialogTrigger, - Button, - DialogContent, - DialogHeader, - DialogTitle, - Table, - TableBody, - TableCell, - TableHead, - TableHeader, - TableRow, - Input, - RadioGroup, - RadioGroupItem, - DialogFooter, - DialogClose, - Checkbox, - Label, -} from "@common/components"; -import { ApiRoleApi, type ApiRoleByApi } from "../../apirole/api/apirole-api"; - -// 페이지네이션 응답을 위한 인터페이스 -interface Page { - content: T[]; - pageable: { - pageNumber: number; - pageSize: number; - }; - totalElements: number; - totalPages: number; -} - -// API 역할 인터페이스 정의 -interface Role extends ApiRoleByApi { - selected?: boolean; -} - -interface ApiRoleDialogProps { - api: ApiRoleByApi | null; - isOpen: boolean; - onClose: () => void; - onSave: (roleIds: string[]) => Promise; -} - -export function ApiRoleDialog({ api, isOpen, onClose, onSave }: ApiRoleDialogProps): JSX.Element { - const [roles, setRoles] = useState([]); - const [loading, setLoading] = useState(false); - - // API에서 역할 데이터 가져오기 - useEffect(() => { - if (isOpen && api && api.authorizationNo) { - // 실제 API 호출로 데이터 가져오기 - ApiRoleApi.getApiRoleByApiList({ authorizationNo: api.authorizationNo }) - .then((data: Page) => { - // 데이터를 Role 인터페이스에 맞게 변환 - const rolesWithSelected = data.content.map(role => ({ - ...role, - mode: role.useYn ==null?"C":"R", - selected: role.useYn === "Y" - })); - setRoles(rolesWithSelected); - }) - .catch(error => { - console.error("역할 데이터 가져오기 오류:", error); - // 오류 발생 시 빈 배열 설정 - setRoles([]); - }); - } - }, [isOpen, api]); - - const handleToggleRole = (roleId: string) => { - setRoles( - roles.map((role) => - role.roleId === roleId ? { ...role, useYn: role.useYn === "Y" ? "N" : "Y", mode: role.mode === "R" ? "U" : "C" } : role - ) - ); - }; - - const handleSave = async () => { - try { - setLoading(true); - //const selectedRoleIds = roles.filter((role) => role.useYn === "Y").map((role) => role.roleId ?? ""); - await onSave(roles); - onClose(); - } catch (error) { - console.error("권한 저장 중 오류 발생:", error); - } finally { - setLoading(false); - } - }; - - // Dialog가 닫힐 때 호출되는 함수 - const handleOpenChange = (open: boolean) => { - if (!open) { - onClose(); - } - }; - - return ( - - - - - API 권한 설정 - {api?.authorizationName} - - - -
- - - - - - - - - - API 명 - - {api?.authorizationName || ""} - - HTTP 메소드 - - {api?.httpMethodCode || ""} - - - - URL 패턴 - - {api?.urlPatternValue || ""} - - - -
-
- -
- - - - 허용 - 권한 ID - 권한명 - 권한내용 - 사용여부 - - - - {roles.map((role) => ( - - - handleToggleRole(role.roleId)} - /> - - {role.roleId} - {role.roleName} - {role.roleContent} - - - {role.useYn === "Y" ? "사용" : "미사용"} - - - - ))} - {roles.length === 0 && ( - - - 권한 정보가 없습니다. - - - )} - -
-
- - - - - -
-
- ); -} diff --git a/apps/cs/src/pages/apiman/ui/apiman-form.tsx b/apps/cs/src/pages/apiman/ui/apiman-form.tsx deleted file mode 100644 index f27502f4e..000000000 --- a/apps/cs/src/pages/apiman/ui/apiman-form.tsx +++ /dev/null @@ -1,256 +0,0 @@ -// apps/cs/src/pages/apiman/ui/apiman-form.tsx -"use client"; - -import { useState } from "react"; -import { useRouter } from "next/navigation"; -import { useConfirm } from "@frontend-opensource/use-react-hooks"; -import { type UseFormReturn } from "react-hook-form"; -import { - Button, - Input, - Label, - RadioGroup, - RadioGroupItem, - Table, - TableBody, - TableCell, - TableHead, - TableRow, - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from "@common/components"; -import { FormItem, FormControl, FormField, Form } from "@/shared/ui/form"; -import type { ApiFormData } from "../api/apiman-api"; -import { ConfirmDialog } from "@/shared/ui/confirm-dialog"; - -interface ApimanFormProps { - form: UseFormReturn; - authorizationNo?: number; - handleSave: (data: ApiFormData) => Promise; - handleDelete?: () => Promise; -} - -function ApimanForm({ form, authorizationNo, handleSave, handleDelete }: ApimanFormProps) { - const isModifyMode = !!authorizationNo; - const router = useRouter(); - const { confirm } = useConfirm(); - const [onConfirm, setOnConfirm] = useState(false); - - const handleConfirm = async (callback: () => Promise) => { - setOnConfirm(true); - await callback(); - setOnConfirm(false); - }; - - const onSubmit = async (data: ApiFormData) => { - const confirmMessage = isModifyMode - ? "수정하시겠습니까?" - : "저장하시겠습니까?"; - - await handleConfirm(async () => { - if (await confirm(confirmMessage)) { - await handleSave(data); - } - }); - }; - - const onDelete = async () => { - await handleConfirm(async () => { - if (await confirm("삭제하시겠습니까?")) { - handleDelete?.(); - } - }); - }; - - return ( - <> -
- -
- - - - - - - {isModifyMode && ( - - API 일련번호 - - ( - - - - - - )} - /> - - - )} - - API 명 - - ( - - - - - - )} - /> - - - - URL 패턴 - - ( - - - - - - )} - /> - - - - 요청 메소드 - - ( - - - - - - )} - /> - - - - 정렬 순서 - - ( - - - field.onChange(parseInt(e.target.value) || 0)} - /> - - - )} - /> - - - - 사용 여부 - - ( - - - -
- - -
-
- - -
-
-
-
- )} - /> -
-
-
-
-
-
- - - {isModifyMode && ( - - )} -
-
- - - - ); -} - -export { ApimanForm }; diff --git a/apps/cs/src/pages/apiman/ui/apiman-page.tsx b/apps/cs/src/pages/apiman/ui/apiman-page.tsx deleted file mode 100644 index fb0b82511..000000000 --- a/apps/cs/src/pages/apiman/ui/apiman-page.tsx +++ /dev/null @@ -1,213 +0,0 @@ -"use client"; -import "@common/assets/styles/grid.css"; -import { useRouter } from "next/navigation"; -import { useEffect, useState } from "react"; -import { useQuery } from "@tanstack/react-query"; -import { - getCoreRowModel, - getPaginationRowModel, - useReactTable -} from "@tanstack/react-table"; -import { - Button, - DataTable, - Input, - Label, - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, - Pagination -} from "@common/components"; - -import { ApimanApi, type Api, type ApiParams } from "../api/apiman-api"; -import { type ApiRoleByApi } from "../../apirole/api/apirole-api"; -import { ENDPOINT } from "@/shared/config"; -import { columns } from "../model/apiman-table-columns"; -import { ApiRoleDialog } from "./api-role-dialog"; - -function ApimanPage() { - const router = useRouter(); - const [apiQuery, setApiQuery] = useState({ - authorizationName: "", - httpMethodCode: "", - useYn: "", - page: 0, - size: 10, - }); - - // API 역할 다이얼로그 상태 관리 - const [apiRoleDialog, setApiRoleDialog] = useState<{ - isOpen: boolean; - api: ApiRoleByApi | null; - }>({ - isOpen: false, - api: null, - }); - - const { data: apiList, refetch, isLoading } = useQuery({ - queryKey: [ENDPOINT.USER_SERVICE.AUTHRTS, apiQuery], - queryFn: () => ApimanApi.getApiList(apiQuery), - enabled: false, - }); - - const table = useReactTable({ - data: apiList?.content ?? [], - columns, - getCoreRowModel: getCoreRowModel(), - getPaginationRowModel: getPaginationRowModel(), - pageCount: apiList?.totalPages ?? -1, - state: { - pagination: { - pageIndex: apiQuery.page ?? 0, - pageSize: apiQuery.size ?? 10, - }, - }, - meta: { - openRoleDialog: (api: ApiRoleByApi) => { - setApiRoleDialog({ - isOpen: true, - api, - }); - }, - }, - onPaginationChange: (updater) => { - const newPagination = - typeof updater === "function" - ? updater({ pageIndex: apiQuery.page ?? 0, pageSize: apiQuery.size ?? 10 }) - : updater; - - setApiQuery((prev) => ({ - ...prev, - page: newPagination.pageIndex, - size: newPagination.pageSize, - })); - }, - manualPagination: true, - }); - - useEffect(() => { - refetch(); - }, [apiQuery, refetch]); - - const handleSubmit = (e: React.FormEvent) => { - e.preventDefault(); - setApiQuery(prev => ({ ...prev, page: 0 })); - refetch(); - }; - - - const handleRowClick = (api: Api) => { - router.push(`/apiman/register/${api.authorizationNo}`); - }; - - // API 역할 저장 핸들러 - const handleSaveRoles = async (roles: ApiRoleByApi[]) => { - try { - // 실제 구현에서는 API 호출로 대체 - console.log(`API ${apiRoleDialog.api?.authorizationNo}에 권한 저장:`, roles); - // 성공 시 다이얼로그 닫기 - setApiRoleDialog({ isOpen: false, api: null }); - // 목록 새로고침 - refetch(); - } catch (error) { - console.error("권한 저장 중 오류 발생:", error); - } - }; - - return ( -
- {/* API 역할 다이얼로그 */} - setApiRoleDialog({ isOpen: false, api: null })} - onSave={handleSaveRoles} - /> - -
-
- - - - - setApiQuery( prev => ({ ...prev, authorizationName: e.target.value }))} - placeholder="API 명 입력" - /> - -
-
- - - -
-
-

모듈API 목록

- -
- - - -
-
- 총 {apiList?.totalElements ?? 0} 건 -
- - setApiQuery(prev => ({ ...prev, page: page - 1 })) - } - /> - -
-
-
- ); -} - -export { ApimanPage }; diff --git a/apps/cs/src/pages/apiman/ui/create-page.tsx b/apps/cs/src/pages/apiman/ui/create-page.tsx deleted file mode 100644 index 69f774765..000000000 --- a/apps/cs/src/pages/apiman/ui/create-page.tsx +++ /dev/null @@ -1,76 +0,0 @@ -"use client"; - -import { useRouter } from "next/navigation"; -import { useForm } from "react-hook-form"; -import { zodResolver } from "@hookform/resolvers/zod"; -import { useMutation, useQueryClient } from "@tanstack/react-query"; -import { ApimanApi, type ApiFormData } from "../api/apiman-api"; -import { ENDPOINT } from "@/shared/config"; -import { useAlertStore } from "@/shared/lib/use-alert-store"; -import { ApimanForm } from "./apiman-form"; -import { z } from "zod"; -import { AxiosError } from "axios"; - -// API 스키마 정의 -const apiFormSchema = z.object({ - authorizationNo: z.number().nullable(), - authorizationName: z.string().min(1, "API 명을 입력해주세요"), - urlPatternValue: z.string().min(1, "URL 패턴을 입력해주세요"), - httpMethodCode: z.string().min(1, "HTTP 메소드를 선택해주세요"), - sortSeq: z.number().min(0, "정렬 순서는 0 이상이어야 합니다"), - useYn: z.string(), -}); - -function CreatePage() { - const router = useRouter(); - const queryClient = useQueryClient(); - const { setMessage: alert } = useAlertStore((state) => state); - - const { mutateAsync: createApi } = useMutation({ - mutationFn: (data: ApiFormData) => ApimanApi.createApi(data), - onSuccess: () => { - alert("등록되었습니다.", () => { - queryClient.invalidateQueries({ - queryKey: [ENDPOINT.USER_SERVICE.AUTHRTS], - }); - router.push("/apiman"); - }); - }, - onError: (error: unknown) => { - const axiosError = error as AxiosError<{ message: string }>; - if (axiosError.response?.data) { - alert(axiosError.response.data.message); - } else if (error instanceof Error) { - alert(error.message); - } else { - alert("알 수 없는 오류가 발생했습니다."); - } - }, - }); - - const form = useForm({ - resolver: zodResolver(apiFormSchema), - defaultValues: { - authorizationNo: null, - authorizationName: "", - urlPatternValue: "", - httpMethodCode: "", - sortSeq: 0, - useYn: "Y" - } - }); - - return ( -
-
-

API 등록

-
- -
- ); -} - -export { CreatePage }; diff --git a/apps/cs/src/pages/apiman/ui/modify-page.tsx b/apps/cs/src/pages/apiman/ui/modify-page.tsx deleted file mode 100644 index a6185e8d0..000000000 --- a/apps/cs/src/pages/apiman/ui/modify-page.tsx +++ /dev/null @@ -1,104 +0,0 @@ -"use client"; - -import { useRouter } from "next/navigation"; -import { useForm } from "react-hook-form"; -import { zodResolver } from "@hookform/resolvers/zod"; -import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; -import { ApimanApi, type ApiFormData } from "../api/apiman-api"; -import { ENDPOINT } from "@/shared/config"; -import { useAlertStore } from "@/shared/lib/use-alert-store"; -import { ApimanForm } from "./apiman-form"; -import { z } from "zod"; -import { AxiosError } from "axios"; - -// API 스키마 정의 -const apiFormSchema = z.object({ - authorizationNo: z.number().nullable(), - authorizationName: z.string().min(1, "API 명을 입력해주세요"), - urlPatternValue: z.string().min(1, "URL 패턴을 입력해주세요"), - httpMethodCode: z.string().min(1, "HTTP 메소드를 선택해주세요"), - sortSeq: z.number(), - useYn: z.string(), -}); - -function ModifyPage({ authorizationNo }: { authorizationNo: number }) { - const router = useRouter(); - const queryClient = useQueryClient(); - const { setMessage: alert } = useAlertStore((state) => state); - - const { data: apiDetail } = useQuery({ - queryKey: [ENDPOINT.USER_SERVICE.AUTHRTS, authorizationNo], - queryFn: () => ApimanApi.getApi(authorizationNo), - select: (data) => { - const keys = Object.keys(apiFormSchema.shape); - const filteredData = Object.fromEntries( - Object.entries(data).filter(([key]) => keys.includes(key)), - ); - return filteredData; - }, - enabled: !!authorizationNo, - }); - - const { mutateAsync: updateApi } = useMutation({ - mutationFn: (data: ApiFormData) => ApimanApi.updateApi(authorizationNo, data), - onSuccess: () => { - alert("수정되었습니다.", () => { - queryClient.invalidateQueries({ - queryKey: [ENDPOINT.USER_SERVICE.AUTHRTS], - }); - router.back(); - }); - }, - onError: (error: unknown) => { - const axiosError = error as AxiosError<{ message: string }>; - if (axiosError.response?.data) { - alert(axiosError.response.data.message); - } else if (error instanceof Error) { - alert(error.message); - } else { - alert("알 수 없는 오류가 발생했습니다."); - } - }, - }); - - const { mutateAsync: deleteApi } = useMutation({ - mutationFn: () => ApimanApi.deleteApi(authorizationNo), - onSuccess: () => { - alert("삭제되었습니다.", router.back); - }, - onError: (error: unknown) => { - const axiosError = error as AxiosError<{ message: string }>; - if (axiosError.response?.data) { - alert(axiosError.response.data.message); - } else if (error instanceof Error) { - alert(error.message); - } else { - alert("알 수 없는 오류가 발생했습니다."); - } - }, - }); - - const form = useForm({ - resolver: zodResolver(apiFormSchema), - values: apiDetail as ApiFormData, - }); - - return ( -
-
-

API 수정

-
- { - await updateApi(data); - return; - }} - handleDelete={deleteApi} - /> -
- ); -} - -export { ModifyPage }; diff --git a/apps/cs/src/pages/apirole/api/apirole-api.ts b/apps/cs/src/pages/apirole/api/apirole-api.ts deleted file mode 100644 index c525c9a6a..000000000 --- a/apps/cs/src/pages/apirole/api/apirole-api.ts +++ /dev/null @@ -1,77 +0,0 @@ -import type { Page } from "@/shared/types"; -import { client } from "@/shared/api"; -import { ENDPOINT } from "@/shared/config"; - -export interface ApiRole { - roleId?: string; - /** @format int64 */ - authorizationNo?: number; - authorizationName?: string; - urlPatternValue?: string; - httpMethodCode?: string; - /** @format int32 */ - sortSeq?: number; - createdAt?: boolean; -} -/** API 에서 역할 추가 (API에 대한 역할) */ -export interface ApiRoleByApi { - roleId?: string; - roleName?: string; - roleContent?: string; - useYn?: string; - /** @format int64 */ - authorizationNo?: number; - mode?:string; -} - -export interface ApiRoleParams { - authorizationNo?: number; // API 일련번호 검색 - roleId?: string; // API 역할 검색 - page?: number; // 페이지 번호 - size?: number; // 페이지 크기 -} - -export interface ApiRoleFormData { - authorizationNo: number | null; // API 일련번호 (신규 등록 시 null) - authorizationName: string; // API 명 - urlPatternValue: string; // URL 패턴 - httpMethodCode: string; // HTTP 메소드 - sortSeq: number; // 정렬 순서 - useYn: string; // 사용 여부 -} - -export const ApiRoleApi = { - getApiRoleList: async (params: ApiRoleParams) => { - const { data } = await client.get>( - `${ENDPOINT.USER_SERVICE.ROLES_AUTHRTS}`, - { params } - ); - return data; - }, - getApiRoleByApiList: async (params: ApiRoleParams) => { - const { data } = await client.get>( - `${ENDPOINT.USER_SERVICE.ROLES_AUTHRTS}/api`, - { params } - ); - return data; - }, - getApiRole: async (authorizationNo: number) => { - const { data } = await client.get(`${ENDPOINT.USER_SERVICE.ROLES_AUTHRTS}/${authorizationNo}`); - return data; - }, - - createApiRole: async (apiData: ApiRoleFormData) => { - const { data } = await client.post(ENDPOINT.USER_SERVICE.ROLES_AUTHRTS, apiData); - return data; - }, - - updateApiRole: async (authorizationNo: number, apiData: ApiRoleFormData) => { - const { data } = await client.put(`${ENDPOINT.USER_SERVICE.ROLES_AUTHRTS}/${authorizationNo}`, apiData); - return data; - }, - - deleteApiRole: async (authorizationNo: number) => { - const { data } = await client.delete(`${ENDPOINT.USER_SERVICE.ROLES_AUTHRTS}/${authorizationNo}`); - return data; - }, -}; diff --git a/apps/cs/src/pages/group/api/group-api.ts b/apps/cs/src/pages/group/api/group-api.ts deleted file mode 100644 index ffffa958d..000000000 --- a/apps/cs/src/pages/group/api/group-api.ts +++ /dev/null @@ -1,64 +0,0 @@ -//import { http } from "@/libs/axios"; -import type { Page } from "@/shared/types"; -import { client } from "@/shared/api"; -import { ENDPOINT } from "@/shared/config"; - -export interface Group { - groupId: string; - groupNm: string; - groupSeCd: string; - groupExpln: string; - delYn: string; - regDt: string; - rgtr: string; - mdfcnDt: string | null; - mdfr: string | null; - authrtId: string; - siteId: string | null; -} - -export interface GroupParams { - groupNm?: string; - groupSeCd?: string; - siteId?: string; -} - -export interface GroupFormData { - groupId: string; - groupNm: string; - groupSeCd: string; - groupExpln: string; - delYn: string; - authrtId: string; - siteId: string; -} - - -export const GroupApi = { - getGroupList: async (params: GroupParams) => { - const { data } = await client.get>( - `${ENDPOINT.CMS_SERVICE.GROUP}` - , { params }); - return data; - }, - - getGroup: async (groupId: string) => { - const { data } = await client.get(`${ENDPOINT.CMS_SERVICE.GROUP}/${groupId}`); - return data; - }, - - createGroup: async (groupData: GroupFormData) => { - const { data } = await client.post(ENDPOINT.CMS_SERVICE.GROUP, groupData); - return data; - }, - - updateGroup: async (groupId: string, groupData: GroupFormData) => { - const { data } = await client.put(`${ENDPOINT.CMS_SERVICE.GROUP}/${groupId}`, groupData); - return data; - }, - - deleteGroup: async (groupId: string) => { - const { data } = await client.delete(`${ENDPOINT.CMS_SERVICE.GROUP}/${groupId}`); - return data; - }, -}; \ No newline at end of file diff --git a/apps/cs/src/pages/group/index.ts b/apps/cs/src/pages/group/index.ts deleted file mode 100644 index 8ba97789f..000000000 --- a/apps/cs/src/pages/group/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { GroupPage } from "./ui/group-page"; \ No newline at end of file diff --git a/apps/cs/src/pages/group/model/group-table-columns.tsx b/apps/cs/src/pages/group/model/group-table-columns.tsx deleted file mode 100644 index cd12ef6e8..000000000 --- a/apps/cs/src/pages/group/model/group-table-columns.tsx +++ /dev/null @@ -1,73 +0,0 @@ -import { type ColumnDef } from "@tanstack/react-table"; -import { Checkbox } from "@common/components/ui"; -import { type Group } from "../api/group-api"; -import dayjs from "dayjs"; - -export const columns: ColumnDef[] = [ - /* { - id: "select", - header: ({ table }) => ( - table.toggleAllPageRowsSelected(!!value)} - aria-label="전체 선택" - /> - ), - cell: ({ row }) => ( - row.toggleSelected(!!value)} - aria-label="행 선택" - /> - ), - enableSorting: false, - enableHiding: false, - }, */ - { - id: "no", - header: "NO", - accessorFn: (_, index) => index + 1, - }, - { - accessorKey: "groupId", - header: "그룹 ID", - enableSorting: true, - }, - { - accessorKey: "groupNm", - header: "그룹명", - }, - { - accessorKey: "groupSeNm", - header: "그룹구분", - }, - { - accessorKey: "delYn", - header: "삭제여부", - cell: ({ row }) => ( - - ) - }, - { - accessorKey: "siteId", - header: "사이트 ID", - enableSorting: true, - }, - { - accessorKey: "roleNm", - header: "권한", - }, - { - accessorKey: "mdfrNm", - header: "수정자", - }, - { - accessorKey: "mdfcnDt", - header: "수정일시", - cell: ({ row }) => dayjs(row.original.mdfcnDt).format("YYYY-MM-DD"), - } -]; \ No newline at end of file diff --git a/apps/cs/src/pages/group/ui/create-page.tsx b/apps/cs/src/pages/group/ui/create-page.tsx deleted file mode 100644 index 1970147dd..000000000 --- a/apps/cs/src/pages/group/ui/create-page.tsx +++ /dev/null @@ -1,71 +0,0 @@ -// apps/cs/src/pages/group/ui/create-page.tsx -"use client"; - -import { useRouter } from "next/navigation"; -import { useForm } from "react-hook-form"; -import { useMutation } from "@tanstack/react-query"; -import { zodResolver } from "@hookform/resolvers/zod"; -import { GroupApi, type GroupFormData } from "../api/group-api"; -import { useAlertStore } from "@/shared/lib/use-alert-store"; -import { GroupForm } from "./group-form"; -import { z } from "zod"; - -const groupFormSchema = z.object({ - groupId: z.string(), - groupNm: z.string().min(1, "그룹명을 입력해주세요"), - groupSeCd: z.string().min(1, "그룹구분을 선택해주세요"), - groupExpln: z.string(), - delYn: z.string(), - authrtId: z.string(), - siteId: z.string(), -}); - -function CreatePage() { - const router = useRouter(); - const { setMessage: alert } = useAlertStore((state) => state); - - const { mutateAsync: createGroup } = useMutation({ - mutationFn: (data: GroupFormData) => GroupApi.createGroup(data), - onSuccess: () => { - alert("등록되었습니다.", router.back); - }, - onError: (error) => { - /*{ - "timestamp": "2025-04-07T14:30:15.471581", - "message": "해당 권한이 존재하지 않습니다. ID = sd", - "status": 400, - "code": "B001", - "errors": [] - }*/ - if(error.response.data){ - alert(error.response.data.message); - }else{ - alert(error.message); - } - }, - }); - - const form = useForm({ - resolver: zodResolver(groupFormSchema), - defaultValues: { - groupId: "", - groupNm: "", - groupSeCd: "", - groupExpln: "", - delYn: "N", - authrtId: "", - siteId: "", - }, - }); - - return ( -
-
-

그룹 등록

-
- -
- ); -} - -export { CreatePage }; \ No newline at end of file diff --git a/apps/cs/src/pages/group/ui/group-form.tsx b/apps/cs/src/pages/group/ui/group-form.tsx deleted file mode 100644 index 2a88a0bd7..000000000 --- a/apps/cs/src/pages/group/ui/group-form.tsx +++ /dev/null @@ -1,258 +0,0 @@ -// apps/cs/src/pages/group/ui/group-form.tsx -"use client"; - -import { useState } from "react"; -import { useRouter } from "next/navigation"; -import { useConfirm } from "@frontend-opensource/use-react-hooks"; -import { type UseFormReturn } from "react-hook-form"; -import { - Button, - Input, - Label, - RadioGroup, - RadioGroupItem, - Table, - TableBody, - TableCell, - TableHead, - TableRow, -} from "@common/components"; -import { CodeSelect } from "@/entities/code"; -import { FormItem, FormControl, FormField, Form } from "@/shared/ui/form"; -import type { GroupFormData } from "../api/group-api"; -import { ConfirmDialog } from "@/shared/ui/confirm-dialog"; - -interface GroupFormProps { - form: UseFormReturn; - groupId?: string; - handleSave: (data: GroupFormData) => Promise; - handleDelete?: () => Promise; -} - -function GroupForm({ form, groupId, handleSave, handleDelete }: GroupFormProps) { - const isModifyMode = !!groupId; - const router = useRouter(); - const { confirm } = useConfirm(); - const [onConfirm, setOnConfirm] = useState(false); - - const handleConfirm = async (callback: () => Promise) => { - setOnConfirm(true); - await callback(); - setOnConfirm(false); - }; - - const onSubmit = async (data: GroupFormData) => { - const confirmMessage = isModifyMode - ? "수정하시겠습니까?" - : "저장하시겠습니까?"; - - await handleConfirm(async () => { - if (await confirm(confirmMessage)) { - handleSave(data); - } - }); - }; - - const onDelete = async () => { - await handleConfirm(async () => { - if (await confirm("삭제하시겠습니까?")) { - handleDelete?.(); - } - }); - }; - - return ( - <> -
- -
- - - - - - - - 그룹 ID - - ( - - - - - - )} - /> - - - - 그룹명 - - ( - - - - - - )} - /> - - - - 그룹구분 - - ( - - - - - - )} - /> - - - - 그룹설명 - - ( - - - - - - )} - /> - - - - 사이트 ID - - ( - - - - - - )} - /> - - - - 권한 ID - - ( - - - - - - )} - /> - - - - 삭제여부 - - ( - - - -
- - -
-
- - -
-
-
-
- )} - /> -
-
-
-
-
-
- - - {isModifyMode && ( - - )} -
-
- - - - ); -} - -export { GroupForm }; \ No newline at end of file diff --git a/apps/cs/src/pages/group/ui/group-page.tsx b/apps/cs/src/pages/group/ui/group-page.tsx deleted file mode 100644 index 99459c185..000000000 --- a/apps/cs/src/pages/group/ui/group-page.tsx +++ /dev/null @@ -1,145 +0,0 @@ -"use client"; -import "@common/assets/styles/grid.css"; -import { useRouter } from "next/navigation"; -import { useEffect, useState } from "react"; -import { useQuery } from "@tanstack/react-query"; -import { - getCoreRowModel, - getPaginationRowModel, - useReactTable -} from "@tanstack/react-table"; -import { - Button, - DataTable, - Input, - Label, - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, - Pagination -} from "@common/components"; - -import { GroupApi, type Group, type GroupParams } from "../api/group-api"; -import { ENDPOINT } from "@/shared/config"; -import { columns } from "../model/group-table-columns"; - -function GroupPage() { - const router = useRouter(); - const [groupQuery, setGroupQuery] = useState({ - groupNm: "", - groupSeCd: "", - page: 0, - size: 2, - }); - - const { data: groupList, refetch } = useQuery({ - queryKey: [ENDPOINT.CMS_SERVICE.GROUP, groupQuery], - queryFn: () => GroupApi.getGroupList(groupQuery), - enabled: false, - }); - - const table = useReactTable({ - data: groupList?.content ?? [], - columns, - getCoreRowModel: getCoreRowModel(), - getPaginationRowModel: getPaginationRowModel(), - pageCount: groupList?.totalPages ?? -1, - state: { - pagination: { - pageIndex: groupQuery.page, - pageSize: groupQuery.size, - }, - }, - onPaginationChange: (updater) => { - if (typeof updater === 'function') { - const newPagination = updater({ - pageIndex: groupQuery.page, - pageSize: groupQuery.size, - }); - setGroupQuery(prev => ({ - ...prev, - page: newPagination.pageIndex, - size: newPagination.pageSize, - })); - } - }, - manualPagination: true, - }); - - const handleSubmit = (e: React.FormEvent) => { - e.preventDefault(); - setGroupQuery(prev => ({ ...prev, page: 0 })); // 검색 시 첫 페이지로 이동 - refetch(); - }; - - const handleRowClick = (row: Group) => { - router.push(`/group/register/${row.groupId}`); - }; - - useEffect(() => { - refetch(); - }, [groupQuery, refetch]); //[groupQuery.page, groupQuery.size]); // 페이지나 사이즈 변경 시 자동 조회 - - return ( -
-
-
- - setGroupQuery(prev => ({ ...prev, groupNm: e.target.value }))} - /> - - -
-
-
-
-

그룹 목록

- -
-
- -
-
- 총 {groupList?.totalElements ?? 0} 건 -
- - setGroupQuery(prev => ({ ...prev, page: page - 1 })) - } - /> - -
-
-
-
- ); -} - -export { GroupPage }; \ No newline at end of file diff --git a/apps/cs/src/shared/config/env.ts b/apps/cs/src/shared/config/env.ts index f0b4c83b1..a36a8ad65 100644 --- a/apps/cs/src/shared/config/env.ts +++ b/apps/cs/src/shared/config/env.ts @@ -1,10 +1,7 @@ export const PORT = process.env.NEXT_PUBLIC_PORT || "3000"; export const PROXY_HOST = process.env.NEXT_PUBLIC_PROXY_HOST || `http://localhost:${PORT}`; - -export const SERVER_API_URL = process.env.NEXT_PUBLIC_SERVER_API_URL; export const SITE_ID = process.env.NEXT_PUBLIC_SITE_ID || "CS"; - export const CLAIM_NAME = process.env.NEXT_PUBLIC_CLAIM_NAME || "Authorization"; export const ACCESS_TOKEN = process.env.NEXT_PUBLIC_ACCESS_TOKEN || "access-token"; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 69ed7d939..c9b665bf9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -37,6 +37,115 @@ importers: specifier: 2.4.2 version: 2.4.2 + apps/common/board: + dependencies: + '@common/assets': + specifier: workspace:* + version: link:../../../packages/common/assets + '@common/components': + specifier: workspace:* + version: link:../../../packages/common/components + '@frontend-opensource/use-react-hooks': + specifier: ^1.1.4 + version: 1.1.4 + '@hookform/resolvers': + specifier: ^4.1.3 + version: 4.1.3(react-hook-form@7.54.2) + '@minoru/react-dnd-treeview': + specifier: ^3.5.0 + version: 3.5.0(dnd-core@16.0.1)(react-dnd@16.0.1)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-label': + specifier: ^2.1.2 + version: 2.1.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-slot': + specifier: ^1.1.2 + version: 1.1.2(@types/react@18.3.18)(react@18.3.1) + '@tanstack/react-query': + specifier: ^5.67.1 + version: 5.67.1(react@18.3.1) + '@tanstack/react-table': + specifier: ^8.21.2 + version: 8.21.2(react-dom@18.3.1)(react@18.3.1) + '@tinymce/tinymce-react': + specifier: ^6.1.0 + version: 6.1.0(react-dom@18.3.1)(react@18.3.1) + axios: + specifier: ^1.8.1 + version: 1.8.1 + chart.js: + specifier: ^4.4.8 + version: 4.4.8 + dayjs: + specifier: ^1.11.13 + version: 1.11.13 + js-cookie: + specifier: ^3.0.5 + version: 3.0.5 + next: + specifier: 15.1.7 + version: 15.1.7(react-dom@18.3.1)(react@18.3.1) + react-chartjs-2: + specifier: ^5.3.0 + version: 5.3.0(chart.js@4.4.8)(react@18.3.1) + react-dnd: + specifier: ^16.0.1 + version: 16.0.1(@types/node@22.13.9)(@types/react@18.3.18)(react@18.3.1) + react-hook-form: + specifier: ^7.54.2 + version: 7.54.2(react@18.3.1) + tailwindcss-animate: + specifier: ^1.0.7 + version: 1.0.7(tailwindcss@3.4.17) + tus-js-client: + specifier: ^4.3.1 + version: 4.3.1 + zod: + specifier: ^3.24.2 + version: 3.24.2 + zustand: + specifier: ^5.0.3 + version: 5.0.3(@types/react@18.3.18)(react@18.3.1) + devDependencies: + '@eslint/eslintrc': + specifier: ^3 + version: 3.3.0 + '@faker-js/faker': + specifier: ^9.5.0 + version: 9.5.0 + '@types/js-cookie': + specifier: ^3.0.6 + version: 3.0.6 + '@types/node': + specifier: ^22.13.1 + version: 22.13.9 + '@types/webpack': + specifier: ^5.28.5 + version: 5.28.5 + eslint: + specifier: ^9 + version: 9.21.0 + eslint-config-next: + specifier: 15.1.7 + version: 15.1.7(eslint@9.21.0)(typescript@5.6.3) + postcss: + specifier: ^8 + version: 8.5.3 + prettier: + specifier: ^3.4.2 + version: 3.5.2 + prettier-plugin-tailwindcss: + specifier: ^0.6.11 + version: 0.6.11(prettier@3.5.2) + steiger: + specifier: ^0.5.5 + version: 0.5.5(typescript@5.6.3) + tailwindcss: + specifier: ^3.4.1 + version: 3.4.17 + typescript: + specifier: ^5 + version: 5.6.3 + apps/cs: dependencies: '@common/assets': @@ -1700,7 +1809,7 @@ packages: dnd-multi-backend: 8.1.2(dnd-core@16.0.1) framer-motion: 11.18.2(react-dom@18.3.1)(react@18.3.1) react: 18.3.1 - react-dnd: 16.0.1(@types/node@22.13.5)(@types/react@18.3.18)(react@18.3.1) + react-dnd: 16.0.1(@types/node@22.13.9)(@types/react@18.3.18)(react@18.3.1) react-dnd-html5-backend: 16.0.1 react-dnd-touch-backend: 16.0.1 react-dom: 18.3.1(react@18.3.1) @@ -3508,7 +3617,6 @@ packages: resolution: {integrity: sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw==} dependencies: undici-types: 6.20.0 - dev: true /@types/prop-types@15.7.14: resolution: {integrity: sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==} @@ -3537,7 +3645,7 @@ packages: /@types/webpack@5.28.5: resolution: {integrity: sha512-wR87cgvxj3p6D0Crt1r5avwqffqPXUkNlnQ1mjU93G7gCuFjufZR4I6j8cz5g1F1tTYpfOOFvly+cmIQwL9wvw==} dependencies: - '@types/node': 22.13.5 + '@types/node': 22.13.9 tapable: 2.2.1 webpack: 5.98.0 transitivePeerDependencies: @@ -6178,7 +6286,7 @@ packages: resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} engines: {node: '>= 10.13.0'} dependencies: - '@types/node': 22.13.5 + '@types/node': 22.13.9 merge-stream: 2.0.0 supports-color: 8.1.1 dev: true @@ -7138,6 +7246,31 @@ packages: react: 18.3.1 dev: false + /react-dnd@16.0.1(@types/node@22.13.9)(@types/react@18.3.18)(react@18.3.1): + resolution: {integrity: sha512-QeoM/i73HHu2XF9aKksIUuamHPDvRglEwdHL4jsp784BgUuWcg6mzfxT0QDdQz8Wj0qyRKx2eMg8iZtWvU4E2Q==} + peerDependencies: + '@types/hoist-non-react-statics': '>= 3.3.1' + '@types/node': '>= 12' + '@types/react': ^18.3.18 + react: ^18.3.1 + peerDependenciesMeta: + '@types/hoist-non-react-statics': + optional: true + '@types/node': + optional: true + '@types/react': + optional: true + dependencies: + '@react-dnd/invariant': 4.0.2 + '@react-dnd/shallowequal': 4.0.2 + '@types/node': 22.13.9 + '@types/react': 18.3.18 + dnd-core: 16.0.1 + fast-deep-equal: 3.1.3 + hoist-non-react-statics: 3.3.2 + react: 18.3.1 + dev: false + /react-docgen-typescript@2.2.2(typescript@5.6.3): resolution: {integrity: sha512-tvg2ZtOpOi6QDwsb3GZhOjDkkX0h8Z2gipvTg6OVMUyoYoURhEiRNePT8NZItTVCDh39JJHnLdfCOkzoLbFnTg==} peerDependencies: diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index e6a13a3cc..56de4568f 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,4 +1,5 @@ packages: - "apps/*" + - "apps/common/*" - "packages/*" - "packages/common/*"