Merge pull request '제어 관리 수정사항' (#31) from dataflowMng into dev

Reviewed-on: http://39.117.244.52:3000/kjs/ERP-node/pulls/31
This commit is contained in:
hyeonsu 2025-09-16 18:23:54 +09:00
commit 7648c1f532
7 changed files with 110 additions and 16 deletions

View File

@ -84,9 +84,20 @@ export const ConnectionSetupModal: React.FC<ConnectionSetupModalProps> = ({
setSimpleKeySettings({ setSimpleKeySettings({
notes: settings.notes as string, notes: settings.notes as string,
}); });
} else if (connectionType === "data-save" && settings.actions) { } else if (connectionType === "data-save") {
// data-save 설정 로드 - 안전하게 처리 // data-save 설정 로드 - 안전하게 처리 (다양한 구조 지원)
const actionsData = Array.isArray(settings.actions) ? settings.actions : []; let actionsData: Record<string, unknown>[] = [];
if (Array.isArray((settings as any).actions)) {
// 직접 actions 배열이 있는 경우
actionsData = (settings as any).actions;
} else if ((settings as any).plan && Array.isArray((settings as any).plan.actions)) {
// plan 객체 안에 actions가 있는 경우
actionsData = (settings as any).plan.actions;
} else if (Array.isArray(settings)) {
// settings 자체가 actions 배열인 경우
actionsData = settings as Record<string, unknown>[];
}
setDataSaveSettings({ setDataSaveSettings({
actions: actionsData.map((action: Record<string, unknown>) => ({ actions: actionsData.map((action: Record<string, unknown>) => ({
id: (action.id as string) || `action-${Date.now()}`, id: (action.id as string) || `action-${Date.now()}`,
@ -118,12 +129,19 @@ export const ConnectionSetupModal: React.FC<ConnectionSetupModalProps> = ({
})), })),
}); });
// 전체 실행 조건 로드 // control 설정도 로드 (전체 실행 조건)
if (settings.control) { if (
const controlSettings = settings.control as { conditionTree?: ConditionNode[] }; (settings as any).control &&
if (Array.isArray(controlSettings.conditionTree)) { (settings as any).control.conditionTree &&
setConditions(controlSettings.conditionTree || []); Array.isArray((settings as any).control.conditionTree)
} ) {
const conditionTree = (settings as any).control.conditionTree as ConditionNode[];
setConditions(
conditionTree.map((condition) => ({
...condition,
operator: condition.operator || "=", // 기본값 보장
})),
);
} }
} else if (connectionType === "external-call") { } else if (connectionType === "external-call") {
setExternalCallSettings({ setExternalCallSettings({
@ -186,7 +204,7 @@ export const ConnectionSetupModal: React.FC<ConnectionSetupModalProps> = ({
} else { } else {
// 기본값 설정 // 기본값 설정
setSimpleKeySettings({ setSimpleKeySettings({
notes: `${fromDisplayName}${toDisplayName} 간의 키값 연결`, notes: existingRel?.note || `${fromDisplayName}${toDisplayName} 간의 키값 연결`,
}); });
setDataSaveSettings({ actions: [] }); setDataSaveSettings({ actions: [] });
} }

View File

@ -114,6 +114,7 @@ export const DataFlowDesigner: React.FC<DataFlowDesignerProps> = ({
toColumns: Array.isArray(rel.toColumns) ? rel.toColumns : [], toColumns: Array.isArray(rel.toColumns) ? rel.toColumns : [],
connectionType: rel.connectionType || "simple-key", connectionType: rel.connectionType || "simple-key",
relationshipName: rel.relationshipName || "", relationshipName: rel.relationshipName || "",
note: rel.note || "", // 🔥 연결 설명 로드
})); }));
setTempRelationships(loadedRelationships); setTempRelationships(loadedRelationships);
@ -493,6 +494,7 @@ export const DataFlowDesigner: React.FC<DataFlowDesignerProps> = ({
toColumns: relationshipData.to_column_name ? relationshipData.to_column_name.split(",") : [], toColumns: relationshipData.to_column_name ? relationshipData.to_column_name.split(",") : [],
connectionType: relationshipData.connection_type as "simple-key" | "data-save" | "external-call", connectionType: relationshipData.connection_type as "simple-key" | "data-save" | "external-call",
relationshipName: relationshipData.relationship_name, relationshipName: relationshipData.relationship_name,
note: (relationshipData.settings as any)?.notes || "", // 🔥 notes를 note로 변환
settings: relationshipData.settings || {}, settings: relationshipData.settings || {},
}; };
@ -532,6 +534,7 @@ export const DataFlowDesigner: React.FC<DataFlowDesignerProps> = ({
toColumns: relationshipData.to_column_name ? relationshipData.to_column_name.split(",") : [], toColumns: relationshipData.to_column_name ? relationshipData.to_column_name.split(",") : [],
connectionType: relationshipData.connection_type as "simple-key" | "data-save" | "external-call", connectionType: relationshipData.connection_type as "simple-key" | "data-save" | "external-call",
relationshipName: relationshipData.relationship_name, relationshipName: relationshipData.relationship_name,
note: (relationshipData.settings as any)?.notes || "", // 🔥 notes를 note로 변환
settings: relationshipData.settings || {}, settings: relationshipData.settings || {},
}; };
@ -613,7 +616,7 @@ export const DataFlowDesigner: React.FC<DataFlowDesignerProps> = ({
// 연결된 테이블 목록 추출 // 연결된 테이블 목록 추출
const tableNames = extractTableNames(nodes); const tableNames = extractTableNames(nodes);
// 관계 데이터를 JsonRelationship 형태로 변환 (settings 제거 - relationships는 순수 연결 정보만) // 관계 데이터를 JsonRelationship 형태로 변환 (note 필드 포함)
const jsonRelationships: JsonRelationship[] = tempRelationships.map((rel) => ({ const jsonRelationships: JsonRelationship[] = tempRelationships.map((rel) => ({
id: rel.id, id: rel.id,
relationshipName: rel.relationshipName, // 🔥 핵심: 관계 이름 포함 relationshipName: rel.relationshipName, // 🔥 핵심: 관계 이름 포함
@ -622,6 +625,7 @@ export const DataFlowDesigner: React.FC<DataFlowDesignerProps> = ({
fromColumns: rel.fromColumns, fromColumns: rel.fromColumns,
toColumns: rel.toColumns, toColumns: rel.toColumns,
connectionType: rel.connectionType, connectionType: rel.connectionType,
note: rel.note, // 🔥 연결 설명 포함
})); }));
// 저장 요청 데이터 구성 // 저장 요청 데이터 구성

View File

@ -49,9 +49,15 @@ export const RelationshipListModal: React.FC<RelationshipListModalProps> = ({
} }
onSetSelectedColumns(newSelectedColumns); onSetSelectedColumns(newSelectedColumns);
// 🔥 수정: 데이터베이스에서 관계 설정 정보 로드 // 🔥 수정: 관계 설정 정보 로드 (임시 관계 우선, 없으면 데이터베이스에서)
let relationshipSettings = {}; let relationshipSettings = {};
if (diagramId && diagramId > 0) {
// 1. 먼저 임시 관계의 settings 사용 (메모리에 있는 데이터)
if (relationship.settings && Object.keys(relationship.settings).length > 0) {
relationshipSettings = relationship.settings;
}
// 2. 임시 settings가 없고 저장된 관계도인 경우 데이터베이스에서 로드
else if (diagramId && diagramId > 0) {
try { try {
const jsonDiagram = await DataFlowAPI.getJsonDataFlowDiagramById(diagramId, companyCode); const jsonDiagram = await DataFlowAPI.getJsonDataFlowDiagramById(diagramId, companyCode);
if (jsonDiagram && relationship.connectionType === "data-save") { if (jsonDiagram && relationship.connectionType === "data-save") {
@ -102,6 +108,7 @@ export const RelationshipListModal: React.FC<RelationshipListModalProps> = ({
existingRelationship: { existingRelationship: {
relationshipName: relationship.relationshipName, relationshipName: relationship.relationshipName,
connectionType: relationship.connectionType, connectionType: relationship.connectionType,
note: relationship.note, // 🔥 연결 설명 포함
settings: relationshipSettings, settings: relationshipSettings,
}, },
}); });

View File

@ -27,7 +27,7 @@ export const ExternalCallSettings: React.FC<ExternalCallSettingsProps> = ({ sett
</Label> </Label>
<Select <Select
value={settings.callType} value={settings.callType}
onValueChange={(value: "rest-api" | "email" | "webhook" | "ftp" | "queue") => onValueChange={(value: "rest-api" | "email" | "webhook" | "kakao-talk" | "ftp" | "queue") =>
onSettingsChange({ ...settings, callType: value }) onSettingsChange({ ...settings, callType: value })
} }
> >
@ -36,6 +36,7 @@ export const ExternalCallSettings: React.FC<ExternalCallSettingsProps> = ({ sett
</SelectTrigger> </SelectTrigger>
<SelectContent> <SelectContent>
<SelectItem value="rest-api">REST API </SelectItem> <SelectItem value="rest-api">REST API </SelectItem>
<SelectItem value="kakao-talk"> </SelectItem>
<SelectItem value="email"> </SelectItem> <SelectItem value="email"> </SelectItem>
<SelectItem value="webhook"></SelectItem> <SelectItem value="webhook"></SelectItem>
<SelectItem value="ftp">FTP </SelectItem> <SelectItem value="ftp">FTP </SelectItem>
@ -109,6 +110,64 @@ export const ExternalCallSettings: React.FC<ExternalCallSettingsProps> = ({ sett
</div> </div>
</> </>
)} )}
{settings.callType === "kakao-talk" && (
<>
<div>
<Label htmlFor="kakaoAccessToken" className="text-sm">
<span className="text-red-500">*</span>
</Label>
<Input
id="kakaoAccessToken"
type="password"
value={settings.kakaoAccessToken || ""}
onChange={(e) =>
onSettingsChange({
...settings,
kakaoAccessToken: e.target.value,
})
}
placeholder="카카오 개발자 센터에서 발급받은 토큰"
className="text-sm"
/>
<p className="mt-1 text-xs text-gray-600">
💡{" "}
<a
href="https://developers.kakao.com"
target="_blank"
rel="noopener noreferrer"
className="text-blue-500 hover:underline"
>
</a>
</p>
</div>
<div>
<Label htmlFor="kakaoMessage" className="text-sm">
릿 <span className="text-red-500">*</span>
</Label>
<Textarea
id="kakaoMessage"
value={settings.bodyTemplate || ""}
onChange={(e) =>
onSettingsChange({
...settings,
bodyTemplate: e.target.value,
})
}
placeholder="안녕하세요! {{customer_name}}님의 주문({{order_id}})이 처리되었습니다."
rows={3}
className="text-sm"
/>
<p className="mt-1 text-xs text-gray-600">
💡 {"{{"} {"}"} (: {"{{"} user_name {"}"}, {"{{"} amount{" "}
{"}"})
</p>
</div>
</>
)}
</div> </div>
</div> </div>
); );

View File

@ -260,7 +260,7 @@ export interface JsonRelationship {
fromColumns: string[]; fromColumns: string[];
toColumns: string[]; toColumns: string[];
connectionType: "simple-key" | "data-save" | "external-call"; connectionType: "simple-key" | "data-save" | "external-call";
// settings 제거 - relationships는 순수 연결 정보만 저장 note?: string; // 데이터 연결에 대한 설명
} }
export interface CreateDiagramRequest { export interface CreateDiagramRequest {

View File

@ -23,6 +23,7 @@ export interface ConnectionInfo {
existingRelationship?: { existingRelationship?: {
relationshipName: string; relationshipName: string;
connectionType: string; connectionType: string;
note?: string; // 연결 설명
settings?: Record<string, unknown>; settings?: Record<string, unknown>;
}; };
} }
@ -66,11 +67,15 @@ export interface DataSaveSettings {
// 외부 호출 설정 // 외부 호출 설정
export interface ExternalCallSettings { export interface ExternalCallSettings {
callType: "rest-api" | "email" | "webhook" | "ftp" | "queue"; callType: "rest-api" | "email" | "webhook" | "kakao-talk" | "ftp" | "queue";
apiUrl?: string; apiUrl?: string;
httpMethod?: "GET" | "POST" | "PUT" | "DELETE"; httpMethod?: "GET" | "POST" | "PUT" | "DELETE";
headers?: string; headers?: string;
bodyTemplate?: string; bodyTemplate?: string;
// 카카오톡 전용 설정
kakaoAccessToken?: string;
kakaoRecipient?: string;
} }
// ConnectionSetupModal Props 타입 // ConnectionSetupModal Props 타입

View File

@ -22,6 +22,7 @@ export interface TableNodeData extends Record<string, unknown> {
// 내부에서 사용할 확장된 JsonRelationship 타입 (connectionType 포함) // 내부에서 사용할 확장된 JsonRelationship 타입 (connectionType 포함)
export interface ExtendedJsonRelationship extends JsonRelationship { export interface ExtendedJsonRelationship extends JsonRelationship {
connectionType: "simple-key" | "data-save" | "external-call"; connectionType: "simple-key" | "data-save" | "external-call";
note?: string; // 데이터 연결에 대한 설명
settings?: { settings?: {
control?: { control?: {
triggerType?: "insert" | "update" | "delete"; triggerType?: "insert" | "update" | "delete";