feat: 모달 저장 후 부모 화면 테이블 자동 새로고침 기능 추가

- ScreenModal에 onRefresh 콜백 추가하여 refreshTable 이벤트 발송
- InteractiveScreenViewerDynamic에 onRefresh, onFlowRefresh prop 추가 및 하위 컴포넌트로 전달
- TableListComponent에 refreshTable 이벤트 리스너 추가
- SplitPanelLayoutComponent에 refreshTable 이벤트 리스너 추가하여 좌/우측 패널 모두 새로고침
- 모달에서 데이터 저장 시 부모 화면의 모든 테이블 컴포넌트가 자동으로 새로고침되도록 개선

변경된 파일:
- frontend/components/common/ScreenModal.tsx
- frontend/components/screen/InteractiveScreenViewerDynamic.tsx
- frontend/lib/registry/components/table-list/TableListComponent.tsx
- frontend/lib/registry/components/split-panel-layout/SplitPanelLayoutComponent.tsx
This commit is contained in:
kjs 2025-11-13 17:42:20 +09:00
parent ab1cbd37b3
commit 2a52f25c10
4 changed files with 50 additions and 3 deletions

View File

@ -414,6 +414,11 @@ export const ScreenModal: React.FC<ScreenModalProps> = ({ className }) => {
return newFormData;
});
}}
onRefresh={() => {
// 부모 화면의 테이블 새로고침 이벤트 발송
console.log("🔄 모달에서 부모 화면 테이블 새로고침 이벤트 발송");
window.dispatchEvent(new CustomEvent("refreshTable"));
}}
screenInfo={{
id: modalState.screenId!,
tableName: screenData.screenInfo?.tableName,

View File

@ -40,6 +40,8 @@ interface InteractiveScreenViewerProps {
tableName?: string;
};
onSave?: () => Promise<void>;
onRefresh?: () => void;
onFlowRefresh?: () => void;
}
export const InteractiveScreenViewerDynamic: React.FC<InteractiveScreenViewerProps> = ({
@ -50,6 +52,8 @@ export const InteractiveScreenViewerDynamic: React.FC<InteractiveScreenViewerPro
hideLabel = false,
screenInfo,
onSave,
onRefresh,
onFlowRefresh,
}) => {
const { isPreviewMode } = useScreenPreview(); // 프리뷰 모드 확인
const { userName, user } = useAuth();
@ -324,9 +328,11 @@ export const InteractiveScreenViewerDynamic: React.FC<InteractiveScreenViewerPro
setFlowSelectedData(selectedData);
setFlowSelectedStepId(stepId);
}}
onRefresh={() => {
// 테이블 컴포넌트는 자체적으로 loadData 호출
}}
onRefresh={onRefresh || (() => {
// 부모로부터 전달받은 onRefresh 또는 기본 동작
console.log("🔄 InteractiveScreenViewerDynamic onRefresh 호출");
})}
onFlowRefresh={onFlowRefresh}
onClose={() => {
// buttonActions.ts가 이미 처리함
}}

View File

@ -962,6 +962,26 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [leftFilters]);
// 🆕 전역 테이블 새로고침 이벤트 리스너
useEffect(() => {
const handleRefreshTable = () => {
if (!isDesignMode) {
console.log("🔄 [SplitPanel] refreshTable 이벤트 수신 - 데이터 새로고침");
loadLeftData();
// 선택된 항목이 있으면 우측 패널도 새로고침
if (selectedLeftItem) {
loadRightData(selectedLeftItem);
}
}
};
window.addEventListener("refreshTable", handleRefreshTable);
return () => {
window.removeEventListener("refreshTable", handleRefreshTable);
};
}, [isDesignMode, loadLeftData, loadRightData, selectedLeftItem]);
// 리사이저 드래그 핸들러
const handleMouseDown = (e: React.MouseEvent) => {
if (!resizable) return;

View File

@ -1766,6 +1766,22 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
}
}, [tableConfig.refreshInterval, isDesignMode]);
// 🆕 전역 테이블 새로고침 이벤트 리스너
useEffect(() => {
const handleRefreshTable = () => {
if (tableConfig.selectedTable && !isDesignMode) {
console.log("🔄 [TableList] refreshTable 이벤트 수신 - 데이터 새로고침");
setRefreshTrigger((prev) => prev + 1);
}
};
window.addEventListener("refreshTable", handleRefreshTable);
return () => {
window.removeEventListener("refreshTable", handleRefreshTable);
};
}, [tableConfig.selectedTable, isDesignMode]);
// 초기 컬럼 너비 측정 (한 번만)
useEffect(() => {
if (!hasInitializedWidths.current && visibleColumns.length > 0) {