feat: Enhance EditModal and V2Repeater functionality
- Implemented zone offset adjustments for conditional components in EditModal to ensure correct rendering positions. - Added repeaterSave event dispatching in EditModal after saving data, improving integration with V2Repeater. - Updated V2Repeater to handle existing detail data loading based on foreign key relationships, enhancing data management. - Improved calculation rules handling in V2RepeaterConfigPanel, allowing for dynamic updates and better user experience. - Enhanced SplitPanelLayoutComponent to conditionally load data based on selected items and tab changes, improving performance and usability.
This commit is contained in:
@@ -1526,22 +1526,30 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||
[componentConfig.rightPanel?.additionalTabs, isDesignMode, toast],
|
||||
);
|
||||
|
||||
// 탭 변경 핸들러 (좌측 미선택 시에도 전체 데이터 로드)
|
||||
// 탭 변경 핸들러
|
||||
const handleTabChange = useCallback(
|
||||
(newTabIndex: number) => {
|
||||
setActiveTabIndex(newTabIndex);
|
||||
|
||||
// 메인 패널이 "detail"(선택 시 표시)이면 좌측 미선택 시 데이터 로드하지 않음
|
||||
const mainRelationType = componentConfig.rightPanel?.relation?.type || "detail";
|
||||
const requireSelection = mainRelationType === "detail";
|
||||
|
||||
if (newTabIndex === 0) {
|
||||
if (!rightData || (Array.isArray(rightData) && rightData.length === 0)) {
|
||||
loadRightData(selectedLeftItem);
|
||||
if (!requireSelection || selectedLeftItem) {
|
||||
loadRightData(selectedLeftItem);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!tabsData[newTabIndex]) {
|
||||
loadTabData(newTabIndex, selectedLeftItem);
|
||||
if (!requireSelection || selectedLeftItem) {
|
||||
loadTabData(newTabIndex, selectedLeftItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
[selectedLeftItem, rightData, tabsData, loadRightData, loadTabData],
|
||||
[selectedLeftItem, rightData, tabsData, loadRightData, loadTabData, componentConfig.rightPanel?.relation?.type],
|
||||
);
|
||||
|
||||
// 좌측 항목 선택 핸들러 (동일 항목 재클릭 시 선택 해제 → 전체 데이터 표시)
|
||||
@@ -1554,24 +1562,31 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||
selectedLeftItem[leftPk] === item[leftPk];
|
||||
|
||||
if (isSameItem) {
|
||||
// 선택 해제 → 전체 데이터 로드
|
||||
// 선택 해제
|
||||
setSelectedLeftItem(null);
|
||||
setCustomLeftSelectedData({}); // 커스텀 모드 우측 폼 데이터 초기화
|
||||
setCustomLeftSelectedData({});
|
||||
setExpandedRightItems(new Set());
|
||||
setTabsData({});
|
||||
if (activeTabIndex === 0) {
|
||||
loadRightData(null);
|
||||
|
||||
const mainRelationType = componentConfig.rightPanel?.relation?.type || "detail";
|
||||
if (mainRelationType === "detail") {
|
||||
// "선택 시 표시" 모드: 선택 해제 시 데이터 비움
|
||||
setRightData(null);
|
||||
} else {
|
||||
loadTabData(activeTabIndex, null);
|
||||
}
|
||||
// 추가 탭들도 전체 데이터 로드
|
||||
const tabs = componentConfig.rightPanel?.additionalTabs;
|
||||
if (tabs && tabs.length > 0) {
|
||||
tabs.forEach((_: any, idx: number) => {
|
||||
if (idx + 1 !== activeTabIndex) {
|
||||
loadTabData(idx + 1, null);
|
||||
}
|
||||
});
|
||||
// "연관 목록" 모드: 선택 해제 시 전체 데이터 로드
|
||||
if (activeTabIndex === 0) {
|
||||
loadRightData(null);
|
||||
} else {
|
||||
loadTabData(activeTabIndex, null);
|
||||
}
|
||||
const tabs = componentConfig.rightPanel?.additionalTabs;
|
||||
if (tabs && tabs.length > 0) {
|
||||
tabs.forEach((_: any, idx: number) => {
|
||||
if (idx + 1 !== activeTabIndex) {
|
||||
loadTabData(idx + 1, null);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -2778,15 +2793,17 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||
if (relationshipType === "join") {
|
||||
loadRightData(null);
|
||||
}
|
||||
// 추가 탭: 각 탭의 relation.type에 따라 초기 로드 결정
|
||||
const tabs = componentConfig.rightPanel?.additionalTabs;
|
||||
if (tabs && tabs.length > 0) {
|
||||
tabs.forEach((tab: any, idx: number) => {
|
||||
const tabRelType = tab.relation?.type || "join";
|
||||
if (tabRelType === "join") {
|
||||
loadTabData(idx + 1, null);
|
||||
}
|
||||
});
|
||||
// 추가 탭: 메인 패널이 "detail"(선택 시 표시)이면 추가 탭도 초기 로드하지 않음
|
||||
if (relationshipType !== "detail") {
|
||||
const tabs = componentConfig.rightPanel?.additionalTabs;
|
||||
if (tabs && tabs.length > 0) {
|
||||
tabs.forEach((tab: any, idx: number) => {
|
||||
const tabRelType = tab.relation?.type || "join";
|
||||
if (tabRelType === "join") {
|
||||
loadTabData(idx + 1, null);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
@@ -3734,6 +3751,17 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||
const currentTabData = tabsData[activeTabIndex] || [];
|
||||
const isTabLoading = tabsLoading[activeTabIndex];
|
||||
|
||||
// 메인 패널이 "detail"(선택 시 표시)이면 좌측 미선택 시 안내 메시지
|
||||
const mainRelationType = componentConfig.rightPanel?.relation?.type || "detail";
|
||||
if (mainRelationType === "detail" && !selectedLeftItem && !isDesignMode) {
|
||||
return (
|
||||
<div className="text-muted-foreground flex h-full flex-col items-center justify-center gap-2 py-12 text-sm">
|
||||
<p>좌측에서 항목을 선택하세요</p>
|
||||
<p className="text-xs">선택한 항목의 관련 데이터가 여기에 표시됩니다</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (isTabLoading) {
|
||||
return (
|
||||
<div className="flex h-32 items-center justify-center">
|
||||
|
||||
Reference in New Issue
Block a user