v2-repeat-screen-modal 컴포넌트 제거 및 관련 파일 삭제: v2-repeat-screen-modal 컴포넌트와 관련된 모든 파일을 삭제하여 코드베이스를 정리하였습니다. 이로 인해 더 이상 사용되지 않는 컴포넌트가 제거되어 관리 효율성이 향상되었습니다.

This commit is contained in:
kjs 2026-01-20 09:42:33 +09:00
parent d3701cfe1e
commit a67b53038f
13 changed files with 34 additions and 10017 deletions

View File

@ -1044,7 +1044,6 @@
"integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/code-frame": "^7.27.1",
"@babel/generator": "^7.28.3",
@ -2372,7 +2371,6 @@
"resolved": "https://registry.npmjs.org/@redis/client/-/client-1.6.1.tgz",
"integrity": "sha512-/KCsg3xSlR+nCK8/8ZYSknYxvXHwubJrU82F3Lm1Fp6789VQ0/3RJKfsmRXjqfaTA++23CvC3hqmqe/2GEt6Kw==",
"license": "MIT",
"peer": true,
"dependencies": {
"cluster-key-slot": "1.1.2",
"generic-pool": "3.9.0",
@ -3476,7 +3474,6 @@
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.17.tgz",
"integrity": "sha512-gfehUI8N1z92kygssiuWvLiwcbOB3IRktR6hTDgJlXMYh5OvkPSRmgfoBUmfZt+vhwJtX7v1Yw4KvvAf7c5QKQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"undici-types": "~6.21.0"
}
@ -3713,7 +3710,6 @@
"integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==",
"dev": true,
"license": "BSD-2-Clause",
"peer": true,
"dependencies": {
"@typescript-eslint/scope-manager": "6.21.0",
"@typescript-eslint/types": "6.21.0",
@ -3931,7 +3927,6 @@
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"dev": true,
"license": "MIT",
"peer": true,
"bin": {
"acorn": "bin/acorn"
},
@ -4458,7 +4453,6 @@
}
],
"license": "MIT",
"peer": true,
"dependencies": {
"baseline-browser-mapping": "^2.8.3",
"caniuse-lite": "^1.0.30001741",
@ -5669,7 +5663,6 @@
"deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.6.1",
@ -7432,7 +7425,6 @@
"integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@jest/core": "^29.7.0",
"@jest/types": "^29.6.3",
@ -8402,6 +8394,7 @@
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
"license": "MIT",
"peer": true,
"dependencies": {
"js-tokens": "^3.0.0 || ^4.0.0"
},
@ -9290,7 +9283,6 @@
"resolved": "https://registry.npmjs.org/pg/-/pg-8.16.3.tgz",
"integrity": "sha512-enxc1h0jA/aq5oSDMvqyW3q89ra6XIIDZgCX9vkMrnz5DFTw/Ny3Li2lFQ+pt3L6MCgm/5o2o8HW9hiJji+xvw==",
"license": "MIT",
"peer": true,
"dependencies": {
"pg-connection-string": "^2.9.1",
"pg-pool": "^3.10.1",
@ -10141,6 +10133,7 @@
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
"integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"loose-envify": "^1.1.0"
}
@ -10949,7 +10942,6 @@
"integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@cspotcode/source-map-support": "^0.8.0",
"@tsconfig/node10": "^1.0.7",
@ -11055,7 +11047,6 @@
"integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==",
"dev": true,
"license": "Apache-2.0",
"peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"

View File

@ -132,6 +132,7 @@ export function ComponentsPanel({
"pivot-grid", // → v2-pivot-grid
"table-search-widget", // → v2-table-search-widget
"tabs", // → v2-tabs
"tabs-widget", // → v2-tabs-widget
];
return {

View File

@ -97,7 +97,6 @@ import "./v2-numbering-rule/NumberingRuleRenderer";
import "./v2-table-list/TableListRenderer";
import "./v2-text-display/TextDisplayRenderer";
import "./v2-pivot-grid/PivotGridRenderer";
import "./v2-repeat-screen-modal/RepeatScreenModalRenderer";
import "./v2-divider-line/DividerLineRenderer";
import "./v2-repeat-container/RepeatContainerRenderer";
import "./v2-section-card/SectionCardRenderer";

View File

@ -1,409 +0,0 @@
# RepeatScreenModal 컴포넌트 v3.1
## 개요
`RepeatScreenModal`은 선택한 데이터를 기반으로 여러 개의 카드를 생성하고, 각 카드의 내부 레이아웃을 자유롭게 구성할 수 있는 컴포넌트입니다.
## v3.1 주요 변경사항 (2025-11-28)
### 1. 외부 테이블 데이터 소스
테이블 행에서 **외부 테이블의 데이터를 조회**하여 표시할 수 있습니다.
```
예시: 수주 관리에서 출하 계획 이력 조회
┌─────────────────────────────────────────────────────────────────┐
│ 카드: 품목 A │
├─────────────────────────────────────────────────────────────────┤
│ [행 1] 헤더: 품목코드, 품목명 │
├─────────────────────────────────────────────────────────────────┤
│ [행 2] 테이블: shipment_plan 테이블에서 조회 │
│ → sales_order_id로 조인하여 출하 계획 이력 표시 │
└─────────────────────────────────────────────────────────────────┘
```
### 2. 테이블 행 CRUD
테이블 행에서 **행 추가/수정/삭제** 기능을 지원합니다.
- **추가**: 새 행 추가 버튼으로 빈 행 생성
- **수정**: 편집 가능한 컬럼 직접 수정
- **삭제**: 행 삭제 (확인 팝업 옵션)
### 3. Footer 버튼 영역
모달 하단에 **커스터마이징 가능한 버튼 영역**을 제공합니다.
```
┌─────────────────────────────────────────────────────────────────┐
│ 카드 내용... │
├─────────────────────────────────────────────────────────────────┤
│ [초기화] [취소] [저장] │
└─────────────────────────────────────────────────────────────────┘
```
### 4. 집계 연산식 지원
집계 행에서 **컬럼 간 사칙연산**을 지원합니다.
```typescript
// 예: 미출하 수량 = 수주수량 - 출하수량
{
sourceType: "formula",
formula: "{order_qty} - {ship_qty}",
label: "미출하 수량"
}
```
---
## v3 주요 변경사항 (기존)
### 자유 레이아웃 시스템
기존의 "simple 모드 / withTable 모드" 구분을 없애고, **행(Row)을 추가하고 각 행마다 타입을 선택**하는 방식으로 변경되었습니다.
```
┌─────────────────────────────────────────────────────────────────┐
│ 카드 │
├─────────────────────────────────────────────────────────────────┤
│ [행 1] 타입: 헤더 → 품목코드, 품목명, 규격 │
├─────────────────────────────────────────────────────────────────┤
│ [행 2] 타입: 집계 → 총수주잔량, 현재고, 가용재고 │
├─────────────────────────────────────────────────────────────────┤
│ [행 3] 타입: 테이블 → 수주번호, 거래처, 납기일, 출하계획 │
├─────────────────────────────────────────────────────────────────┤
│ [행 4] 타입: 테이블 → 또 다른 테이블도 가능! │
└─────────────────────────────────────────────────────────────────┘
```
### 행 타입
| 타입 | 설명 | 사용 시나리오 |
|------|------|---------------|
| **헤더 (header)** | 필드들을 가로/세로로 나열 | 품목정보, 거래처정보 표시 |
| **필드 (fields)** | 헤더와 동일, 편집 가능 | 폼 입력 영역 |
| **집계 (aggregation)** | 그룹 내 데이터 집계값 표시 | 총수량, 합계금액 등 |
| **테이블 (table)** | 그룹 내 각 행을 테이블로 표시 | 수주목록, 품목목록 등 |
---
## 설정 방법
### 1. 기본 설정 탭
- **카드 제목 표시**: 카드 상단에 제목을 표시할지 여부
- **카드 제목 템플릿**: `{field_name}` 형식으로 동적 제목 생성
- **카드 간격**: 카드 사이의 간격 (8px ~ 32px)
- **테두리**: 카드 테두리 표시 여부
- **저장 모드**: 전체 저장 / 개별 저장
### 2. 데이터 소스 탭
- **소스 테이블**: 데이터를 조회할 테이블
- **필터 필드**: formData에서 필터링할 필드 (예: selectedIds)
### 3. 그룹 탭
- **그룹핑 활성화**: 여러 행을 하나의 카드로 묶을지 여부
- **그룹 기준 필드**: 그룹핑할 필드 (예: part_code)
- **집계 설정**:
- 원본 필드: 합계할 필드 (예: balance_qty)
- 집계 타입: sum, count, avg, min, max
- 결과 필드명: 집계 결과를 저장할 필드명
- 라벨: 표시될 라벨
### 4. 레이아웃 탭
#### 행 추가
4가지 타입의 행을 추가할 수 있습니다:
- **헤더**: 필드 정보 표시 (읽기전용)
- **집계**: 그룹 집계값 표시
- **테이블**: 그룹 내 행들을 테이블로 표시
- **필드**: 입력 필드 (편집가능)
#### 헤더/필드 행 설정
- **방향**: 가로 / 세로
- **배경색**: 없음, 파랑, 초록, 보라, 주황
- **컬럼**: 필드명, 라벨, 타입, 너비, 편집 가능, 필수
- **소스 설정**: 직접 / 조인 / 수동
- **저장 설정**: 저장할 테이블과 컬럼
#### 집계 행 설정
- **레이아웃**: 가로 나열 / 그리드
- **그리드 컬럼 수**: 2, 3, 4개
- **집계 필드**: 그룹 탭에서 정의한 집계 결과 선택
- **스타일**: 배경색, 폰트 크기
#### 테이블 행 설정 (v3.1 확장)
- **테이블 제목**: 선택사항
- **헤더 표시**: 테이블 헤더 표시 여부
- **외부 테이블 데이터 소스**: (v3.1 신규)
- 소스 테이블: 조회할 외부 테이블
- 조인 조건: 외부 테이블 키 ↔ 카드 데이터 키
- 정렬: 정렬 컬럼 및 방향
- **CRUD 설정**: (v3.1 신규)
- 추가: 새 행 추가 허용
- 수정: 행 수정 허용
- 삭제: 행 삭제 허용 (확인 팝업 옵션)
- **테이블 컬럼**: 필드명, 라벨, 타입, 너비, 편집 가능
- **저장 설정**: 편집 가능한 컬럼의 저장 위치
### 5. Footer 탭 (v3.1 신규)
- **Footer 사용**: Footer 영역 활성화
- **위치**: 컨텐츠 아래 / 하단 고정 (sticky)
- **정렬**: 왼쪽 / 가운데 / 오른쪽
- **버튼 설정**:
- 라벨: 버튼 텍스트
- 액션: 저장 / 취소 / 닫기 / 초기화 / 커스텀
- 스타일: 기본 / 보조 / 외곽선 / 삭제 / 고스트
- 아이콘: 저장 / X / 초기화 / 없음
---
## 데이터 흐름
```
1. formData에서 selectedIds 가져오기
2. 소스 테이블에서 해당 ID들의 데이터 조회
3. 그룹핑 활성화 시 groupByField 기준으로 그룹화
4. 각 그룹에 대해 집계값 계산
5. 외부 테이블 데이터 소스가 설정된 테이블 행의 데이터 로드 (v3.1)
6. 카드 렌더링 (contentRows 기반)
7. 사용자 편집 (CRUD 포함)
8. Footer 버튼 또는 기본 저장 버튼으로 저장
9. 기본 데이터 + 외부 테이블 데이터 일괄 저장
```
---
## 사용 예시
### 출하계획 등록 (v3.1 - 외부 테이블 + CRUD)
```typescript
{
showCardTitle: true,
cardTitle: "{part_code} - {part_name}",
dataSource: {
sourceTable: "sales_order_mng",
filterField: "selectedIds"
},
grouping: {
enabled: true,
groupByField: "part_code",
aggregations: [
{ sourceField: "balance_qty", type: "sum", resultField: "total_balance", label: "총수주잔량" },
{ sourceField: "id", type: "count", resultField: "order_count", label: "수주건수" }
]
},
contentRows: [
{
id: "row-1",
type: "header",
columns: [
{ id: "c1", field: "part_code", label: "품목코드", type: "text", editable: false },
{ id: "c2", field: "part_name", label: "품목명", type: "text", editable: false }
],
layout: "horizontal"
},
{
id: "row-2",
type: "aggregation",
aggregationLayout: "horizontal",
aggregationFields: [
{ sourceType: "aggregation", aggregationResultField: "total_balance", label: "총수주잔량", backgroundColor: "blue" },
{ sourceType: "formula", formula: "{order_qty} - {ship_qty}", label: "미출하 수량", backgroundColor: "orange" }
]
},
{
id: "row-3",
type: "table",
tableTitle: "출하 계획 이력",
showTableHeader: true,
// 외부 테이블에서 데이터 조회
tableDataSource: {
enabled: true,
sourceTable: "shipment_plan",
joinConditions: [
{ sourceKey: "sales_order_id", referenceKey: "id" }
],
orderBy: { column: "created_date", direction: "desc" }
},
// CRUD 설정
tableCrud: {
allowCreate: true,
allowUpdate: true,
allowDelete: true,
newRowDefaults: {
sales_order_id: "{id}",
status: "READY"
},
deleteConfirm: { enabled: true }
},
tableColumns: [
{ id: "tc1", field: "plan_date", label: "계획일", type: "date", editable: true },
{ id: "tc2", field: "plan_qty", label: "계획수량", type: "number", editable: true },
{ id: "tc3", field: "status", label: "상태", type: "text", editable: false },
{ id: "tc4", field: "memo", label: "비고", type: "text", editable: true }
]
}
],
// Footer 설정
footerConfig: {
enabled: true,
position: "sticky",
alignment: "right",
buttons: [
{ id: "btn-cancel", label: "취소", action: "cancel", variant: "outline" },
{ id: "btn-save", label: "저장", action: "save", variant: "default", icon: "save" }
]
}
}
```
---
## 타입 정의 (v3.1)
### TableDataSourceConfig
```typescript
interface TableDataSourceConfig {
enabled: boolean; // 외부 데이터 소스 사용 여부
sourceTable: string; // 조회할 테이블
joinConditions: JoinCondition[]; // 조인 조건
orderBy?: {
column: string; // 정렬 컬럼
direction: "asc" | "desc"; // 정렬 방향
};
limit?: number; // 최대 행 수
}
interface JoinCondition {
sourceKey: string; // 외부 테이블의 조인 키
referenceKey: string; // 카드 데이터의 참조 키
referenceType?: "card" | "row"; // 참조 소스
}
```
### TableCrudConfig
```typescript
interface TableCrudConfig {
allowCreate: boolean; // 행 추가 허용
allowUpdate: boolean; // 행 수정 허용
allowDelete: boolean; // 행 삭제 허용
newRowDefaults?: Record<string, string>; // 신규 행 기본값 ({field} 형식 지원)
deleteConfirm?: {
enabled: boolean; // 삭제 확인 팝업
message?: string; // 확인 메시지
};
targetTable?: string; // 저장 대상 테이블
}
```
### FooterConfig
```typescript
interface FooterConfig {
enabled: boolean; // Footer 사용 여부
buttons?: FooterButtonConfig[];
position?: "sticky" | "static";
alignment?: "left" | "center" | "right";
}
interface FooterButtonConfig {
id: string;
label: string;
action: "save" | "cancel" | "close" | "reset" | "custom";
variant?: "default" | "secondary" | "outline" | "destructive" | "ghost";
icon?: string;
disabled?: boolean;
customAction?: {
type: string;
config?: Record<string, any>;
};
}
```
### AggregationDisplayConfig (v3.1 확장)
```typescript
interface AggregationDisplayConfig {
// 값 소스 타입
sourceType: "aggregation" | "formula" | "external" | "externalFormula";
// aggregation: 기존 집계 결과 참조
aggregationResultField?: string;
// formula: 컬럼 간 연산
formula?: string; // 예: "{order_qty} - {ship_qty}"
// external: 외부 테이블 조회 (향후 구현)
externalSource?: ExternalValueSource;
// externalFormula: 외부 테이블 + 연산 (향후 구현)
externalSources?: ExternalValueSource[];
externalFormula?: string;
// 표시 설정
label: string;
icon?: string;
backgroundColor?: string;
textColor?: string;
fontSize?: "xs" | "sm" | "base" | "lg" | "xl" | "2xl";
format?: "number" | "currency" | "percent";
decimalPlaces?: number;
}
```
---
## 레거시 호환
v2에서 사용하던 `cardMode`, `cardLayout`, `tableLayout` 설정도 계속 지원됩니다.
새로운 프로젝트에서는 `contentRows`를 사용하는 것을 권장합니다.
---
## 주의사항
1. **집계는 그룹핑 필수**: 집계 행은 그룹핑이 활성화되어 있어야 의미가 있습니다.
2. **테이블은 그룹핑 필수**: 테이블 행도 그룹핑이 활성화되어 있어야 그룹 내 행들을 표시할 수 있습니다.
3. **단순 모드**: 그룹핑 없이 사용하면 1행 = 1카드로 동작합니다. 이 경우 헤더/필드 타입만 사용 가능합니다.
4. **외부 테이블 CRUD**: 외부 테이블 데이터 소스가 설정된 테이블에서만 CRUD가 동작합니다.
5. **연산식**: 사칙연산(+, -, *, /)과 괄호만 지원됩니다. 복잡한 함수는 지원하지 않습니다.
---
## 변경 이력
### v3.1 (2025-11-28)
- 외부 테이블 데이터 소스 기능 추가
- 테이블 행 CRUD (추가/수정/삭제) 기능 추가
- Footer 버튼 영역 기능 추가
- 집계 연산식 (formula) 지원 추가
- 다단계 조인 타입 정의 추가 (향후 구현 예정)
### v3.0
- 자유 레이아웃 시스템 도입
- contentRows 기반 행 타입 선택 방식
- 헤더/필드/집계/테이블 4가지 행 타입 지원
### v2.0
- simple 모드 / withTable 모드 구분
- cardLayout / tableLayout 분리

View File

@ -1,13 +0,0 @@
"use client";
import { ComponentRegistry } from "@/lib/registry/ComponentRegistry";
import { V2RepeatScreenModalDefinition } from "./index";
// 컴포넌트 자동 등록
if (typeof window !== "undefined") {
ComponentRegistry.registerComponent(V2RepeatScreenModalDefinition);
// console.log("✅ RepeatScreenModal 컴포넌트 등록 완료");
}
export {};

View File

@ -1,114 +0,0 @@
"use client";
import { createComponentDefinition } from "../../utils/createComponentDefinition";
import { ComponentCategory } from "@/types/component";
import { RepeatScreenModalComponent } from "./RepeatScreenModalComponent";
import { RepeatScreenModalConfigPanel } from "./RepeatScreenModalConfigPanel";
import type {
RepeatScreenModalProps,
CardRowConfig,
CardColumnConfig,
ColumnSourceConfig,
ColumnTargetConfig,
DataSourceConfig,
CardData,
GroupingConfig,
AggregationConfig,
TableLayoutConfig,
TableColumnConfig,
GroupedCardData,
CardRowData,
CardContentRowConfig,
AggregationDisplayConfig,
} from "./types";
/**
* RepeatScreenModal v3
* - ,
*
* :
* - 🆕 v3: 자유 - (Row) (///)
* - 그룹핑: 특정
* - 집계: 그룹 //
* - 테이블: 그룹
* - 레이아웃: ,
* - 설정: 직접 / /
* - 설정: 어느
* - 저장: 하나의
*
* :
* - ( + )
* - ( + )
* - ( + )
* - ( + )
*/
export const V2RepeatScreenModalDefinition = createComponentDefinition({
id: "v2-repeat-screen-modal",
name: "반복 화면 모달",
nameEng: "Repeat Screen Modal",
description:
"선택한 행을 그룹핑하여 카드로 표시하고, 각 카드는 헤더/집계/테이블을 자유롭게 구성 가능한 폼 (출하계획, 구매발주 등)",
category: ComponentCategory.DATA,
webType: "form",
component: RepeatScreenModalComponent,
defaultConfig: {
// 기본 설정
showCardTitle: true,
cardTitle: "카드 {index}",
cardSpacing: "24px",
showCardBorder: true,
saveMode: "all",
// 데이터 소스
dataSource: {
sourceTable: "",
filterField: "selectedIds",
},
// 그룹핑 설정
grouping: {
enabled: false,
groupByField: "",
aggregations: [],
},
// 🆕 v3: 자유 레이아웃 (행 추가 후 타입 선택)
contentRows: [],
// (레거시 호환)
cardMode: "simple",
cardLayout: [],
tableLayout: {
headerRows: [],
tableColumns: [],
},
} as Partial<RepeatScreenModalProps>,
defaultSize: { width: 1000, height: 800 },
configPanel: RepeatScreenModalConfigPanel,
icon: "LayoutGrid",
tags: ["모달", "폼", "반복", "카드", "그룹핑", "집계", "테이블", "편집", "데이터", "출하계획", "일괄등록", "자유레이아웃"],
version: "3.0.0",
author: "개발팀",
});
// 타입 재 export
export type {
RepeatScreenModalProps,
CardRowConfig,
CardColumnConfig,
ColumnSourceConfig,
ColumnTargetConfig,
DataSourceConfig,
CardData,
GroupingConfig,
AggregationConfig,
TableLayoutConfig,
TableColumnConfig,
GroupedCardData,
CardRowData,
CardContentRowConfig,
AggregationDisplayConfig,
};
// 컴포넌트 재 export
export { RepeatScreenModalComponent, RepeatScreenModalConfigPanel };

View File

@ -1,525 +0,0 @@
import { ComponentRendererProps } from "@/types/component";
/**
* RepeatScreenModal Props
* ,
*
* 🆕 v3: (Row) - (//)
*/
export interface RepeatScreenModalProps {
// === 기본 설정 ===
showCardTitle?: boolean; // 카드 제목 표시 여부
cardTitle?: string; // 카드 제목 템플릿 (예: "{order_no} - {item_code}")
cardSpacing?: string; // 카드 간 간격 (기본: 24px)
showCardBorder?: boolean; // 카드 테두리 표시 여부
saveMode?: "all" | "individual"; // 저장 모드
// === 데이터 소스 ===
dataSource?: DataSourceConfig; // 데이터 소스 설정
// === 그룹핑 설정 ===
grouping?: GroupingConfig; // 그룹핑 설정
// === 🆕 v3: 자유 레이아웃 ===
contentRows?: CardContentRowConfig[]; // 카드 내부 행들 (각 행마다 타입 선택)
// === 🆕 v3.1: Footer 버튼 설정 ===
footerConfig?: FooterConfig; // Footer 영역 설정
// === (레거시 호환) ===
cardMode?: "simple" | "withTable"; // @deprecated - contentRows 사용 권장
cardLayout?: CardRowConfig[]; // @deprecated - contentRows 사용 권장
tableLayout?: TableLayoutConfig; // @deprecated - contentRows 사용 권장
// === 값 ===
value?: any[];
onChange?: (newData: any[]) => void;
}
/**
* 🆕 v3.1: Footer
*/
export interface FooterConfig {
enabled: boolean; // Footer 사용 여부
buttons?: FooterButtonConfig[]; // Footer 버튼들
position?: "sticky" | "static"; // sticky: 하단 고정, static: 컨텐츠 아래
alignment?: "left" | "center" | "right"; // 버튼 정렬
}
/**
* 🆕 v3.1: Footer
*/
export interface FooterButtonConfig {
id: string; // 버튼 고유 ID
label: string; // 버튼 라벨
action: "save" | "cancel" | "close" | "reset" | "custom"; // 액션 타입
variant?: "default" | "secondary" | "outline" | "destructive" | "ghost"; // 버튼 스타일
icon?: string; // 아이콘 (lucide 아이콘명)
disabled?: boolean; // 비활성화 여부
// custom 액션일 때
customAction?: {
type: string; // 커스텀 액션 타입
config?: Record<string, any>; // 커스텀 설정
};
}
/**
*
*/
export interface DataSourceConfig {
sourceTable: string; // 조회할 테이블 (예: "sales_order_mng")
filterField?: string; // formData에서 필터링할 필드 (예: "selectedIds")
selectColumns?: string[]; // 선택할 컬럼 목록
}
/**
*
*
*/
export interface GroupingConfig {
enabled: boolean; // 그룹핑 활성화 여부
groupByField: string; // 그룹 기준 필드 (예: "part_code")
// 집계 설정 (그룹별 합계, 개수 등)
aggregations?: AggregationConfig[];
}
/**
* 🆕 v3: 카드
* (//)
*/
export interface CardContentRowConfig {
id: string; // 행 고유 ID
type: "header" | "aggregation" | "table" | "fields"; // 행 타입
// === header/fields 타입일 때 ===
columns?: CardColumnConfig[]; // 컬럼 설정
layout?: "horizontal" | "vertical"; // 레이아웃 방향
gap?: string; // 컬럼 간 간격
backgroundColor?: string; // 배경색
padding?: string; // 패딩
// === aggregation 타입일 때 ===
aggregationFields?: AggregationDisplayConfig[]; // 표시할 집계 필드들
aggregationLayout?: "horizontal" | "grid"; // 집계 레이아웃 (가로 나열 / 그리드)
aggregationColumns?: number; // grid일 때 컬럼 수 (기본: 4)
// === table 타입일 때 ===
tableColumns?: TableColumnConfig[]; // 테이블 컬럼 설정
tableTitle?: string; // 테이블 제목
showTableHeader?: boolean; // 테이블 헤더 표시 여부
tableMaxHeight?: string; // 테이블 최대 높이
// 🆕 v3.1: 테이블 외부 데이터 소스
tableDataSource?: TableDataSourceConfig; // 외부 테이블에서 데이터 조회
// 🆕 v3.1: 테이블 CRUD 설정
tableCrud?: TableCrudConfig; // 행 추가/수정/삭제 설정
}
/**
* 🆕 v3.1: 테이블
*
*/
export interface TableDataSourceConfig {
enabled: boolean; // 외부 데이터 소스 사용 여부
sourceTable: string; // 조회할 테이블 (예: "shipment_plan")
// 조인 설정
joinConditions: JoinCondition[]; // 조인 조건 (복합 키 지원)
// 🆕 v3.3: 추가 조인 테이블 설정 (소스 테이블에 없는 컬럼 조회)
additionalJoins?: AdditionalJoinConfig[];
// 🆕 v3.4: 필터 조건 설정 (그룹 내 특정 조건으로 필터링)
filterConfig?: TableFilterConfig;
// 정렬 설정
orderBy?: {
column: string; // 정렬 컬럼
direction: "asc" | "desc"; // 정렬 방향
};
// 제한
limit?: number; // 최대 행 수
}
/**
* 🆕 v3.4: 테이블
*
*/
export interface TableFilterConfig {
enabled: boolean; // 필터 사용 여부
filterField: string; // 필터링할 필드 (예: "order_no")
filterType: "equals" | "notEquals"; // equals: 같은 값만, notEquals: 다른 값만
referenceField: string; // 비교 기준 필드 (formData 또는 카드 대표 데이터에서)
referenceSource: "formData" | "representativeData"; // 비교 값 소스
}
/**
* 🆕 v3.3: 추가
*
*/
export interface AdditionalJoinConfig {
id: string; // 조인 설정 고유 ID
joinTable: string; // 조인할 테이블 (예: "sales_order_mng")
joinType: "left" | "inner"; // 조인 타입
sourceKey: string; // 소스 테이블의 조인 키 (예: "sales_order_id")
targetKey: string; // 조인 테이블의 키 (예: "id")
alias?: string; // 테이블 별칭 (예: "so")
selectColumns?: string[]; // 가져올 컬럼 목록 (비어있으면 전체)
}
/**
* 🆕 v3.1: 조인
*/
export interface JoinCondition {
sourceKey: string; // 외부 테이블의 조인 키 (예: "sales_order_id")
referenceKey: string; // 현재 카드 데이터의 참조 키 (예: "id")
referenceType?: "card" | "row"; // card: 카드 대표 데이터, row: 각 행 데이터 (기본: card)
}
/**
* 🆕 v3.1: 테이블 CRUD
*/
export interface TableCrudConfig {
allowCreate: boolean; // 행 추가 허용
allowUpdate: boolean; // 행 수정 허용
allowDelete: boolean; // 행 삭제 허용
// 신규 행 기본값
newRowDefaults?: Record<string, string>; // 기본값 (예: { status: "READY", sales_order_id: "{id}" })
// 삭제 확인
deleteConfirm?: {
enabled: boolean; // 삭제 확인 팝업 표시 여부
message?: string; // 확인 메시지
};
// 저장 대상 테이블 (외부 데이터 소스 사용 시)
targetTable?: string; // 저장할 테이블 (기본: tableDataSource.sourceTable)
// 🆕 v3.12: 연동 저장 설정 (모달 전체 저장 시 다른 테이블에도 동기화)
syncSaves?: SyncSaveConfig[];
// 🆕 v3.13: 행 추가 시 자동 채번 설정
rowNumbering?: RowNumberingConfig;
}
/**
* 🆕 v3.13: 테이블
* "추가"
*
* :
* - (shipment_plan_no)
* - (invoice_no)
* - (work_order_no)
*
* 참고: 채번 "수정 가능"
*/
export interface RowNumberingConfig {
enabled: boolean; // 채번 사용 여부
targetColumn: string; // 채번 결과를 저장할 컬럼 (예: "shipment_plan_no")
// 채번 규칙 설정 (옵션설정 > 코드설정에서 등록된 채번 규칙)
numberingRuleId: string; // 채번 규칙 ID (numbering_rule 테이블)
}
/**
* 🆕 v3.12: 연동
*
*/
export interface SyncSaveConfig {
id: string; // 고유 ID
enabled: boolean; // 활성화 여부
// 소스 설정 (이 테이블에서)
sourceColumn: string; // 집계할 컬럼 (예: "plan_qty")
aggregationType: "sum" | "count" | "avg" | "min" | "max" | "latest"; // 집계 방식
// 대상 설정 (저장할 테이블)
targetTable: string; // 대상 테이블 (예: "sales_order_mng")
targetColumn: string; // 대상 컬럼 (예: "plan_ship_qty")
// 조인 키 (어떤 레코드를 업데이트할지)
joinKey: {
sourceField: string; // 이 테이블의 조인 키 (예: "sales_order_id")
targetField: string; // 대상 테이블의 키 (예: "id")
};
}
/**
* 🆕 v3: 집계
*/
export interface AggregationDisplayConfig {
// 값 소스 타입
sourceType: "aggregation" | "formula" | "external" | "externalFormula";
// === sourceType: "aggregation" (기존 그룹핑 집계 결과 참조) ===
aggregationResultField?: string; // 그룹핑 설정의 resultField 참조
// === sourceType: "formula" (컬럼 간 연산) ===
formula?: string; // 연산식 (예: "{order_qty} - {ship_qty}")
// === sourceType: "external" (외부 테이블 조회) ===
externalSource?: ExternalValueSource;
// === sourceType: "externalFormula" (외부 테이블 + 연산) ===
externalSources?: ExternalValueSource[]; // 여러 외부 소스
externalFormula?: string; // 외부 값들을 조합한 연산식 (예: "{inv_qty} + {prod_qty}")
// 표시 설정
label: string; // 표시 라벨
icon?: string; // 아이콘 (lucide 아이콘명)
backgroundColor?: string; // 배경색
textColor?: string; // 텍스트 색상
fontSize?: "xs" | "sm" | "base" | "lg" | "xl" | "2xl"; // 폰트 크기
format?: "number" | "currency" | "percent"; // 숫자 포맷
decimalPlaces?: number; // 소수점 자릿수
}
/**
* 🆕 v3.1: 외부
*/
export interface ExternalValueSource {
alias: string; // 연산식에서 사용할 별칭 (예: "inv_qty")
sourceTable: string; // 조회할 테이블
sourceColumn: string; // 조회할 컬럼
aggregationType?: "sum" | "count" | "avg" | "min" | "max" | "first"; // 집계 타입 (기본: first)
// 조인 설정 (다단계 조인 지원)
joins: ChainedJoinConfig[];
}
/**
* 🆕 v3.1: 다단계
*/
export interface ChainedJoinConfig {
step: number; // 조인 순서 (1, 2, 3...)
sourceTable: string; // 조인할 테이블
joinConditions: {
sourceKey: string; // 조인 테이블의 키
referenceKey: string; // 참조 키 (이전 단계 결과 또는 카드 데이터)
referenceFrom?: "card" | "previousStep"; // 참조 소스 (기본: card, step > 1이면 previousStep)
}[];
selectColumns?: string[]; // 이 단계에서 선택할 컬럼
}
/**
*
* 🆕 v3.2: 다중 (formula)
* 🆕 v3.9: 연관
*/
export interface AggregationConfig {
// === 집계 소스 타입 ===
sourceType: "column" | "formula"; // column: 테이블 컬럼 집계, formula: 연산식 (가상 집계)
// === sourceType: "column" (테이블 컬럼 집계) ===
sourceTable?: string; // 집계할 테이블 (기본: dataSource.sourceTable, 외부 테이블도 가능)
sourceField?: string; // 원본 필드 (예: "balance_qty")
type?: "sum" | "count" | "avg" | "min" | "max"; // 집계 타입
// === sourceType: "formula" (가상 집계 - 연산식) ===
// 연산식 문법:
// - {resultField}: 다른 집계 결과 참조 (예: {total_balance})
// - {테이블.컬럼}: 테이블의 컬럼 직접 참조 (예: {sales_order_mng.order_qty})
// - SUM({컬럼}): 기본 테이블 행들의 합계
// - SUM_EXT({컬럼}): 외부 테이블 행들의 합계 (externalTableData)
// - 산술 연산: +, -, *, /, ()
formula?: string; // 연산식 (예: "{total_balance} - SUM_EXT({plan_qty})")
// === 🆕 v3.11: SUM_EXT 참조 테이블 제한 ===
// SUM_EXT 함수가 참조할 외부 테이블 행 ID 목록
// 비어있거나 undefined면 모든 외부 테이블 데이터 사용 (기존 동작)
// 특정 테이블만 참조하려면 contentRow의 id를 배열로 지정
externalTableRefs?: string[]; // 참조할 테이블 행 ID 목록 (예: ["crow-1764571929625"])
// === 공통 ===
resultField: string; // 결과 필드명 (예: "total_balance_qty")
label: string; // 표시 라벨 (예: "총수주잔량")
// === 🆕 v3.10: 숨김 설정 ===
hidden?: boolean; // 레이아웃에서 숨김 (연산에만 사용, 기본: false)
// === 🆕 v3.9: 저장 설정 ===
saveConfig?: AggregationSaveConfig; // 연관 테이블 저장 설정
}
/**
* 🆕 v3.9: 집계
*
*/
export interface AggregationSaveConfig {
enabled: boolean; // 저장 활성화 여부
autoSave: boolean; // 자동 저장 (레이아웃에 없어도 저장)
// 저장 대상
targetTable: string; // 저장할 테이블 (예: "sales_order_mng")
targetColumn: string; // 저장할 컬럼 (예: "plan_qty_total")
// 조인 키 (어떤 레코드를 업데이트할지)
joinKey: {
sourceField: string; // 현재 카드의 조인 키 (예: "id" 또는 "sales_order_id")
targetField: string; // 대상 테이블의 키 (예: "id")
};
}
/**
* @deprecated v3에서는 contentRows
*
*/
export interface TableLayoutConfig {
headerRows: CardRowConfig[];
tableColumns: TableColumnConfig[];
tableTitle?: string;
showTableHeader?: boolean;
tableMaxHeight?: string;
}
/**
*
*/
export interface TableColumnConfig {
id: string; // 컬럼 고유 ID
field: string; // 필드명 (소스 테이블 컬럼 또는 조인 테이블 컬럼)
label: string; // 헤더 라벨
type: "text" | "number" | "date" | "select" | "badge"; // 타입
width?: string; // 너비 (예: "100px", "20%")
align?: "left" | "center" | "right"; // 정렬
editable: boolean; // 편집 가능 여부
required?: boolean; // 필수 입력 여부
// 🆕 v3.13: 숨김 설정 (화면에는 안 보이지만 데이터는 존재)
hidden?: boolean; // 숨김 여부
// 🆕 v3.3: 컬럼 소스 테이블 지정 (조인 테이블 컬럼 사용 시)
fromTable?: string; // 컬럼이 속한 테이블 (비어있으면 소스 테이블)
fromJoinId?: string; // additionalJoins의 id 참조 (조인 테이블 컬럼일 때)
// Select 타입 옵션
selectOptions?: { value: string; label: string }[];
// Badge 타입 설정
badgeVariant?: "default" | "secondary" | "destructive" | "outline";
badgeColorMap?: Record<string, string>; // 값별 색상 매핑
// 데이터 소스 설정
sourceConfig?: ColumnSourceConfig;
// 데이터 타겟 설정
targetConfig?: ColumnTargetConfig;
}
/**
*
* (Row) ,
*/
export interface CardRowConfig {
id: string; // 행 고유 ID
columns: CardColumnConfig[]; // 이 행에 배치할 컬럼들
gap?: string; // 컬럼 간 간격 (기본: 16px)
layout?: "horizontal" | "vertical"; // 레이아웃 방향 (기본: horizontal)
// 🆕 행 스타일 설정
backgroundColor?: string; // 배경색 (예: "blue", "green")
padding?: string; // 패딩
rounded?: boolean; // 둥근 모서리
}
/**
*
*/
export interface CardColumnConfig {
id: string; // 컬럼 고유 ID
field: string; // 필드명 (데이터 바인딩)
label: string; // 라벨
type: "text" | "number" | "date" | "select" | "textarea" | "component" | "aggregation"; // 🆕 aggregation 추가
width?: string; // 너비 (예: "50%", "200px", "1fr")
editable: boolean; // 편집 가능 여부
required?: boolean; // 필수 입력 여부
placeholder?: string; // 플레이스홀더
// Select 타입 옵션
selectOptions?: { value: string; label: string }[];
// 데이터 소스 설정 (어디서 조회?)
sourceConfig?: ColumnSourceConfig;
// 데이터 타겟 설정 (어디에 저장?)
targetConfig?: ColumnTargetConfig;
// Component 타입일 때
componentType?: string; // 삽입할 컴포넌트 타입 (예: "simple-repeater-table")
componentConfig?: any; // 컴포넌트 설정
// 🆕 Aggregation 타입일 때 (집계값 표시)
aggregationField?: string; // 표시할 집계 필드명 (GroupingConfig.aggregations의 resultField)
// 🆕 스타일 설정
textColor?: string; // 텍스트 색상
fontSize?: "xs" | "sm" | "base" | "lg" | "xl" | "2xl"; // 폰트 크기
fontWeight?: "normal" | "medium" | "semibold" | "bold"; // 폰트 굵기
}
/**
* (SimpleRepeaterTable과 )
*/
export interface ColumnSourceConfig {
type: "direct" | "join" | "manual"; // 조회 타입
sourceTable?: string; // type: "direct" - 조회할 테이블
sourceColumn?: string; // type: "direct" - 조회할 컬럼
joinTable?: string; // type: "join" - 조인할 테이블
joinColumn?: string; // type: "join" - 조인 테이블에서 가져올 컬럼
joinKey?: string; // type: "join" - 현재 데이터의 조인 키 컬럼
joinRefKey?: string; // type: "join" - 조인 테이블의 참조 키 컬럼
}
/**
* (SimpleRepeaterTable과 )
*/
export interface ColumnTargetConfig {
targetTable: string; // 저장할 테이블
targetColumn: string; // 저장할 컬럼
saveEnabled?: boolean; // 저장 활성화 여부 (기본 true)
}
/**
* ( )
*/
export interface CardData {
_cardId: string; // 카드 고유 ID
_originalData: Record<string, any>; // 원본 데이터 (조회된 데이터)
_isDirty: boolean; // 수정 여부
[key: string]: any; // 실제 필드 데이터
}
/**
* 🆕
*/
export interface GroupedCardData {
_cardId: string; // 카드 고유 ID
_groupKey: string; // 그룹 키 값 (예: "PROD-001")
_groupField: string; // 그룹 기준 필드명 (예: "part_code")
_aggregations: Record<string, number>; // 집계 결과 (예: { total_balance_qty: 100 })
_rows: CardRowData[]; // 그룹 내 각 행 데이터
_representativeData: Record<string, any>; // 그룹 대표 데이터 (첫 번째 행 기준)
}
/**
* 🆕
*/
export interface CardRowData {
_rowId: string; // 행 고유 ID
_originalData: Record<string, any>; // 원본 데이터
_isDirty: boolean; // 수정 여부
[key: string]: any; // 실제 필드 데이터
}
/**
* (API )
*/
export interface TableInfo {
tableName: string;
displayName?: string;
}

View File

@ -5373,7 +5373,7 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
{/* 🆕 DevExpress 스타일 기능 툴바 */}
<div className="border-border bg-muted/20 flex flex-wrap items-center gap-1 border-b px-2 py-1.5 sm:gap-2 sm:px-4 sm:py-2">
{/* 편집 모드 토글 */}
{(tableConfig.toolbar?.showEditMode ?? true) && (
{(tableConfig.toolbar?.showEditMode ?? false) && (
<div className="border-border flex items-center gap-1 border-r pr-2">
<Button
variant={editMode === "batch" ? "default" : "ghost"}
@ -5389,9 +5389,9 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
)}
{/* 내보내기 버튼들 */}
{((tableConfig.toolbar?.showExcel ?? true) || (tableConfig.toolbar?.showPdf ?? true)) && (
{((tableConfig.toolbar?.showExcel ?? false) || (tableConfig.toolbar?.showPdf ?? false)) && (
<div className="border-border flex items-center gap-1 border-r pr-2">
{(tableConfig.toolbar?.showExcel ?? true) && (
{(tableConfig.toolbar?.showExcel ?? false) && (
<Button
variant="ghost"
size="sm"
@ -5403,7 +5403,7 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
Excel
</Button>
)}
{(tableConfig.toolbar?.showPdf ?? true) && (
{(tableConfig.toolbar?.showPdf ?? false) && (
<Button
variant="ghost"
size="sm"
@ -5419,7 +5419,7 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
)}
{/* 복사 버튼 */}
{(tableConfig.toolbar?.showCopy ?? true) && (
{(tableConfig.toolbar?.showCopy ?? false) && (
<div className="border-border flex items-center gap-1 border-r pr-2">
<Button
variant="ghost"
@ -5454,7 +5454,7 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
)}
{/* 🆕 통합 검색 패널 */}
{(tableConfig.toolbar?.showSearch ?? true) && (
{(tableConfig.toolbar?.showSearch ?? false) && (
<div className="border-border flex items-center gap-1 border-r pr-2">
{isSearchPanelOpen ? (
<div className="flex items-center gap-1">
@ -5529,7 +5529,7 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
)}
{/* 🆕 Filter Builder (고급 필터) 버튼 */}
{(tableConfig.toolbar?.showFilter ?? true) && (
{(tableConfig.toolbar?.showFilter ?? false) && (
<div className="border-border flex items-center gap-1 border-r pr-2">
<Button
variant={activeFilterCount > 0 ? "default" : "ghost"}
@ -5558,8 +5558,8 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
</div>
)}
{/* 새로고침 */}
{(tableConfig.toolbar?.showRefresh ?? true) && (
{/* 새로고침 (상단) */}
{(tableConfig.toolbar?.showRefresh ?? false) && (
<div className="ml-auto flex items-center gap-1">
<Button
variant="ghost"

View File

@ -771,7 +771,7 @@ export const TableListConfigPanel: React.FC<TableListConfigPanelProps> = ({
<div className="flex items-center space-x-2">
<Checkbox
id="showEditMode"
checked={config.toolbar?.showEditMode ?? true}
checked={config.toolbar?.showEditMode ?? false}
onCheckedChange={(checked) => handleNestedChange("toolbar", "showEditMode", checked)}
/>
<Label htmlFor="showEditMode" className="text-xs"> </Label>
@ -779,7 +779,7 @@ export const TableListConfigPanel: React.FC<TableListConfigPanelProps> = ({
<div className="flex items-center space-x-2">
<Checkbox
id="showExcel"
checked={config.toolbar?.showExcel ?? true}
checked={config.toolbar?.showExcel ?? false}
onCheckedChange={(checked) => handleNestedChange("toolbar", "showExcel", checked)}
/>
<Label htmlFor="showExcel" className="text-xs">Excel</Label>
@ -787,7 +787,7 @@ export const TableListConfigPanel: React.FC<TableListConfigPanelProps> = ({
<div className="flex items-center space-x-2">
<Checkbox
id="showPdf"
checked={config.toolbar?.showPdf ?? true}
checked={config.toolbar?.showPdf ?? false}
onCheckedChange={(checked) => handleNestedChange("toolbar", "showPdf", checked)}
/>
<Label htmlFor="showPdf" className="text-xs">PDF</Label>
@ -795,7 +795,7 @@ export const TableListConfigPanel: React.FC<TableListConfigPanelProps> = ({
<div className="flex items-center space-x-2">
<Checkbox
id="showCopy"
checked={config.toolbar?.showCopy ?? true}
checked={config.toolbar?.showCopy ?? false}
onCheckedChange={(checked) => handleNestedChange("toolbar", "showCopy", checked)}
/>
<Label htmlFor="showCopy" className="text-xs"></Label>
@ -803,7 +803,7 @@ export const TableListConfigPanel: React.FC<TableListConfigPanelProps> = ({
<div className="flex items-center space-x-2">
<Checkbox
id="showSearch"
checked={config.toolbar?.showSearch ?? true}
checked={config.toolbar?.showSearch ?? false}
onCheckedChange={(checked) => handleNestedChange("toolbar", "showSearch", checked)}
/>
<Label htmlFor="showSearch" className="text-xs"></Label>
@ -811,7 +811,7 @@ export const TableListConfigPanel: React.FC<TableListConfigPanelProps> = ({
<div className="flex items-center space-x-2">
<Checkbox
id="showFilter"
checked={config.toolbar?.showFilter ?? true}
checked={config.toolbar?.showFilter ?? false}
onCheckedChange={(checked) => handleNestedChange("toolbar", "showFilter", checked)}
/>
<Label htmlFor="showFilter" className="text-xs"></Label>
@ -819,7 +819,7 @@ export const TableListConfigPanel: React.FC<TableListConfigPanelProps> = ({
<div className="flex items-center space-x-2">
<Checkbox
id="showRefresh"
checked={config.toolbar?.showRefresh ?? true}
checked={config.toolbar?.showRefresh ?? false}
onCheckedChange={(checked) => handleNestedChange("toolbar", "showRefresh", checked)}
/>
<Label htmlFor="showRefresh" className="text-xs"> ()</Label>

View File

@ -23,16 +23,16 @@ export const V2TableListDefinition = createComponentDefinition({
defaultConfig: {
// 표시 모드 설정
displayMode: "table" as const,
// 카드 모드 기본 설정
cardConfig: {
idColumn: "id",
titleColumn: "name",
titleColumn: "name",
cardsPerRow: 3,
cardSpacing: 16,
showActions: true,
},
// 테이블 기본 설정
showHeader: true,
showFooter: true,
@ -93,6 +93,18 @@ export const V2TableListDefinition = createComponentDefinition({
borderStyle: "light",
},
// 툴바 설정 (기본값: 새로고침 하단만 활성화)
toolbar: {
showEditMode: false,
showExcel: false,
showPdf: false,
showCopy: false,
showSearch: false,
showFilter: false,
showRefresh: false,
showPaginationRefresh: true, // 새로고침 (하단)만 기본 활성화
},
// 데이터 로딩
autoLoad: true,
},

View File

@ -64,7 +64,6 @@ const CONFIG_PANEL_MAP: Record<string, () => Promise<any>> = {
"simple-repeater-table": () => import("@/lib/registry/components/simple-repeater-table/SimpleRepeaterTableConfigPanel"),
"modal-repeater-table": () => import("@/lib/registry/components/modal-repeater-table/ModalRepeaterTableConfigPanel"),
"repeat-screen-modal": () => import("@/lib/registry/components/repeat-screen-modal/RepeatScreenModalConfigPanel"),
"v2-repeat-screen-modal": () => import("@/lib/registry/components/v2-repeat-screen-modal/RepeatScreenModalConfigPanel"),
"related-data-buttons": () => import("@/lib/registry/components/related-data-buttons/RelatedDataButtonsConfigPanel"),
// ========== 검색/선택 ==========