From 4924fbe71de6c57516c434a73fedaaf799b1a81c Mon Sep 17 00:00:00 2001 From: kjs Date: Thu, 30 Oct 2025 17:02:30 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=ED=85=8C=EC=9D=B4=EB=B8=94=20=ED=83=80?= =?UTF-8?q?=EC=9E=85=20=EA=B4=80=EB=A6=AC=20=ED=8E=98=EC=9D=B4=EC=A7=80=20?= =?UTF-8?q?UI=20=EA=B0=9C=EC=84=A0=20=EB=B0=8F=20=ED=85=8C=EC=9D=B4?= =?UTF-8?q?=EB=B8=94=20=EC=82=AD=EC=A0=9C=20=EB=B0=A9=EC=8B=9D=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 테이블 삭제 방식을 체크박스 선택 기반 일괄 삭제로 변경 - 좌측 테이블 리스트 영역에 스크롤 적용 - 선택된 테이블에 검정 테두리 표시 (border-2 border-black) - 우측 상단 타이틀 제거 - 각 테이블 카드에 라운딩 적용 (rounded-lg) - 컬럼 간 간격 개선 (입력 타입-상세 설정 간격 증가) - Entity 설정 박스 스타일 제거 (평면적 레이아웃으로 변경) - 좌측 영역 우측 여백 조정 (pr-4) --- .../(main)/admin/batch-management/page.tsx | 16 +- .../admin/collection-management/page.tsx | 34 +- .../admin/external-connections/page.tsx | 40 +- frontend/app/(main)/admin/standards/page.tsx | 22 +- frontend/app/(main)/admin/tableMng/page.tsx | 437 +++++++++++++----- frontend/app/(main)/admin/templates/page.tsx | 46 +- frontend/components/admin/CompanyTable.tsx | 24 +- frontend/components/admin/UserTable.tsx | 34 +- frontend/components/screen/ScreenList.tsx | 87 ++-- 9 files changed, 458 insertions(+), 282 deletions(-) diff --git a/frontend/app/(main)/admin/batch-management/page.tsx b/frontend/app/(main)/admin/batch-management/page.tsx index ed762521..5bb82a84 100644 --- a/frontend/app/(main)/admin/batch-management/page.tsx +++ b/frontend/app/(main)/admin/batch-management/page.tsx @@ -353,14 +353,14 @@ export default function BatchManagementPage() { - 작업명 - 타입 - 스케줄 - 상태 - 실행 통계 - 성공률 - 마지막 실행 - 작업 + 작업명 + 타입 + 스케줄 + 상태 + 실행 통계 + 성공률 + 마지막 실행 + 작업 diff --git a/frontend/app/(main)/admin/collection-management/page.tsx b/frontend/app/(main)/admin/collection-management/page.tsx index 6523b1d0..75f00cdb 100644 --- a/frontend/app/(main)/admin/collection-management/page.tsx +++ b/frontend/app/(main)/admin/collection-management/page.tsx @@ -249,20 +249,20 @@ export default function CollectionManagementPage() {
- 설정명 - 수집 타입 - 소스 테이블 - 대상 테이블 - 스케줄 - 상태 - 마지막 수집 - 작업 + 설정명 + 수집 타입 + 소스 테이블 + 대상 테이블 + 스케줄 + 상태 + 마지막 수집 + 작업 {filteredConfigs.map((config) => ( - - + +
{config.config_name}
{config.description && ( @@ -272,27 +272,27 @@ export default function CollectionManagementPage() { )}
- + {getTypeBadge(config.collection_type)} - + {config.source_table} - + {config.target_table || "-"} - + {config.schedule_cron || "-"} - + {getStatusBadge(config.is_active)} - + {config.last_collected_at ? new Date(config.last_collected_at).toLocaleString() : "-"} - +
- - 연결명 - DB 타입 - 호스트:포트 - 데이터베이스 - 사용자 - 상태 - 생성일 - 연결 테스트 - 작업 + + 연결명 + DB 타입 + 호스트:포트 + 데이터베이스 + 사용자 + 상태 + 생성일 + 연결 테스트 + 작업 {connections.map((connection) => ( - - + +
{connection.connection_name}
- + {DB_TYPE_LABELS[connection.db_type] || connection.db_type} - + {connection.host}:{connection.port} - {connection.database_name} - {connection.username} - + {connection.database_name} + {connection.username} + {connection.is_active === "Y" ? "활성" : "비활성"} - + {connection.created_date ? new Date(connection.created_date).toLocaleDateString() : "N/A"} - +
+ )} +
+ )} + {loading ? (
@@ -707,40 +828,42 @@ export default function TableManagementPage() { .map((table) => (
-
handleTableSelect(table.tableName)}> -

{table.displayName || table.tableName}

-

- {table.description || getTextFromUI(TABLE_MANAGEMENT_KEYS.TABLE_DESCRIPTION, "설명 없음")} -

-
- 컬럼 - - {table.columnCount} - +
+ {/* 체크박스 (최고 관리자만) */} + {isSuperAdmin && ( + handleTableCheck(table.tableName, checked as boolean)} + aria-label={`${table.displayName || table.tableName} 선택`} + className="mt-0.5" + onClick={(e) => e.stopPropagation()} + /> + )} +
handleTableSelect(table.tableName)} + > +

{table.displayName || table.tableName}

+

+ {table.description || getTextFromUI(TABLE_MANAGEMENT_KEYS.TABLE_DESCRIPTION, "설명 없음")} +

+
+ 컬럼 + + {table.columnCount} + +
- - {/* 삭제 버튼 (최고 관리자만) */} - {isSuperAdmin && ( -
- -
- )}
)) )} @@ -749,14 +872,9 @@ export default function TableManagementPage() {
{/* 우측 메인 영역: 컬럼 타입 관리 (80%) */} -
-
-

- - {selectedTable ? <>테이블 설정 - {selectedTable} : "테이블 타입 관리"} -

- -
+
+
+
{!selectedTable ? (
@@ -801,19 +919,19 @@ export default function TableManagementPage() { ) : (
{/* 컬럼 헤더 */} -
-
컬럼명
+
+
컬럼명
라벨
-
입력 타입
-
+
입력 타입
+
상세 설정
-
설명
+
설명
{/* 컬럼 리스트 */}
{ const { scrollTop, scrollHeight, clientHeight } = e.currentTarget; // 스크롤이 끝에 가까워지면 더 많은 데이터 로드 @@ -825,9 +943,9 @@ export default function TableManagementPage() { {columns.map((column, index) => (
-
+
{column.columnName}
@@ -838,7 +956,7 @@ export default function TableManagementPage() { className="h-8 text-xs" />
-
+
-
+
{/* 웹 타입이 'code'인 경우 공통코드 선택 */} {column.inputType === "code" && ( + handleDetailSettingsChange(column.columnName, "entity", value) + } + > + + + + + {referenceTableOptions.map((option, index) => ( + +
+ {option.label} + + {option.value} + +
+
+ ))} +
+
-
- {/* 참조 테이블 */} + {/* 조인 컬럼 */} + {column.referenceTable && column.referenceTable !== "none" && (
+ )} - {/* 조인 컬럼 */} - {column.referenceTable && column.referenceTable !== "none" && ( + {/* 표시 컬럼 */} + {column.referenceTable && + column.referenceTable !== "none" && + column.referenceColumn && + column.referenceColumn !== "none" && (
)} -
- - {/* 설정 완료 표시 - 간소화 */} - {column.referenceTable && - column.referenceTable !== "none" && - column.referenceColumn && - column.referenceColumn !== "none" && - column.displayColumn && - column.displayColumn !== "none" && ( -
- - - {column.columnName} → {column.referenceTable}.{column.displayColumn} - -
- )}
+ + {/* 설정 완료 표시 */} + {column.referenceTable && + column.referenceTable !== "none" && + column.referenceColumn && + column.referenceColumn !== "none" && + column.displayColumn && + column.displayColumn !== "none" && ( +
+ + + {column.columnName} → {column.referenceTable}.{column.displayColumn} + +
+ )}
)} {/* 다른 웹 타입인 경우 빈 공간 */} {column.inputType !== "code" && column.inputType !== "entity" && ( -
-
+
+ - +
)}
-
+
handleColumnChange(index, "description", e.target.value)} @@ -1075,26 +1234,62 @@ export default function TableManagementPage() { - 테이블 삭제 확인 + + {selectedTableIds.size > 0 ? "테이블 일괄 삭제 확인" : "테이블 삭제 확인"} + - 정말로 테이블을 삭제하시겠습니까? 이 작업은 되돌릴 수 없습니다. + {selectedTableIds.size > 0 ? ( + <> + 선택된 {selectedTableIds.size}개의 테이블을 삭제하시겠습니까? +
+ 이 작업은 되돌릴 수 없습니다. + + ) : ( + <> + 정말로 테이블을 삭제하시겠습니까? 이 작업은 되돌릴 수 없습니다. + + )}
-
-
-

경고

-

- 테이블 {tableToDelete}과 모든 데이터가 영구적으로 - 삭제됩니다. -

+ {selectedTableIds.size === 0 && tableToDelete && ( +
+
+

경고

+

+ 테이블 {tableToDelete}과 모든 데이터가 영구적으로 + 삭제됩니다. +

+
-
+ )} + + {selectedTableIds.size > 0 && ( +
+
+

경고

+

+ 다음 테이블들과 모든 데이터가 영구적으로 삭제됩니다: +

+
    + {Array.from(selectedTableIds).map((tableName) => ( +
  • + {tableName} +
  • + ))} +
+
+
+ )}
- + - + - + - 카테고리 - 설명 - 아이콘 - 기본 크기 - 공개 여부 - 활성화 - 수정일 - 작업 + 카테고리 + 설명 + 아이콘 + 기본 크기 + 공개 여부 + 활성화 + 수정일 + 작업 @@ -299,39 +299,39 @@ export default function TemplatesManagePage() { ) : ( filteredAndSortedTemplates.map((template) => ( - - {template.sort_order || 0} - {template.template_code} - + + {template.sort_order || 0} + {template.template_code} + {template.template_name} {template.template_name_eng && (
{template.template_name_eng}
)}
- + {template.category} - {template.description || "-"} - + {template.description || "-"} +
{renderIcon(template.icon_name)}
- + {template.default_size ? `${template.default_size.width}×${template.default_size.height}` : "-"} - + {template.is_public === "Y" ? "공개" : "비공개"} - + {template.is_active === "Y" ? "활성화" : "비활성화"} - + {template.updated_date ? new Date(template.updated_date).toLocaleDateString("ko-KR") : "-"} - +
- - 화면명 - 화면 코드 - 테이블명 - 상태 - 생성일 - 작업 + + 화면명 + 화면 코드 + 테이블명 + 상태 + 생성일 + 작업 {screens.map((screen) => ( onDesignScreen(screen)} > - +
{screen.screenName}
{screen.description && ( @@ -461,26 +458,26 @@ export default function ScreenList({ onScreenSelect, selectedScreen, onDesignScr )}
- + {screen.screenCode} - + {screen.tableLabel || screen.tableName} - + {screen.isActive === "Y" ? "활성" : "비활성"} - +
{screen.createdDate.toLocaleDateString()}
{screen.createdBy}
- + - )} - +
- - + + 0 && selectedScreenIds.length === deletedScreens.length} onCheckedChange={handleSelectAll} aria-label="전체 선택" /> - 화면명 - 화면 코드 - 테이블명 - 삭제일 - 삭제자 - 삭제 사유 - 작업 + 화면명 + 화면 코드 + 테이블명 + 삭제일 + 삭제자 + 삭제 사유 + 작업 {deletedScreens.map((screen) => ( - - + + handleScreenCheck(screen.screenId, checked as boolean)} aria-label={`${screen.screenName} 선택`} /> - +
{screen.screenName}
{screen.description && ( @@ -724,28 +706,28 @@ export default function ScreenList({ onScreenSelect, selectedScreen, onDesignScr )}
- + {screen.screenCode} - + {screen.tableLabel || screen.tableName} - +
{screen.deletedDate?.toLocaleDateString()}
- +
{screen.deletedBy}
- +
{screen.deleteReason || "-"}
- +
{selectedScreenIds.length > 0 && (