이력테이블 기준 컬럼 설정 기능
This commit is contained in:
parent
5fdefffd26
commit
a3bfcdf2d8
|
|
@ -359,12 +359,9 @@ export function TableHistoryModal({
|
|||
{!recordId && (
|
||||
<td className="p-2">
|
||||
{displayValue ? (
|
||||
<div className="flex flex-col">
|
||||
<span className="font-medium text-gray-900">{displayValue}</span>
|
||||
<span className="text-xs text-gray-500">(ID: {record.original_id})</span>
|
||||
</div>
|
||||
<span className="font-medium text-gray-900">{displayValue}</span>
|
||||
) : (
|
||||
<span className="font-mono font-medium text-blue-600">{record.original_id}</span>
|
||||
<span className="text-muted-foreground text-xs">-</span>
|
||||
)}
|
||||
</td>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -136,11 +136,6 @@ export const RealtimePreviewDynamic: React.FC<RealtimePreviewProps> = ({
|
|||
// 컴포넌트의 실제 size.height도 업데이트 (중복 업데이트 방지)
|
||||
if (onConfigChange && finalHeight !== lastUpdatedHeight.current && finalHeight !== component.size?.height) {
|
||||
lastUpdatedHeight.current = finalHeight;
|
||||
console.log("🔄 플로우 위젯 높이 업데이트 이벤트 발송:", {
|
||||
componentId: component.id,
|
||||
oldHeight: component.size?.height,
|
||||
newHeight: finalHeight,
|
||||
});
|
||||
// size는 별도 속성이므로 직접 업데이트
|
||||
const event = new CustomEvent("updateComponentSize", {
|
||||
detail: {
|
||||
|
|
|
|||
|
|
@ -258,16 +258,6 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD
|
|||
window.dispatchEvent(syncEvent);
|
||||
});
|
||||
|
||||
console.log("✅ DB 파일 컴포넌트 데이터 복원 완료:", {
|
||||
totalComponents: components.length,
|
||||
restoredFileComponents: restoredCount,
|
||||
totalFiles: fileResponse.totalFiles,
|
||||
globalFileState: Object.keys(globalFileState).map((id) => ({
|
||||
id,
|
||||
fileCount: globalFileState[id]?.length || 0,
|
||||
})),
|
||||
});
|
||||
|
||||
if (restoredCount > 0) {
|
||||
toast.success(
|
||||
`${restoredCount}개 파일 컴포넌트 데이터가 DB에서 복원되었습니다. (총 ${fileResponse.totalFiles}개 파일)`,
|
||||
|
|
@ -322,15 +312,6 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD
|
|||
snapToGrid: layout.gridSettings.snapToGrid || false,
|
||||
});
|
||||
|
||||
console.log("🧮 격자 정보 재계산:", {
|
||||
resolution: `${width}x${height}`,
|
||||
columns: layout.gridSettings.columns,
|
||||
gap: layout.gridSettings.gap,
|
||||
padding: layout.gridSettings.padding,
|
||||
columnWidth: newGridInfo.columnWidth.toFixed(2),
|
||||
snapToGrid: layout.gridSettings.snapToGrid,
|
||||
});
|
||||
|
||||
return newGridInfo;
|
||||
}, [layout.gridSettings, screenResolution]);
|
||||
|
||||
|
|
@ -425,13 +406,6 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD
|
|||
// 컴포넌트 속성 업데이트
|
||||
const updateComponentProperty = useCallback(
|
||||
(componentId: string, path: string, value: any) => {
|
||||
console.log("⚙️ 컴포넌트 속성 업데이트:", {
|
||||
componentId,
|
||||
path,
|
||||
value,
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
|
||||
// 🔥 함수형 업데이트로 변경하여 최신 layout 사용
|
||||
setLayout((prevLayout) => {
|
||||
const targetComponent = prevLayout.components.find((comp) => comp.id === componentId);
|
||||
|
|
@ -494,26 +468,16 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD
|
|||
// 중첩 경로를 고려한 안전한 복사
|
||||
const newComp = { ...comp };
|
||||
|
||||
console.log("🔍 업데이트 전 상태:", {
|
||||
path,
|
||||
value,
|
||||
"기존 componentConfig": newComp.componentConfig,
|
||||
"기존 action": (newComp as any).componentConfig?.action,
|
||||
});
|
||||
|
||||
// 경로를 따라 내려가면서 각 레벨을 새 객체로 복사
|
||||
let current: any = newComp;
|
||||
for (let i = 0; i < pathParts.length - 1; i++) {
|
||||
const key = pathParts[i];
|
||||
console.log(`🔍 경로 탐색 [${i}]: key="${key}", current[key]=`, current[key]);
|
||||
|
||||
// 다음 레벨이 없거나 객체가 아니면 새 객체 생성
|
||||
if (!current[key] || typeof current[key] !== "object" || Array.isArray(current[key])) {
|
||||
console.log(`🆕 새 객체 생성: ${key}`);
|
||||
current[key] = {};
|
||||
} else {
|
||||
// 기존 객체를 복사하여 불변성 유지
|
||||
console.log(`📋 기존 객체 복사: ${key}`, { ...current[key] });
|
||||
current[key] = { ...current[key] };
|
||||
}
|
||||
current = current[key];
|
||||
|
|
@ -521,58 +485,12 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD
|
|||
|
||||
// 최종 값 설정
|
||||
const finalKey = pathParts[pathParts.length - 1];
|
||||
console.log(`✍️ 최종 값 설정: ${finalKey} = ${value}`);
|
||||
current[finalKey] = value;
|
||||
|
||||
console.log("✅ 컴포넌트 업데이트 완료:", {
|
||||
componentId,
|
||||
path,
|
||||
newValue: current[pathParts[pathParts.length - 1]],
|
||||
fullComponent: newComp,
|
||||
webTypeConfig: newComp.type === "widget" ? (newComp as any).webTypeConfig : null,
|
||||
});
|
||||
|
||||
// webTypeConfig 업데이트의 경우 추가 검증
|
||||
if (path === "webTypeConfig") {
|
||||
console.log("🎛️ webTypeConfig 특별 처리:", {
|
||||
componentId,
|
||||
oldConfig: comp.type === "widget" ? (comp as any).webTypeConfig : null,
|
||||
newConfig: current[pathParts[pathParts.length - 1]],
|
||||
configType: typeof current[pathParts[pathParts.length - 1]],
|
||||
configStringified: JSON.stringify(current[pathParts[pathParts.length - 1]]),
|
||||
oldConfigStringified: JSON.stringify(comp.type === "widget" ? (comp as any).webTypeConfig : null),
|
||||
isConfigChanged:
|
||||
JSON.stringify(comp.type === "widget" ? (comp as any).webTypeConfig : null) !==
|
||||
JSON.stringify(current[pathParts[pathParts.length - 1]]),
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
}
|
||||
|
||||
// gridColumns 변경 시 크기 자동 업데이트
|
||||
console.log("🔍 gridColumns 변경 감지:", {
|
||||
path,
|
||||
value,
|
||||
componentType: newComp.type,
|
||||
hasGridInfo: !!gridInfo,
|
||||
hasGridSettings: !!layout.gridSettings,
|
||||
currentGridColumns: (newComp as any).gridColumns,
|
||||
});
|
||||
|
||||
if (path === "gridColumns" && gridInfo) {
|
||||
const updatedSize = updateSizeFromGridColumns(newComp, gridInfo, layout.gridSettings as GridUtilSettings);
|
||||
newComp.size = updatedSize;
|
||||
console.log("📏 gridColumns 변경으로 크기 업데이트:", {
|
||||
gridColumns: value,
|
||||
oldSize: comp.size,
|
||||
newSize: updatedSize,
|
||||
});
|
||||
} else if (path === "gridColumns") {
|
||||
console.log("❌ gridColumns 변경 실패:", {
|
||||
hasGridInfo: !!gridInfo,
|
||||
hasGridSettings: !!layout.gridSettings,
|
||||
gridInfo,
|
||||
gridSettings: layout.gridSettings,
|
||||
});
|
||||
}
|
||||
|
||||
// 크기 변경 시 격자 스냅 적용 (그룹 컴포넌트 제외)
|
||||
|
|
@ -604,11 +522,6 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD
|
|||
);
|
||||
if (newComp.gridColumns !== adjustedColumns) {
|
||||
newComp.gridColumns = adjustedColumns;
|
||||
console.log("📏 크기 변경으로 gridColumns 자동 조정:", {
|
||||
oldColumns: comp.gridColumns,
|
||||
newColumns: adjustedColumns,
|
||||
newSize: snappedSize,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -631,15 +544,6 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD
|
|||
...newComp.size,
|
||||
width: newWidth,
|
||||
};
|
||||
|
||||
console.log("📐 gridColumns 변경으로 크기 자동 조정:", {
|
||||
componentId,
|
||||
gridColumns: newComp.gridColumns,
|
||||
oldWidth: comp.size.width,
|
||||
newWidth: newWidth,
|
||||
columnWidth: currentGridInfo.columnWidth,
|
||||
gap: layout.gridSettings.gap,
|
||||
});
|
||||
}
|
||||
|
||||
// 위치 변경 시 격자 스냅 적용 (그룹 내부 컴포넌트 포함)
|
||||
|
|
@ -687,26 +591,6 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD
|
|||
width: snappedWidth,
|
||||
height: snappedHeight,
|
||||
};
|
||||
|
||||
console.log("🎯 그룹 내부 컴포넌트 격자 스냅 (패딩 고려):", {
|
||||
componentId,
|
||||
parentId: newComp.parentId,
|
||||
originalPosition: comp.position,
|
||||
originalSize: comp.size,
|
||||
calculation: {
|
||||
effectiveX,
|
||||
effectiveY,
|
||||
columnIndex,
|
||||
rowIndex,
|
||||
columnWidth,
|
||||
fullColumnWidth,
|
||||
widthInColumns,
|
||||
gap: gap || 16,
|
||||
padding,
|
||||
},
|
||||
snappedPosition: newComp.position,
|
||||
snappedSize: newComp.size,
|
||||
});
|
||||
} else if (newComp.type !== "group") {
|
||||
// 그룹이 아닌 일반 컴포넌트만 격자 스냅 적용
|
||||
const snappedPosition = snapToGrid(
|
||||
|
|
@ -715,18 +599,6 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD
|
|||
layout.gridSettings as GridUtilSettings,
|
||||
);
|
||||
newComp.position = snappedPosition;
|
||||
|
||||
console.log("🧲 일반 컴포넌트 격자 스냅:", {
|
||||
componentId,
|
||||
originalPosition: comp.position,
|
||||
snappedPosition,
|
||||
});
|
||||
} else {
|
||||
console.log("🔓 그룹 컴포넌트는 격자 스냅 제외:", {
|
||||
componentId,
|
||||
type: newComp.type,
|
||||
position: newComp.position,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -736,13 +608,6 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD
|
|||
// 🔥 새로운 layout 생성
|
||||
const newLayout = { ...prevLayout, components: updatedComponents };
|
||||
|
||||
console.log("🔄 setLayout 실행:", {
|
||||
componentId,
|
||||
path,
|
||||
value,
|
||||
업데이트된컴포넌트: updatedComponents.find((c) => c.id === componentId),
|
||||
});
|
||||
|
||||
saveToHistory(newLayout);
|
||||
|
||||
// selectedComponent가 업데이트된 컴포넌트와 같다면 selectedComponent도 업데이트
|
||||
|
|
@ -752,20 +617,6 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD
|
|||
if (updatedSelectedComponent) {
|
||||
// 🔧 완전히 새로운 객체를 만들어서 React가 변경을 감지하도록 함
|
||||
const newSelectedComponent = JSON.parse(JSON.stringify(updatedSelectedComponent));
|
||||
|
||||
console.log("🔄 selectedComponent 동기화:", {
|
||||
componentId,
|
||||
path,
|
||||
oldAction: (prevSelected as any).componentConfig?.action,
|
||||
newAction: (newSelectedComponent as any).componentConfig?.action,
|
||||
oldColumnsCount: prevSelected.type === "datatable" ? (prevSelected as any).columns?.length : "N/A",
|
||||
newColumnsCount:
|
||||
newSelectedComponent.type === "datatable" ? (newSelectedComponent as any).columns?.length : "N/A",
|
||||
oldFiltersCount: prevSelected.type === "datatable" ? (prevSelected as any).filters?.length : "N/A",
|
||||
newFiltersCount:
|
||||
newSelectedComponent.type === "datatable" ? (newSelectedComponent as any).filters?.length : "N/A",
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
return newSelectedComponent;
|
||||
}
|
||||
}
|
||||
|
|
@ -989,16 +840,8 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD
|
|||
let layoutToUse = response;
|
||||
|
||||
if (needsMigration(response)) {
|
||||
console.log("🔄 픽셀 기반 레이아웃 감지 - 그리드 시스템으로 마이그레이션 시작...");
|
||||
|
||||
const canvasWidth = response.screenResolution?.width || 1920;
|
||||
layoutToUse = safeMigrateLayout(response, canvasWidth);
|
||||
|
||||
console.log("✅ 마이그레이션 완료:", {
|
||||
originalComponents: response.components.length,
|
||||
migratedComponents: layoutToUse.components.length,
|
||||
sampleComponent: layoutToUse.components[0],
|
||||
});
|
||||
}
|
||||
|
||||
// 기본 격자 설정 보장 (격자 표시와 스냅 기본 활성화)
|
||||
|
|
@ -2224,16 +2067,6 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD
|
|||
...component.defaultSize,
|
||||
width: Math.max(calculatedWidth, minWidth),
|
||||
};
|
||||
|
||||
console.log(`📐 ${component.name} 초기 크기 자동 조정:`, {
|
||||
componentId: component.id,
|
||||
gridColumns,
|
||||
defaultWidth: component.defaultSize.width,
|
||||
calculatedWidth,
|
||||
finalWidth: componentSize.width,
|
||||
gridInfo,
|
||||
gridSettings: layout.gridSettings,
|
||||
});
|
||||
}
|
||||
|
||||
console.log("🎨 최종 컴포넌트 크기:", {
|
||||
|
|
@ -2858,18 +2691,6 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD
|
|||
return;
|
||||
}
|
||||
|
||||
console.log("🔍 컴포넌트 클릭 시 최신 버전 확인:", {
|
||||
componentId: component.id,
|
||||
파라미터로받은버전: {
|
||||
actionType: (component as any).componentConfig?.action?.type,
|
||||
fullAction: (component as any).componentConfig?.action,
|
||||
},
|
||||
layout에서찾은최신버전: {
|
||||
actionType: (latestComponent as any).componentConfig?.action?.type,
|
||||
fullAction: (latestComponent as any).componentConfig?.action,
|
||||
},
|
||||
});
|
||||
|
||||
const isShiftPressed = event?.shiftKey || false;
|
||||
const isCtrlPressed = event?.ctrlKey || event?.metaKey || false;
|
||||
const isGroupContainer = latestComponent.type === "group";
|
||||
|
|
@ -4218,30 +4039,17 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD
|
|||
const handleComponentSizeUpdate = (event: CustomEvent) => {
|
||||
const { componentId, height } = event.detail;
|
||||
|
||||
console.log("📥 ScreenDesigner에서 높이 업데이트 이벤트 수신:", {
|
||||
componentId,
|
||||
height,
|
||||
});
|
||||
|
||||
// 해당 컴포넌트 찾기
|
||||
const targetComponent = layout.components.find((c) => c.id === componentId);
|
||||
if (!targetComponent) {
|
||||
console.log("⚠️ 컴포넌트를 찾을 수 없음:", componentId);
|
||||
return;
|
||||
}
|
||||
|
||||
// 이미 같은 높이면 업데이트 안함
|
||||
if (targetComponent.size?.height === height) {
|
||||
console.log("ℹ️ 이미 같은 높이:", height);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log("✅ 컴포넌트 높이 업데이트 중:", {
|
||||
componentId,
|
||||
oldHeight: targetComponent.size?.height,
|
||||
newHeight: height,
|
||||
});
|
||||
|
||||
// 컴포넌트 높이 업데이트
|
||||
const updatedComponents = layout.components.map((comp) => {
|
||||
if (comp.id === componentId) {
|
||||
|
|
@ -4269,7 +4077,6 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD
|
|||
const updatedComponent = updatedComponents.find((c) => c.id === componentId);
|
||||
if (updatedComponent) {
|
||||
setSelectedComponent(updatedComponent);
|
||||
console.log("✅ 선택된 컴포넌트도 업데이트됨");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -39,13 +39,6 @@ export const ButtonConfigPanel: React.FC<ButtonConfigPanelProps> = ({
|
|||
const config = component.componentConfig || {};
|
||||
const currentAction = component.componentConfig?.action || {};
|
||||
|
||||
console.log("🎨 ButtonConfigPanel 렌더링:", {
|
||||
componentId: component.id,
|
||||
"component.componentConfig?.action?.type": component.componentConfig?.action?.type,
|
||||
currentTableName: currentTableName,
|
||||
"config.action?.historyTableName": config.action?.historyTableName,
|
||||
});
|
||||
|
||||
// 로컬 상태 관리 (실시간 입력 반영)
|
||||
const [localInputs, setLocalInputs] = useState({
|
||||
text: config.text !== undefined ? config.text : "버튼",
|
||||
|
|
@ -140,14 +133,6 @@ export const ButtonConfigPanel: React.FC<ButtonConfigPanelProps> = ({
|
|||
},
|
||||
});
|
||||
|
||||
console.log("📋 [ButtonConfigPanel] API 응답:", {
|
||||
tableName,
|
||||
success: response.data.success,
|
||||
hasData: !!response.data.data,
|
||||
hasColumns: !!response.data.data?.columns,
|
||||
totalColumns: response.data.data?.columns?.length,
|
||||
});
|
||||
|
||||
// API 응답 구조: { success, data: { columns: [...], total, page, totalPages } }
|
||||
const columnData = response.data.data?.columns;
|
||||
|
||||
|
|
@ -164,28 +149,13 @@ export const ButtonConfigPanel: React.FC<ButtonConfigPanelProps> = ({
|
|||
const colName = col.columnName.toLowerCase();
|
||||
const dataType = col.dataType?.toLowerCase() || "";
|
||||
|
||||
console.log(`🔍 [필터링 체크] ${col.columnName}:`, {
|
||||
colName,
|
||||
dataType,
|
||||
isId: colName === "id" || colName.endsWith("_id"),
|
||||
hasDateInType: dataType.includes("date") || dataType.includes("time") || dataType.includes("timestamp"),
|
||||
hasDateInName:
|
||||
colName.includes("date") ||
|
||||
colName.includes("time") ||
|
||||
colName.endsWith("_at") ||
|
||||
colName.startsWith("created") ||
|
||||
colName.startsWith("updated"),
|
||||
});
|
||||
|
||||
// ID 컬럼 제외 (id, _id로 끝나는 컬럼)
|
||||
if (colName === "id" || colName.endsWith("_id")) {
|
||||
console.log(` ❌ 제외: ID 컬럼`);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 날짜/시간 타입 제외 (데이터 타입 기준)
|
||||
if (dataType.includes("date") || dataType.includes("time") || dataType.includes("timestamp")) {
|
||||
console.log(` ❌ 제외: 날짜/시간 타입`);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -197,20 +167,13 @@ export const ButtonConfigPanel: React.FC<ButtonConfigPanelProps> = ({
|
|||
colName.startsWith("created") ||
|
||||
colName.startsWith("updated")
|
||||
) {
|
||||
console.log(` ❌ 제외: 날짜 관련 컬럼명`);
|
||||
return false;
|
||||
}
|
||||
|
||||
console.log(` ✅ 통과`);
|
||||
return true;
|
||||
})
|
||||
.map((col: any) => col.columnName);
|
||||
|
||||
console.log("✅ [ButtonConfigPanel] 필터링된 컬럼:", {
|
||||
totalFiltered: filteredColumns.length,
|
||||
columns: filteredColumns,
|
||||
});
|
||||
|
||||
setTableColumns(filteredColumns);
|
||||
}
|
||||
} catch (error) {
|
||||
|
|
@ -305,18 +268,12 @@ export const ButtonConfigPanel: React.FC<ButtonConfigPanelProps> = ({
|
|||
key={`action-${component.id}-${component.componentConfig?.action?.type || "save"}`}
|
||||
value={component.componentConfig?.action?.type || "save"}
|
||||
onValueChange={(value) => {
|
||||
console.log("🎯 버튼 액션 드롭다운 변경:", {
|
||||
oldValue: component.componentConfig?.action?.type,
|
||||
newValue: value,
|
||||
});
|
||||
|
||||
// 🔥 action.type 업데이트
|
||||
onUpdateProperty("componentConfig.action.type", value);
|
||||
|
||||
// 🔥 색상 업데이트는 충분히 지연 (React 리렌더링 완료 후)
|
||||
setTimeout(() => {
|
||||
const newColor = value === "delete" ? "#ef4444" : "#212121";
|
||||
console.log("🎨 라벨 색상 업데이트:", { value, newColor });
|
||||
onUpdateProperty("style.labelColor", newColor);
|
||||
}, 100); // 0 → 100ms로 증가
|
||||
}}
|
||||
|
|
@ -737,8 +694,8 @@ export const ButtonConfigPanel: React.FC<ButtonConfigPanelProps> = ({
|
|||
<p className="mt-2 text-xs text-gray-700">
|
||||
<strong>전체 테이블 이력</strong>에서 레코드를 구분하기 위한 컬럼입니다.
|
||||
<br />
|
||||
예: <code className="rounded bg-white px-1">device_code</code>를 설정하면 "레코드 ID: 5"
|
||||
대신 "DTG-001 (ID: 5)"로 표시됩니다.
|
||||
예: <code className="rounded bg-white px-1">device_code</code>를 설정하면 이력에 "DTG-001"로
|
||||
표시됩니다.
|
||||
<br />이 컬럼으로 검색도 가능합니다.
|
||||
</p>
|
||||
|
||||
|
|
|
|||
|
|
@ -79,27 +79,13 @@ export function FlowWidget({
|
|||
const effectiveSteps = stepsArray || steps;
|
||||
|
||||
// 1순위: 플로우 스텝 기본 설정
|
||||
console.log(`🔍 [FlowWidget] steps 배열 상태:`, {
|
||||
stepsLength: effectiveSteps.length,
|
||||
stepsIds: effectiveSteps.map((s) => s.id),
|
||||
targetStepId: stepId,
|
||||
});
|
||||
|
||||
const currentStep = effectiveSteps.find((s) => s.id === stepId);
|
||||
console.log(`🔍 [FlowWidget] currentStep 찾기 (스텝 ${stepId}):`, {
|
||||
found: !!currentStep,
|
||||
hasDisplayConfig: !!currentStep?.displayConfig,
|
||||
displayConfig: currentStep?.displayConfig,
|
||||
displayConfigType: typeof currentStep?.displayConfig,
|
||||
});
|
||||
|
||||
if (currentStep?.displayConfig?.visibleColumns && currentStep.displayConfig.visibleColumns.length > 0) {
|
||||
console.log(`🎨 [FlowWidget] 플로우 기본 설정 적용 (스텝 ${stepId}):`, currentStep.displayConfig.visibleColumns);
|
||||
return currentStep.displayConfig.visibleColumns;
|
||||
}
|
||||
|
||||
// 2순위: 모든 컬럼 표시
|
||||
console.log(`🎨 [FlowWidget] 전체 컬럼 표시 (스텝 ${stepId}):`, allColumns);
|
||||
return allColumns;
|
||||
};
|
||||
|
||||
|
|
@ -211,15 +197,6 @@ export function FlowWidget({
|
|||
}
|
||||
if (stepsResponse.data) {
|
||||
const sortedSteps = stepsResponse.data.sort((a: FlowStep, b: FlowStep) => a.stepOrder - b.stepOrder);
|
||||
console.log("📋 [FlowWidget] 스텝 목록 로드:", {
|
||||
stepsCount: sortedSteps.length,
|
||||
steps: sortedSteps.map((s: FlowStep) => ({
|
||||
id: s.id,
|
||||
name: s.stepName,
|
||||
hasDisplayConfig: !!s.displayConfig,
|
||||
displayConfig: s.displayConfig,
|
||||
})),
|
||||
});
|
||||
setSteps(sortedSteps);
|
||||
|
||||
// 연결 정보 조회
|
||||
|
|
@ -246,11 +223,6 @@ export function FlowWidget({
|
|||
const firstStep = sortedSteps[0];
|
||||
setSelectedStepId(firstStep.id);
|
||||
setSelectedStep(flowComponentId, firstStep.id);
|
||||
console.log("✅ [FlowWidget] 첫 번째 단계 자동 선택:", {
|
||||
flowComponentId,
|
||||
stepId: firstStep.id,
|
||||
stepName: firstStep.stepName,
|
||||
});
|
||||
|
||||
// 첫 번째 스텝의 데이터 로드
|
||||
try {
|
||||
|
|
@ -292,7 +264,6 @@ export function FlowWidget({
|
|||
// 🆕 언마운트 시 전역 상태 초기화
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
console.log("🧹 [FlowWidget] 언마운트 - 전역 상태 초기화:", flowComponentId);
|
||||
resetFlow(flowComponentId);
|
||||
};
|
||||
}, [flowComponentId, resetFlow]);
|
||||
|
|
@ -314,7 +285,6 @@ export function FlowWidget({
|
|||
setStepDataPage(1); // 🆕 페이지 리셋
|
||||
onSelectedDataChange?.([], null);
|
||||
|
||||
console.log("🔄 [FlowWidget] 단계 선택 해제:", { flowComponentId, stepId });
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -326,8 +296,6 @@ export function FlowWidget({
|
|||
setStepDataPage(1); // 🆕 페이지 리셋
|
||||
onSelectedDataChange?.([], stepId);
|
||||
|
||||
console.log("✅ [FlowWidget] 단계 선택:", { flowComponentId, stepId, stepName });
|
||||
|
||||
try {
|
||||
const response = await getStepDataList(flowId!, stepId, 1, 100);
|
||||
|
||||
|
|
|
|||
|
|
@ -333,7 +333,6 @@ export class AutoRegisteringComponentRenderer {
|
|||
}
|
||||
|
||||
if (this.registeredComponents.has(definition.id)) {
|
||||
console.warn(`⚠️ ${definition.id} 컴포넌트가 이미 등록되어 있습니다.`);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -341,18 +340,6 @@ export class AutoRegisteringComponentRenderer {
|
|||
// 레지스트리에 등록
|
||||
ComponentRegistry.registerComponent(definition);
|
||||
this.registeredComponents.add(definition.id);
|
||||
|
||||
console.log(`✅ 컴포넌트 자동 등록 완료: ${definition.id} (${definition.name})`);
|
||||
|
||||
// 개발 모드에서 추가 정보 출력
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
console.log(`📦 ${definition.id}:`, {
|
||||
name: definition.name,
|
||||
category: definition.category,
|
||||
webType: definition.webType,
|
||||
tags: definition.tags?.join(", ") || "none",
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`❌ ${definition.id} 컴포넌트 등록 실패:`, error);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,8 +52,6 @@ export class ComponentRegistry {
|
|||
timestamp: new Date(),
|
||||
});
|
||||
|
||||
console.log(`✅ 컴포넌트 등록: ${definition.id} (${definition.name})`);
|
||||
|
||||
// 개발자 도구 등록 (개발 모드에서만)
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
this.registerGlobalDevTools();
|
||||
|
|
@ -399,9 +397,6 @@ Hot Reload 제어 (비동기):
|
|||
`);
|
||||
},
|
||||
};
|
||||
|
||||
console.log("🛠️ 컴포넌트 레지스트리 개발자 도구가 등록되었습니다.");
|
||||
console.log(" 사용법: __COMPONENT_REGISTRY__.help()");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -409,17 +404,7 @@ Hot Reload 제어 (비동기):
|
|||
* 디버그 정보 출력
|
||||
*/
|
||||
static debug(): void {
|
||||
const stats = this.getStats();
|
||||
console.group("🎨 컴포넌트 레지스트리 디버그 정보");
|
||||
console.log("📊 총 컴포넌트 수:", stats.total);
|
||||
console.log("📂 카테고리별 분포:", stats.byCategory);
|
||||
console.log("🏷️ 웹타입별 분포:", stats.byWebType);
|
||||
console.log("👨💻 작성자별 분포:", stats.byAuthor);
|
||||
console.log(
|
||||
"🆕 최근 추가:",
|
||||
stats.recentlyAdded.map((c) => `${c.id} (${c.name})`),
|
||||
);
|
||||
console.groupEnd();
|
||||
// 디버그 로그 제거 (필요시 브라우저 콘솔에서 ComponentRegistry.getStats() 사용)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ export class FlowWidgetRenderer extends AutoRegisteringComponentRenderer {
|
|||
|
||||
render(): React.ReactElement {
|
||||
return (
|
||||
<FlowWidget
|
||||
component={this.props.component as any}
|
||||
<FlowWidget
|
||||
component={this.props.component as any}
|
||||
onSelectedDataChange={this.props.onFlowSelectedDataChange}
|
||||
flowRefreshKey={this.props.flowRefreshKey}
|
||||
onFlowRefresh={this.props.onFlowRefresh}
|
||||
|
|
@ -38,5 +38,3 @@ FlowWidgetRenderer.registerSelf();
|
|||
if (process.env.NODE_ENV === "development") {
|
||||
FlowWidgetRenderer.enableHotReload();
|
||||
}
|
||||
|
||||
console.log("✅ FlowWidget 컴포넌트 등록 완료");
|
||||
|
|
|
|||
|
|
@ -8,8 +8,6 @@ import { initializeHotReload } from "../utils/hotReload";
|
|||
* 모든 컴포넌트를 자동으로 로드하고 등록합니다
|
||||
*/
|
||||
|
||||
console.log("🚀 컴포넌트 시스템 초기화 시작...");
|
||||
|
||||
// 컴포넌트 자동 디스커버리 및 로드
|
||||
// 현재는 수동 import 방식 사용 (향후 자동 디스커버리로 확장 예정)
|
||||
|
||||
|
|
@ -46,16 +44,12 @@ import "./flow-widget/FlowWidgetRenderer";
|
|||
* 컴포넌트 초기화 함수
|
||||
*/
|
||||
export async function initializeComponents() {
|
||||
console.log("🔄 컴포넌트 초기화 중...");
|
||||
|
||||
try {
|
||||
// 1. 자동 등록된 컴포넌트 확인
|
||||
const registeredComponents = ComponentRegistry.getAllComponents();
|
||||
console.log(`✅ 등록된 컴포넌트: ${registeredComponents.length}개`);
|
||||
|
||||
// 2. 카테고리별 통계
|
||||
const stats = ComponentRegistry.getStats();
|
||||
console.log("📊 카테고리별 분포:", stats.byCategory);
|
||||
|
||||
// 3. 개발 모드에서 디버그 정보 출력
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
|
|
|
|||
|
|
@ -13,35 +13,31 @@ export class TableListRenderer extends AutoRegisteringComponentRenderer {
|
|||
static componentDefinition = TableListDefinition;
|
||||
|
||||
render(): React.ReactElement {
|
||||
return <TableListComponent
|
||||
{...this.props}
|
||||
renderer={this}
|
||||
onConfigChange={this.handleConfigChange}
|
||||
/>;
|
||||
return <TableListComponent {...this.props} renderer={this} onConfigChange={this.handleConfigChange} />;
|
||||
}
|
||||
|
||||
// 설정 변경 핸들러
|
||||
protected handleConfigChange = (config: any) => {
|
||||
console.log("📥 TableListRenderer에서 설정 변경 받음:", config);
|
||||
|
||||
|
||||
// 상위 컴포넌트의 onConfigChange 호출 (화면 설계자에게 알림)
|
||||
if (this.props.onConfigChange) {
|
||||
this.props.onConfigChange(config);
|
||||
} else {
|
||||
console.log("⚠️ 상위 컴포넌트에서 onConfigChange가 전달되지 않음");
|
||||
}
|
||||
|
||||
|
||||
this.updateComponent({ config });
|
||||
};
|
||||
|
||||
/**
|
||||
* 컴포넌트별 특화 메서드들
|
||||
*/
|
||||
|
||||
|
||||
// text 타입 특화 속성 처리
|
||||
protected getTableListProps() {
|
||||
const baseProps = this.getWebTypeProps();
|
||||
|
||||
|
||||
// text 타입에 특화된 추가 속성들
|
||||
return {
|
||||
...baseProps,
|
||||
|
|
@ -72,9 +68,7 @@ TableListRenderer.registerSelf();
|
|||
if (typeof window !== "undefined") {
|
||||
setTimeout(() => {
|
||||
try {
|
||||
console.log("🔄 TableList 강제 등록 시도...");
|
||||
TableListRenderer.registerSelf();
|
||||
console.log("✅ TableList 강제 등록 완료");
|
||||
} catch (error) {
|
||||
console.error("❌ TableList 강제 등록 실패:", error);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,10 +96,7 @@ export function createComponentDefinition(options: CreateComponentDefinitionOpti
|
|||
throw new Error(`컴포넌트 정의 검증 실패: ${validationResult.errors.join(", ")}`);
|
||||
}
|
||||
|
||||
// 경고사항 출력 (개발 모드에서만)
|
||||
if (process.env.NODE_ENV === "development" && validationResult.warnings.length > 0) {
|
||||
console.warn(`⚠️ 컴포넌트 정의 경고 (${id}):`, validationResult.warnings);
|
||||
}
|
||||
// 경고사항 출력 (개발 모드에서만) - 로그 제거
|
||||
|
||||
return definition;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,9 +15,8 @@ let hotReloadListeners: Array<() => void> = [];
|
|||
*/
|
||||
export function initializeHotReload(): void {
|
||||
// 핫 리로드 시스템 임시 비활성화 (디버깅 목적)
|
||||
console.log("🔥 컴포넌트 Hot Reload 시스템 비활성화됨 (디버깅 모드)");
|
||||
return;
|
||||
|
||||
|
||||
if (process.env.NODE_ENV !== "development" || typeof window === "undefined") {
|
||||
return;
|
||||
}
|
||||
|
|
@ -64,10 +63,18 @@ function setupDevServerEventListener(): void {
|
|||
const message = args.join(" ");
|
||||
|
||||
// 핫 리로드를 트리거할 특정 메시지만 감지 (디버깅 로그는 제외)
|
||||
if ((message.includes("compiled") || message.includes("Fast Refresh")) &&
|
||||
!message.includes("🔍") && !message.includes("🎯") && !message.includes("📤") &&
|
||||
!message.includes("📥") && !message.includes("⚠️") && !message.includes("🔄") &&
|
||||
!message.includes("✅") && !message.includes("🔧") && !message.includes("📋")) {
|
||||
if (
|
||||
(message.includes("compiled") || message.includes("Fast Refresh")) &&
|
||||
!message.includes("🔍") &&
|
||||
!message.includes("🎯") &&
|
||||
!message.includes("📤") &&
|
||||
!message.includes("📥") &&
|
||||
!message.includes("⚠️") &&
|
||||
!message.includes("🔄") &&
|
||||
!message.includes("✅") &&
|
||||
!message.includes("🔧") &&
|
||||
!message.includes("📋")
|
||||
) {
|
||||
if (!reloadPending) {
|
||||
reloadPending = true;
|
||||
setTimeout(() => {
|
||||
|
|
|
|||
|
|
@ -67,8 +67,6 @@ export class PerformanceOptimizer {
|
|||
static initialize(options: Partial<OptimizationOptions> = {}): void {
|
||||
this.options = { ...DEFAULT_OPTIMIZATION_OPTIONS, ...options };
|
||||
|
||||
console.log("⚡ 성능 최적화 시스템 초기화:", this.options);
|
||||
|
||||
// 메모리 사용량 모니터링 (개발 모드에서만)
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
this.startMemoryMonitoring();
|
||||
|
|
@ -463,5 +461,4 @@ export class PerformanceOptimizer {
|
|||
// 자동 초기화
|
||||
if (typeof window !== "undefined") {
|
||||
PerformanceOptimizer.initialize();
|
||||
console.log("⚡ 성능 최적화 시스템이 초기화되었습니다.");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,7 +48,6 @@ export async function getComponentConfigPanel(componentId: string): Promise<Reac
|
|||
}
|
||||
|
||||
try {
|
||||
console.log(`🔧 ConfigPanel 로드 중: ${componentId}`);
|
||||
const module = await importFn();
|
||||
|
||||
// 모듈에서 ConfigPanel 컴포넌트 추출
|
||||
|
|
@ -65,7 +64,6 @@ export async function getComponentConfigPanel(componentId: string): Promise<Reac
|
|||
|
||||
// 캐시에 저장
|
||||
configPanelCache.set(componentId, ConfigPanelComponent);
|
||||
console.log(`✅ ConfigPanel 로드 완료: ${componentId}`);
|
||||
|
||||
return ConfigPanelComponent;
|
||||
} catch (error) {
|
||||
|
|
@ -119,8 +117,6 @@ export const DynamicComponentConfigPanel: React.FC<ComponentConfigPanelProps> =
|
|||
tableColumns,
|
||||
tables,
|
||||
}) => {
|
||||
console.log(`🔥 DynamicComponentConfigPanel 렌더링 시작: ${componentId}`);
|
||||
|
||||
// 모든 useState를 최상단에 선언 (Hooks 규칙)
|
||||
const [ConfigPanelComponent, setConfigPanelComponent] = React.useState<React.ComponentType<any> | null>(null);
|
||||
const [loading, setLoading] = React.useState(true);
|
||||
|
|
@ -133,12 +129,10 @@ export const DynamicComponentConfigPanel: React.FC<ComponentConfigPanelProps> =
|
|||
|
||||
async function loadConfigPanel() {
|
||||
try {
|
||||
console.log(`🔧 DynamicComponentConfigPanel: ${componentId} 로드 시작`);
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
|
||||
const component = await getComponentConfigPanel(componentId);
|
||||
console.log(`🔧 DynamicComponentConfigPanel: ${componentId} 로드 결과:`, component);
|
||||
|
||||
if (mounted) {
|
||||
setConfigPanelComponent(() => component);
|
||||
|
|
@ -217,38 +211,20 @@ export const DynamicComponentConfigPanel: React.FC<ComponentConfigPanelProps> =
|
|||
);
|
||||
}
|
||||
|
||||
console.log(`🔧 DynamicComponentConfigPanel 렌더링:`, {
|
||||
componentId,
|
||||
ConfigPanelComponent: ConfigPanelComponent?.name,
|
||||
config,
|
||||
configType: typeof config,
|
||||
configKeys: typeof config === "object" ? Object.keys(config || {}) : "not object",
|
||||
screenTableName,
|
||||
tableColumns: Array.isArray(tableColumns) ? tableColumns.length : tableColumns,
|
||||
tables: Array.isArray(tables) ? tables.length : tables,
|
||||
tablesType: typeof tables,
|
||||
tablesDetail: tables, // 전체 테이블 목록 확인
|
||||
});
|
||||
|
||||
// 테이블 변경 핸들러 - 선택된 테이블의 컬럼을 동적으로 로드
|
||||
const handleTableChange = async (tableName: string) => {
|
||||
console.log("🔄 테이블 변경:", tableName);
|
||||
try {
|
||||
// 먼저 tables에서 찾아보기 (이미 컬럼이 있는 경우)
|
||||
const existingTable = tables?.find((t) => t.tableName === tableName);
|
||||
if (existingTable && existingTable.columns && existingTable.columns.length > 0) {
|
||||
console.log("✅ 캐시된 테이블 컬럼 사용:", existingTable.columns.length, "개");
|
||||
setSelectedTableColumns(existingTable.columns);
|
||||
return;
|
||||
}
|
||||
|
||||
// 컬럼이 없으면 tableTypeApi로 조회 (ScreenDesigner와 동일한 방식)
|
||||
console.log("🔍 테이블 컬럼 API 조회:", tableName);
|
||||
const { tableTypeApi } = await import("@/lib/api/screen");
|
||||
const columnsResponse = await tableTypeApi.getColumns(tableName);
|
||||
|
||||
console.log("🔍 컬럼 응답 데이터:", columnsResponse);
|
||||
|
||||
const columns = (columnsResponse || []).map((col: any) => ({
|
||||
tableName: col.tableName || tableName,
|
||||
columnName: col.columnName || col.column_name,
|
||||
|
|
@ -265,7 +241,6 @@ export const DynamicComponentConfigPanel: React.FC<ComponentConfigPanelProps> =
|
|||
codeValue: col.codeValue || col.code_value,
|
||||
}));
|
||||
|
||||
console.log("✅ 테이블 컬럼 로드 성공:", columns.length, "개");
|
||||
setSelectedTableColumns(columns);
|
||||
} catch (error) {
|
||||
console.error("❌ 테이블 변경 오류:", error);
|
||||
|
|
|
|||
|
|
@ -165,11 +165,6 @@ export function migrateComponentsToColumnSpan(
|
|||
* @returns 새로운 그리드 시스템으로 변환된 레이아웃
|
||||
*/
|
||||
export function migrateLayoutToGridSystem(layout: LayoutData, canvasWidth: number = 1920): LayoutData {
|
||||
console.log("🔄 레이아웃 마이그레이션 시작:", {
|
||||
screenId: layout.screenId,
|
||||
componentCount: layout.components.length,
|
||||
});
|
||||
|
||||
// 1단계: width를 gridColumnSpan으로 변환
|
||||
let migratedComponents = migrateComponentsToColumnSpan(layout.components, canvasWidth);
|
||||
|
||||
|
|
@ -179,11 +174,6 @@ export function migrateLayoutToGridSystem(layout: LayoutData, canvasWidth: numbe
|
|||
// 3단계: 같은 행 내에서 X 좌표로 gridColumnStart 계산
|
||||
migratedComponents = calculateColumnStarts(migratedComponents);
|
||||
|
||||
console.log("✅ 마이그레이션 완료:", {
|
||||
componentCount: migratedComponents.length,
|
||||
sampleComponent: migratedComponents[0],
|
||||
});
|
||||
|
||||
return {
|
||||
...layout,
|
||||
components: migratedComponents,
|
||||
|
|
@ -233,7 +223,6 @@ export function needsMigration(layout: LayoutData): boolean {
|
|||
export function safeMigrateLayout(layout: LayoutData, canvasWidth: number = 1920): LayoutData {
|
||||
try {
|
||||
if (!needsMigration(layout)) {
|
||||
console.log("⏭️ 마이그레이션 불필요 - 이미 최신 형식");
|
||||
return layout;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue