feature/screen-management #174
|
|
@ -1355,9 +1355,20 @@ export class DynamicFormService {
|
|||
console.log(`📋 화면 컴포넌트 조회 결과:`, screenLayouts.length);
|
||||
|
||||
// 저장 버튼 중에서 제어관리가 활성화된 것 찾기
|
||||
let controlConfigFound = false;
|
||||
for (const layout of screenLayouts) {
|
||||
const properties = layout.properties as any;
|
||||
|
||||
// 디버깅: 모든 컴포넌트 정보 출력
|
||||
console.log(`🔍 컴포넌트 검사:`, {
|
||||
componentId: layout.component_id,
|
||||
componentType: properties?.componentType,
|
||||
actionType: properties?.componentConfig?.action?.type,
|
||||
enableDataflowControl: properties?.webTypeConfig?.enableDataflowControl,
|
||||
hasDataflowConfig: !!properties?.webTypeConfig?.dataflowConfig,
|
||||
hasDiagramId: !!properties?.webTypeConfig?.dataflowConfig?.selectedDiagramId,
|
||||
});
|
||||
|
||||
// 버튼 컴포넌트이고 저장 액션이며 제어관리가 활성화된 경우
|
||||
if (
|
||||
properties?.componentType === "button-primary" &&
|
||||
|
|
@ -1365,6 +1376,7 @@ export class DynamicFormService {
|
|||
properties?.webTypeConfig?.enableDataflowControl === true &&
|
||||
properties?.webTypeConfig?.dataflowConfig?.selectedDiagramId
|
||||
) {
|
||||
controlConfigFound = true;
|
||||
const diagramId =
|
||||
properties.webTypeConfig.dataflowConfig.selectedDiagramId;
|
||||
const relationshipId =
|
||||
|
|
@ -1377,9 +1389,37 @@ export class DynamicFormService {
|
|||
triggerType,
|
||||
});
|
||||
|
||||
// 제어관리 실행
|
||||
const controlResult =
|
||||
await this.dataflowControlService.executeDataflowControl(
|
||||
// 노드 플로우 실행 (relationshipId가 없는 경우 노드 플로우로 간주)
|
||||
let controlResult: any;
|
||||
|
||||
if (!relationshipId) {
|
||||
// 노드 플로우 실행
|
||||
console.log(`🚀 노드 플로우 실행 (flowId: ${diagramId})`);
|
||||
const { NodeFlowExecutionService } = await import("./nodeFlowExecutionService");
|
||||
|
||||
const executionResult = await NodeFlowExecutionService.executeFlow(diagramId, {
|
||||
sourceData: [savedData],
|
||||
dataSourceType: "formData",
|
||||
buttonId: "save-button",
|
||||
screenId: screenId,
|
||||
userId: userId,
|
||||
formData: savedData,
|
||||
});
|
||||
|
||||
controlResult = {
|
||||
success: executionResult.success,
|
||||
message: executionResult.message,
|
||||
executedActions: executionResult.executedNodes?.map((node: any) => ({
|
||||
nodeId: node.nodeId,
|
||||
status: node.status,
|
||||
duration: node.duration,
|
||||
})),
|
||||
errors: executionResult.errors,
|
||||
};
|
||||
} else {
|
||||
// 관계 기반 제어관리 실행
|
||||
console.log(`🎯 관계 기반 제어관리 실행 (relationshipId: ${relationshipId})`);
|
||||
controlResult = await this.dataflowControlService.executeDataflowControl(
|
||||
diagramId,
|
||||
relationshipId,
|
||||
triggerType,
|
||||
|
|
@ -1387,6 +1427,7 @@ export class DynamicFormService {
|
|||
tableName,
|
||||
userId
|
||||
);
|
||||
}
|
||||
|
||||
console.log(`🎯 제어관리 실행 결과:`, controlResult);
|
||||
|
||||
|
|
@ -1417,6 +1458,10 @@ export class DynamicFormService {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!controlConfigFound) {
|
||||
console.log(`ℹ️ 제어관리 설정이 없습니다. (화면 ID: ${screenId})`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("❌ 제어관리 설정 확인 및 실행 오류:", error);
|
||||
// 에러를 다시 던지지 않음 - 메인 저장 프로세스에 영향 주지 않기 위해
|
||||
|
|
|
|||
|
|
@ -1278,6 +1278,11 @@ export class ScreenManagementService {
|
|||
},
|
||||
};
|
||||
|
||||
// 🔍 디버깅: webTypeConfig.dataflowConfig 확인
|
||||
if ((component as any).webTypeConfig?.dataflowConfig) {
|
||||
console.log(`🔍 컴포넌트 ${component.id}의 dataflowConfig:`, JSON.stringify((component as any).webTypeConfig.dataflowConfig, null, 2));
|
||||
}
|
||||
|
||||
await query(
|
||||
`INSERT INTO screen_layouts (
|
||||
screen_id, component_type, component_id, parent_id,
|
||||
|
|
|
|||
|
|
@ -263,6 +263,18 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD
|
|||
|
||||
try {
|
||||
setIsSaving(true);
|
||||
|
||||
// 🔍 디버깅: 저장할 레이아웃 데이터 확인
|
||||
console.log("🔍 레이아웃 저장 요청:", {
|
||||
screenId: selectedScreen.screenId,
|
||||
componentsCount: layout.components.length,
|
||||
components: layout.components.map(c => ({
|
||||
id: c.id,
|
||||
type: c.type,
|
||||
webTypeConfig: (c as any).webTypeConfig,
|
||||
})),
|
||||
});
|
||||
|
||||
const response = await screenApi.saveScreenLayout(selectedScreen.screenId, layout);
|
||||
if (response.success) {
|
||||
toast.success("화면이 저장되었습니다.");
|
||||
|
|
|
|||
|
|
@ -63,11 +63,17 @@ export const ImprovedButtonControlConfigPanel: React.FC<ImprovedButtonControlCon
|
|||
const handleFlowSelect = (flowId: string) => {
|
||||
const selectedFlow = flows.find((f) => f.flowId.toString() === flowId);
|
||||
if (selectedFlow) {
|
||||
onUpdateProperty("webTypeConfig.dataflowConfig.flowConfig", {
|
||||
flowId: selectedFlow.flowId,
|
||||
flowName: selectedFlow.flowName,
|
||||
executionTiming: "before", // 기본값
|
||||
contextData: {},
|
||||
// 전체 dataflowConfig 업데이트 (selectedDiagramId 포함)
|
||||
onUpdateProperty("webTypeConfig.dataflowConfig", {
|
||||
...dataflowConfig,
|
||||
selectedDiagramId: selectedFlow.flowId, // 백엔드에서 사용
|
||||
selectedRelationshipId: null, // 노드 플로우는 관계 ID 불필요
|
||||
flowConfig: {
|
||||
flowId: selectedFlow.flowId,
|
||||
flowName: selectedFlow.flowName,
|
||||
executionTiming: "before", // 기본값
|
||||
contextData: {},
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -151,6 +151,12 @@ export const screenApi = {
|
|||
await apiClient.post(`/screen-management/screens/${screenId}/layout`, layoutData);
|
||||
},
|
||||
|
||||
// 화면 레이아웃 저장 (ScreenDesigner_new.tsx용)
|
||||
saveScreenLayout: async (screenId: number, layoutData: LayoutData): Promise<ApiResponse<void>> => {
|
||||
const response = await apiClient.post(`/screen-management/screens/${screenId}/layout`, layoutData);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
// 화면 레이아웃 조회
|
||||
getLayout: async (screenId: number): Promise<LayoutData> => {
|
||||
const response = await apiClient.get(`/screen-management/screens/${screenId}/layout`);
|
||||
|
|
|
|||
|
|
@ -874,7 +874,9 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
|||
<div {...domProps}>
|
||||
{tableConfig.showHeader && (
|
||||
<div className="px-4 py-3 border-b border-border sm:px-6 sm:py-4">
|
||||
<h2 className="text-base font-semibold text-foreground sm:text-lg">{tableConfig.title || tableLabel}</h2>
|
||||
<h2 className="text-base font-semibold text-foreground sm:text-lg">
|
||||
{tableConfig.title || tableLabel || finalSelectedTable}
|
||||
</h2>
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
|
@ -936,7 +938,9 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
|||
{/* 헤더 */}
|
||||
{tableConfig.showHeader && (
|
||||
<div className="px-4 py-3 border-b border-border flex-shrink-0 sm:px-6 sm:py-4">
|
||||
<h2 className="text-base font-semibold text-foreground sm:text-lg">{tableConfig.title || tableLabel}</h2>
|
||||
<h2 className="text-base font-semibold text-foreground sm:text-lg">
|
||||
{tableConfig.title || tableLabel || finalSelectedTable}
|
||||
</h2>
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
|
|
|||
|
|
@ -727,6 +727,30 @@ export const TableListConfigPanel: React.FC<TableListConfigPanelProps> = ({
|
|||
<div className="text-sm font-medium">테이블 리스트 설정</div>
|
||||
|
||||
<div className="space-y-6">
|
||||
{/* 테이블 제목 설정 */}
|
||||
<div className="space-y-3">
|
||||
<div>
|
||||
<h3 className="text-sm font-semibold">테이블 제목</h3>
|
||||
</div>
|
||||
<hr className="border-border" />
|
||||
<div className="space-y-1">
|
||||
<Label htmlFor="tableTitle" className="text-xs">
|
||||
제목 (비워두면 테이블 라벨명 또는 테이블명 표시)
|
||||
</Label>
|
||||
<Input
|
||||
id="tableTitle"
|
||||
type="text"
|
||||
value={config.title || ""}
|
||||
onChange={(e) => handleChange("title", e.target.value)}
|
||||
placeholder="테이블 제목 입력..."
|
||||
className="h-8 text-xs"
|
||||
/>
|
||||
<p className="text-[10px] text-muted-foreground">
|
||||
우선순위: 사용자 입력 제목 → 테이블 라벨명 → 테이블명
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 가로 스크롤 및 컬럼 고정 */}
|
||||
<div className="space-y-3">
|
||||
<div>
|
||||
|
|
|
|||
Loading…
Reference in New Issue