V2 이벤트 시스템 통합 및 데이터 전달 인터페이스 구현: UnifiedRepeater 컴포넌트에 데이터 제공 및 수신 인터페이스를 추가하여 다른 컴포넌트와의 데이터 연동을 개선하였습니다. 또한, AggregationWidgetComponent와 RepeatContainerComponent에서 V2 표준 이벤트를 구독하여 데이터 변경 이벤트를 효율적으로 처리하도록 수정하였습니다. 이를 통해 컴포넌트 간의 데이터 흐름과 사용자 경험을 향상시켰습니다.
This commit is contained in:
@@ -8,6 +8,9 @@ import { cn } from "@/lib/utils";
|
||||
import { useScreenMultiLang } from "@/contexts/ScreenMultiLangContext";
|
||||
import { apiClient } from "@/lib/api/client";
|
||||
|
||||
// V2 이벤트 시스템
|
||||
import { V2_EVENTS, subscribeV2Event, type TableListDataChangeDetail, type RepeaterDataChangeDetail } from "@/types/component-events";
|
||||
|
||||
interface AggregationWidgetComponentProps extends ComponentRendererProps {
|
||||
config?: AggregationWidgetConfig;
|
||||
// 외부에서 데이터를 직접 전달받을 수 있음
|
||||
@@ -269,19 +272,19 @@ export function AggregationWidgetComponent({
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [dataSourceType, selectedRowsKey]);
|
||||
|
||||
// ============================================================
|
||||
// 전역 선택 이벤트 수신 (dataSourceType === "selection"일 때)
|
||||
// V2 표준 이벤트만 사용 (중복 이벤트 제거됨)
|
||||
// ============================================================
|
||||
useEffect(() => {
|
||||
if (dataSourceType !== "selection" || isDesignMode) return;
|
||||
|
||||
// 테이블리스트에서 발생하는 선택 이벤트 수신
|
||||
// tableListDataChange 이벤트의 data가 선택된 행들임
|
||||
const handleTableListDataChange = (event: CustomEvent) => {
|
||||
const { data: eventData, selectedRows: eventSelectedRows } = event.detail || {};
|
||||
// data가 선택된 행 데이터 배열
|
||||
// 테이블리스트 데이터 변경 이벤트 (V2 표준)
|
||||
const handleTableListDataChange = (event: CustomEvent<TableListDataChangeDetail>) => {
|
||||
const { data: eventData } = event.detail || {};
|
||||
const rows = eventData || [];
|
||||
|
||||
if (Array.isArray(rows)) {
|
||||
// 필터 적용
|
||||
const filteredData = applyFilters(
|
||||
rows,
|
||||
filtersRef.current || [],
|
||||
@@ -293,8 +296,8 @@ export function AggregationWidgetComponent({
|
||||
}
|
||||
};
|
||||
|
||||
// 리피터에서 발생하는 이벤트
|
||||
const handleRepeaterDataChange = (event: CustomEvent) => {
|
||||
// 리피터 데이터 변경 이벤트 (V2 표준)
|
||||
const handleRepeaterDataChange = (event: CustomEvent<RepeaterDataChangeDetail>) => {
|
||||
const { data: eventData, selectedData } = event.detail || {};
|
||||
const rows = selectedData || eventData || [];
|
||||
|
||||
@@ -310,38 +313,13 @@ export function AggregationWidgetComponent({
|
||||
}
|
||||
};
|
||||
|
||||
// 일반 선택 이벤트
|
||||
const handleSelectionChange = (event: CustomEvent) => {
|
||||
const { selectedRows: eventSelectedRows, selectedData, checkedRows, selectedItems } = event.detail || {};
|
||||
const rows = selectedData || eventSelectedRows || checkedRows || selectedItems || [];
|
||||
|
||||
if (Array.isArray(rows)) {
|
||||
const filteredData = applyFilters(
|
||||
rows,
|
||||
filtersRef.current || [],
|
||||
filterLogic,
|
||||
formDataRef.current,
|
||||
selectedRowsRef.current
|
||||
);
|
||||
setData(filteredData);
|
||||
}
|
||||
};
|
||||
|
||||
// 다양한 선택 이벤트 수신
|
||||
window.addEventListener("tableListDataChange" as any, handleTableListDataChange);
|
||||
window.addEventListener("repeaterDataChange" as any, handleRepeaterDataChange);
|
||||
window.addEventListener("selectionChange" as any, handleSelectionChange);
|
||||
window.addEventListener("tableSelectionChange" as any, handleSelectionChange);
|
||||
window.addEventListener("rowSelectionChange" as any, handleSelectionChange);
|
||||
window.addEventListener("checkboxSelectionChange" as any, handleSelectionChange);
|
||||
// V2 표준 이벤트만 구독 (중복 이벤트 제거)
|
||||
const unsubscribeTableList = subscribeV2Event(V2_EVENTS.TABLE_LIST_DATA_CHANGE, handleTableListDataChange);
|
||||
const unsubscribeRepeater = subscribeV2Event(V2_EVENTS.REPEATER_DATA_CHANGE, handleRepeaterDataChange);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("tableListDataChange" as any, handleTableListDataChange);
|
||||
window.removeEventListener("repeaterDataChange" as any, handleRepeaterDataChange);
|
||||
window.removeEventListener("selectionChange" as any, handleSelectionChange);
|
||||
window.removeEventListener("tableSelectionChange" as any, handleSelectionChange);
|
||||
window.removeEventListener("rowSelectionChange" as any, handleSelectionChange);
|
||||
window.removeEventListener("checkboxSelectionChange" as any, handleSelectionChange);
|
||||
unsubscribeTableList();
|
||||
unsubscribeRepeater();
|
||||
};
|
||||
}, [dataSourceType, isDesignMode, filterLogic]);
|
||||
|
||||
@@ -362,14 +340,17 @@ export function AggregationWidgetComponent({
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [externalDataKey, filterLogic]);
|
||||
|
||||
// ============================================================
|
||||
// 컴포넌트 데이터 변경 이벤트 리스닝 (dataSourceType === "component"일 때)
|
||||
// V2 표준 이벤트만 사용
|
||||
// ============================================================
|
||||
useEffect(() => {
|
||||
if (dataSourceType !== "component" || !dataSourceComponentId || isDesignMode) return;
|
||||
|
||||
const handleDataChange = (event: CustomEvent) => {
|
||||
// 테이블 리스트 데이터 변경
|
||||
const handleTableListDataChange = (event: CustomEvent<TableListDataChangeDetail>) => {
|
||||
const { componentId, data: eventData } = event.detail || {};
|
||||
if (componentId === dataSourceComponentId && Array.isArray(eventData)) {
|
||||
// 필터 적용
|
||||
const filteredData = applyFilters(
|
||||
eventData,
|
||||
filtersRef.current || [],
|
||||
@@ -381,33 +362,31 @@ export function AggregationWidgetComponent({
|
||||
}
|
||||
};
|
||||
|
||||
// 선택 변경 이벤트 (체크박스 선택 등)
|
||||
const handleSelectionChange = (event: CustomEvent) => {
|
||||
const { componentId, selectedData } = event.detail || {};
|
||||
if (componentId === dataSourceComponentId && Array.isArray(selectedData)) {
|
||||
// 선택된 데이터만 집계
|
||||
const filteredData = applyFilters(
|
||||
selectedData,
|
||||
filtersRef.current || [],
|
||||
filterLogic,
|
||||
formDataRef.current,
|
||||
selectedRowsRef.current
|
||||
);
|
||||
setData(filteredData);
|
||||
// 리피터 데이터 변경
|
||||
const handleRepeaterDataChange = (event: CustomEvent<RepeaterDataChangeDetail>) => {
|
||||
const { componentId, data: eventData, selectedData } = event.detail || {};
|
||||
if (componentId === dataSourceComponentId) {
|
||||
const rows = selectedData || eventData || [];
|
||||
if (Array.isArray(rows)) {
|
||||
const filteredData = applyFilters(
|
||||
rows,
|
||||
filtersRef.current || [],
|
||||
filterLogic,
|
||||
formDataRef.current,
|
||||
selectedRowsRef.current
|
||||
);
|
||||
setData(filteredData);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 리피터 데이터 변경 이벤트
|
||||
window.addEventListener("repeaterDataChange" as any, handleDataChange);
|
||||
// 테이블 리스트 데이터 변경 이벤트
|
||||
window.addEventListener("tableListDataChange" as any, handleDataChange);
|
||||
// 선택 변경 이벤트
|
||||
window.addEventListener("selectionChange" as any, handleSelectionChange);
|
||||
// V2 표준 이벤트만 구독
|
||||
const unsubscribeTableList = subscribeV2Event(V2_EVENTS.TABLE_LIST_DATA_CHANGE, handleTableListDataChange);
|
||||
const unsubscribeRepeater = subscribeV2Event(V2_EVENTS.REPEATER_DATA_CHANGE, handleRepeaterDataChange);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("repeaterDataChange" as any, handleDataChange);
|
||||
window.removeEventListener("tableListDataChange" as any, handleDataChange);
|
||||
window.removeEventListener("selectionChange" as any, handleSelectionChange);
|
||||
unsubscribeTableList();
|
||||
unsubscribeRepeater();
|
||||
};
|
||||
}, [dataSourceType, dataSourceComponentId, isDesignMode, filterLogic]);
|
||||
|
||||
|
||||
@@ -8,6 +8,9 @@ import { cn } from "@/lib/utils";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import DynamicComponentRenderer from "@/lib/registry/DynamicComponentRenderer";
|
||||
|
||||
// V2 이벤트 시스템
|
||||
import { V2_EVENTS, subscribeV2Event, type TableListDataChangeDetail, type RepeaterDataChangeDetail } from "@/types/component-events";
|
||||
|
||||
interface RepeatContainerComponentProps extends ComponentRendererProps {
|
||||
config?: RepeatContainerConfig;
|
||||
// 외부에서 데이터를 직접 전달받을 수 있음
|
||||
@@ -136,7 +139,10 @@ export function RepeatContainerComponent({
|
||||
}
|
||||
}, [externalData]);
|
||||
|
||||
// 컴포넌트 데이터 변경 이벤트 리스닝 (componentId 또는 tableName으로 매칭)
|
||||
// ============================================================
|
||||
// 컴포넌트 데이터 변경 이벤트 리스닝 (V2 표준 이벤트)
|
||||
// componentId 또는 tableName으로 매칭
|
||||
// ============================================================
|
||||
useEffect(() => {
|
||||
if (isDesignMode) return;
|
||||
|
||||
@@ -147,19 +153,12 @@ export function RepeatContainerComponent({
|
||||
effectiveTableName,
|
||||
});
|
||||
|
||||
// dataSourceComponentId가 없어도 테이블명으로 매칭 가능
|
||||
const handleDataChange = (event: CustomEvent) => {
|
||||
const { componentId, tableName: eventTableName, data: eventData } = event.detail || {};
|
||||
|
||||
console.log("📩 리피터 컨테이너 이벤트 수신:", {
|
||||
eventType: event.type,
|
||||
fromComponentId: componentId,
|
||||
fromTableName: eventTableName,
|
||||
dataCount: Array.isArray(eventData) ? eventData.length : 0,
|
||||
myDataSourceComponentId: dataSourceComponentId,
|
||||
myEffectiveTableName: effectiveTableName,
|
||||
});
|
||||
|
||||
// 공통 데이터 처리 함수
|
||||
const processIncomingData = (
|
||||
componentId: string | undefined,
|
||||
eventTableName: string | undefined,
|
||||
eventData: any[]
|
||||
) => {
|
||||
// 1. 명시적으로 dataSourceComponentId가 설정된 경우 해당 컴포넌트만 매칭
|
||||
if (dataSourceComponentId) {
|
||||
if (componentId === dataSourceComponentId && Array.isArray(eventData)) {
|
||||
@@ -167,8 +166,6 @@ export function RepeatContainerComponent({
|
||||
setData(eventData);
|
||||
setCurrentPage(1);
|
||||
setSelectedIndices([]);
|
||||
} else {
|
||||
console.log("⚠️ 리피터: 컴포넌트 ID 불일치로 무시", { expected: dataSourceComponentId, received: componentId });
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -179,17 +176,28 @@ export function RepeatContainerComponent({
|
||||
setData(eventData);
|
||||
setCurrentPage(1);
|
||||
setSelectedIndices([]);
|
||||
} else if (effectiveTableName) {
|
||||
console.log("⚠️ 리피터: 테이블명 불일치로 무시", { expected: effectiveTableName, received: eventTableName });
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener("repeaterDataChange" as any, handleDataChange);
|
||||
window.addEventListener("tableListDataChange" as any, handleDataChange);
|
||||
// 테이블 리스트 데이터 변경 이벤트 (V2 표준)
|
||||
const handleTableListDataChange = (event: CustomEvent<TableListDataChangeDetail>) => {
|
||||
const { componentId, tableName: eventTableName, data: eventData } = event.detail || {};
|
||||
processIncomingData(componentId, eventTableName, eventData);
|
||||
};
|
||||
|
||||
// 리피터 데이터 변경 이벤트 (V2 표준)
|
||||
const handleRepeaterDataChange = (event: CustomEvent<RepeaterDataChangeDetail>) => {
|
||||
const { componentId, tableName: eventTableName, data: eventData } = event.detail || {};
|
||||
processIncomingData(componentId, eventTableName, eventData);
|
||||
};
|
||||
|
||||
// V2 표준 이벤트 구독
|
||||
const unsubscribeTableList = subscribeV2Event(V2_EVENTS.TABLE_LIST_DATA_CHANGE, handleTableListDataChange);
|
||||
const unsubscribeRepeater = subscribeV2Event(V2_EVENTS.REPEATER_DATA_CHANGE, handleRepeaterDataChange);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("repeaterDataChange" as any, handleDataChange);
|
||||
window.removeEventListener("tableListDataChange" as any, handleDataChange);
|
||||
unsubscribeTableList();
|
||||
unsubscribeRepeater();
|
||||
};
|
||||
}, [component?.id, dataSourceType, dataSourceComponentId, effectiveTableName, isDesignMode]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user