단순 키 연결 구현 시 증계 테입르에 레코드 생성 구현
This commit is contained in:
parent
6b6c62f3b7
commit
ac03f311b0
|
|
@ -5139,14 +5139,10 @@ model data_relationship_bridge {
|
||||||
// 소스 테이블 정보
|
// 소스 테이블 정보
|
||||||
from_table_name String @db.VarChar(100)
|
from_table_name String @db.VarChar(100)
|
||||||
from_column_name String @db.VarChar(100)
|
from_column_name String @db.VarChar(100)
|
||||||
from_key_value String? @db.VarChar(500) // 실제 연결 키 값
|
|
||||||
from_record_id String? @db.VarChar(100) // 소스 레코드의 Primary Key
|
|
||||||
|
|
||||||
// 타겟 테이블 정보
|
// 타겟 테이블 정보
|
||||||
to_table_name String @db.VarChar(100)
|
to_table_name String @db.VarChar(100)
|
||||||
to_column_name String @db.VarChar(100)
|
to_column_name String @db.VarChar(100)
|
||||||
to_key_value String? @db.VarChar(500) // 실제 연결 키 값
|
|
||||||
to_record_id String? @db.VarChar(100) // 타겟 레코드의 Primary Key
|
|
||||||
|
|
||||||
// 메타데이터
|
// 메타데이터
|
||||||
connection_type String @db.VarChar(20) // 'simple-key', 'data-save', 'external-call'
|
connection_type String @db.VarChar(20) // 'simple-key', 'data-save', 'external-call'
|
||||||
|
|
@ -5164,12 +5160,12 @@ model data_relationship_bridge {
|
||||||
relationship table_relationships @relation(fields: [relationship_id], references: [relationship_id], onDelete: Cascade)
|
relationship table_relationships @relation(fields: [relationship_id], references: [relationship_id], onDelete: Cascade)
|
||||||
|
|
||||||
@@index([relationship_id], map: "idx_data_bridge_relationship")
|
@@index([relationship_id], map: "idx_data_bridge_relationship")
|
||||||
@@index([from_table_name, from_key_value], map: "idx_data_bridge_from_table")
|
@@index([from_table_name], map: "idx_data_bridge_from_table")
|
||||||
@@index([to_table_name, to_key_value], map: "idx_data_bridge_to_table")
|
@@index([to_table_name], map: "idx_data_bridge_to_table")
|
||||||
@@index([company_code], map: "idx_data_bridge_company")
|
@@index([company_code], map: "idx_data_bridge_company")
|
||||||
@@index([is_active], map: "idx_data_bridge_active")
|
@@index([is_active], map: "idx_data_bridge_active")
|
||||||
@@index([connection_type], map: "idx_data_bridge_connection_type")
|
@@index([connection_type], map: "idx_data_bridge_connection_type")
|
||||||
@@index([from_table_name, from_column_name, from_key_value], map: "idx_data_bridge_from_lookup")
|
@@index([from_table_name, from_column_name], map: "idx_data_bridge_from_lookup")
|
||||||
@@index([to_table_name, to_column_name, to_key_value], map: "idx_data_bridge_to_lookup")
|
@@index([to_table_name, to_column_name], map: "idx_data_bridge_to_lookup")
|
||||||
@@index([company_code, is_active], map: "idx_data_bridge_company_active")
|
@@index([company_code, is_active], map: "idx_data_bridge_company_active")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -366,12 +366,8 @@ export async function createDataLink(
|
||||||
relationshipId,
|
relationshipId,
|
||||||
fromTableName,
|
fromTableName,
|
||||||
fromColumnName,
|
fromColumnName,
|
||||||
fromKeyValue,
|
|
||||||
fromRecordId,
|
|
||||||
toTableName,
|
toTableName,
|
||||||
toColumnName,
|
toColumnName,
|
||||||
toKeyValue,
|
|
||||||
toRecordId,
|
|
||||||
connectionType,
|
connectionType,
|
||||||
bridgeData,
|
bridgeData,
|
||||||
} = req.body;
|
} = req.body;
|
||||||
|
|
@ -381,10 +377,8 @@ export async function createDataLink(
|
||||||
!relationshipId ||
|
!relationshipId ||
|
||||||
!fromTableName ||
|
!fromTableName ||
|
||||||
!fromColumnName ||
|
!fromColumnName ||
|
||||||
!fromKeyValue ||
|
|
||||||
!toTableName ||
|
!toTableName ||
|
||||||
!toColumnName ||
|
!toColumnName ||
|
||||||
!toKeyValue ||
|
|
||||||
!connectionType
|
!connectionType
|
||||||
) {
|
) {
|
||||||
const response: ApiResponse<null> = {
|
const response: ApiResponse<null> = {
|
||||||
|
|
@ -393,7 +387,7 @@ export async function createDataLink(
|
||||||
error: {
|
error: {
|
||||||
code: "MISSING_REQUIRED_FIELDS",
|
code: "MISSING_REQUIRED_FIELDS",
|
||||||
details:
|
details:
|
||||||
"필수 필드: relationshipId, fromTableName, fromColumnName, fromKeyValue, toTableName, toColumnName, toKeyValue, connectionType",
|
"필수 필드: relationshipId, fromTableName, fromColumnName, toTableName, toColumnName, connectionType",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
res.status(400).json(response);
|
res.status(400).json(response);
|
||||||
|
|
@ -409,12 +403,8 @@ export async function createDataLink(
|
||||||
relationshipId,
|
relationshipId,
|
||||||
fromTableName,
|
fromTableName,
|
||||||
fromColumnName,
|
fromColumnName,
|
||||||
fromKeyValue,
|
|
||||||
fromRecordId,
|
|
||||||
toTableName,
|
toTableName,
|
||||||
toColumnName,
|
toColumnName,
|
||||||
toKeyValue,
|
|
||||||
toRecordId,
|
|
||||||
connectionType,
|
connectionType,
|
||||||
companyCode,
|
companyCode,
|
||||||
bridgeData,
|
bridgeData,
|
||||||
|
|
@ -551,3 +541,70 @@ export async function deleteDataLink(
|
||||||
res.status(500).json(response);
|
res.status(500).json(response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ==================== 테이블 데이터 조회 ====================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 테이블 실제 데이터 조회 (페이징)
|
||||||
|
* GET /api/dataflow/table-data/:tableName
|
||||||
|
*/
|
||||||
|
export async function getTableData(req: Request, res: Response): Promise<void> {
|
||||||
|
try {
|
||||||
|
const { tableName } = req.params;
|
||||||
|
const {
|
||||||
|
page = "1",
|
||||||
|
limit = "10",
|
||||||
|
search = "",
|
||||||
|
searchColumn = "",
|
||||||
|
} = req.query;
|
||||||
|
|
||||||
|
if (!tableName) {
|
||||||
|
const response: ApiResponse<null> = {
|
||||||
|
success: false,
|
||||||
|
message: "테이블명이 필요합니다.",
|
||||||
|
error: {
|
||||||
|
code: "MISSING_TABLE_NAME",
|
||||||
|
details: "테이블명을 제공해주세요.",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
res.status(400).json(response);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const pageNum = parseInt(page as string) || 1;
|
||||||
|
const limitNum = parseInt(limit as string) || 10;
|
||||||
|
const userInfo = (req as any).user;
|
||||||
|
const companyCode = userInfo?.company_code || "*";
|
||||||
|
|
||||||
|
const dataflowService = new DataflowService();
|
||||||
|
const result = await dataflowService.getTableData(
|
||||||
|
tableName,
|
||||||
|
pageNum,
|
||||||
|
limitNum,
|
||||||
|
search as string,
|
||||||
|
searchColumn as string,
|
||||||
|
companyCode
|
||||||
|
);
|
||||||
|
|
||||||
|
const response: ApiResponse<typeof result> = {
|
||||||
|
success: true,
|
||||||
|
message: "테이블 데이터를 성공적으로 조회했습니다.",
|
||||||
|
data: result,
|
||||||
|
};
|
||||||
|
|
||||||
|
res.status(200).json(response);
|
||||||
|
} catch (error) {
|
||||||
|
logger.error("테이블 데이터 조회 중 오류 발생:", error);
|
||||||
|
|
||||||
|
const response: ApiResponse<null> = {
|
||||||
|
success: false,
|
||||||
|
message: "테이블 데이터 조회 중 오류가 발생했습니다.",
|
||||||
|
error: {
|
||||||
|
code: "TABLE_DATA_GET_ERROR",
|
||||||
|
details: error instanceof Error ? error.message : "Unknown error",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
res.status(500).json(response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import {
|
||||||
createDataLink,
|
createDataLink,
|
||||||
getLinkedDataByRelationship,
|
getLinkedDataByRelationship,
|
||||||
deleteDataLink,
|
deleteDataLink,
|
||||||
|
getTableData,
|
||||||
} from "../controllers/dataflowController";
|
} from "../controllers/dataflowController";
|
||||||
|
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
|
@ -69,4 +70,12 @@ router.get(
|
||||||
*/
|
*/
|
||||||
router.delete("/data-links/:bridgeId", deleteDataLink);
|
router.delete("/data-links/:bridgeId", deleteDataLink);
|
||||||
|
|
||||||
|
// ==================== 테이블 데이터 조회 라우트 ====================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 테이블 실제 데이터 조회
|
||||||
|
* GET /api/dataflow/table-data/:tableName
|
||||||
|
*/
|
||||||
|
router.get("/table-data/:tableName", getTableData);
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
|
|
||||||
|
|
@ -56,27 +56,63 @@ export class DataflowService {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 새 관계 생성
|
// 트랜잭션으로 관계 생성과 단순 키값 연결 처리
|
||||||
const relationship = await prisma.table_relationships.create({
|
const result = await prisma.$transaction(async (tx) => {
|
||||||
data: {
|
// 1. 새 관계 생성
|
||||||
relationship_name: data.relationshipName,
|
const relationship = await tx.table_relationships.create({
|
||||||
from_table_name: data.fromTableName,
|
data: {
|
||||||
from_column_name: data.fromColumnName,
|
relationship_name: data.relationshipName,
|
||||||
to_table_name: data.toTableName,
|
from_table_name: data.fromTableName,
|
||||||
to_column_name: data.toColumnName,
|
from_column_name: data.fromColumnName,
|
||||||
relationship_type: data.relationshipType,
|
to_table_name: data.toTableName,
|
||||||
connection_type: data.connectionType,
|
to_column_name: data.toColumnName,
|
||||||
company_code: data.companyCode,
|
relationship_type: data.relationshipType,
|
||||||
settings: data.settings,
|
connection_type: data.connectionType,
|
||||||
created_by: data.createdBy,
|
company_code: data.companyCode,
|
||||||
updated_by: data.createdBy,
|
settings: data.settings,
|
||||||
},
|
created_by: data.createdBy,
|
||||||
|
updated_by: data.createdBy,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 2. 단순 키값 연결인 경우 data_relationship_bridge에도 기본 레코드 생성
|
||||||
|
if (data.connectionType === "simple-key") {
|
||||||
|
logger.info(
|
||||||
|
`단순 키값 연결이므로 data_relationship_bridge에 기본 연결 레코드 생성 - 관계ID: ${relationship.relationship_id}`
|
||||||
|
);
|
||||||
|
|
||||||
|
await tx.data_relationship_bridge.create({
|
||||||
|
data: {
|
||||||
|
relationship_id: relationship.relationship_id,
|
||||||
|
from_table_name: data.fromTableName,
|
||||||
|
from_column_name: data.fromColumnName,
|
||||||
|
to_table_name: data.toTableName,
|
||||||
|
to_column_name: data.toColumnName,
|
||||||
|
connection_type: data.connectionType,
|
||||||
|
company_code: data.companyCode,
|
||||||
|
bridge_data: {
|
||||||
|
autoCreated: true,
|
||||||
|
createdAt: new Date().toISOString(),
|
||||||
|
notes: "단순 키값 연결 - 테이블과 컬럼 관계만 정의",
|
||||||
|
connectionInfo: `${data.fromTableName}.${data.fromColumnName} ↔ ${data.toTableName}.${data.toColumnName}`,
|
||||||
|
settings: data.settings,
|
||||||
|
},
|
||||||
|
created_by: data.createdBy,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
`단순 키값 연결 기본 레코드 생성 완료 - 관계ID: ${relationship.relationship_id}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return relationship;
|
||||||
});
|
});
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
`DataflowService: 테이블 관계 생성 완료 - ID: ${relationship.relationship_id}`
|
`DataflowService: 테이블 관계 생성 완료 - ID: ${result.relationship_id}`
|
||||||
);
|
);
|
||||||
return relationship;
|
return result;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error("DataflowService: 테이블 관계 생성 실패", error);
|
logger.error("DataflowService: 테이블 관계 생성 실패", error);
|
||||||
throw error;
|
throw error;
|
||||||
|
|
@ -386,12 +422,8 @@ export class DataflowService {
|
||||||
relationshipId: number;
|
relationshipId: number;
|
||||||
fromTableName: string;
|
fromTableName: string;
|
||||||
fromColumnName: string;
|
fromColumnName: string;
|
||||||
fromKeyValue: string;
|
|
||||||
fromRecordId?: string;
|
|
||||||
toTableName: string;
|
toTableName: string;
|
||||||
toColumnName: string;
|
toColumnName: string;
|
||||||
toKeyValue: string;
|
|
||||||
toRecordId?: string;
|
|
||||||
connectionType: string;
|
connectionType: string;
|
||||||
companyCode: string;
|
companyCode: string;
|
||||||
bridgeData?: any;
|
bridgeData?: any;
|
||||||
|
|
@ -407,12 +439,8 @@ export class DataflowService {
|
||||||
relationship_id: linkData.relationshipId,
|
relationship_id: linkData.relationshipId,
|
||||||
from_table_name: linkData.fromTableName,
|
from_table_name: linkData.fromTableName,
|
||||||
from_column_name: linkData.fromColumnName,
|
from_column_name: linkData.fromColumnName,
|
||||||
from_key_value: linkData.fromKeyValue,
|
|
||||||
from_record_id: linkData.fromRecordId,
|
|
||||||
to_table_name: linkData.toTableName,
|
to_table_name: linkData.toTableName,
|
||||||
to_column_name: linkData.toColumnName,
|
to_column_name: linkData.toColumnName,
|
||||||
to_key_value: linkData.toKeyValue,
|
|
||||||
to_record_id: linkData.toRecordId,
|
|
||||||
connection_type: linkData.connectionType,
|
connection_type: linkData.connectionType,
|
||||||
company_code: linkData.companyCode,
|
company_code: linkData.companyCode,
|
||||||
bridge_data: linkData.bridgeData || {},
|
bridge_data: linkData.bridgeData || {},
|
||||||
|
|
@ -494,13 +522,7 @@ export class DataflowService {
|
||||||
is_active: "Y",
|
is_active: "Y",
|
||||||
};
|
};
|
||||||
|
|
||||||
// 특정 키 값으로 필터링
|
// keyValue 파라미터는 더 이상 사용하지 않음 (key_value 필드 제거됨)
|
||||||
if (keyValue) {
|
|
||||||
whereCondition.OR = [
|
|
||||||
{ from_table_name: tableName, from_key_value: keyValue },
|
|
||||||
{ to_table_name: tableName, to_key_value: keyValue },
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
// 회사코드 필터링
|
// 회사코드 필터링
|
||||||
if (companyCode && companyCode !== "*") {
|
if (companyCode && companyCode !== "*") {
|
||||||
|
|
@ -537,10 +559,6 @@ export class DataflowService {
|
||||||
async updateDataLink(
|
async updateDataLink(
|
||||||
bridgeId: number,
|
bridgeId: number,
|
||||||
updateData: {
|
updateData: {
|
||||||
fromKeyValue?: string;
|
|
||||||
fromRecordId?: string;
|
|
||||||
toKeyValue?: string;
|
|
||||||
toRecordId?: string;
|
|
||||||
bridgeData?: any;
|
bridgeData?: any;
|
||||||
updatedBy: string;
|
updatedBy: string;
|
||||||
},
|
},
|
||||||
|
|
@ -662,4 +680,89 @@ export class DataflowService {
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ==================== 테이블 데이터 조회 ====================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 테이블 실제 데이터 조회 (페이징)
|
||||||
|
*/
|
||||||
|
async getTableData(
|
||||||
|
tableName: string,
|
||||||
|
page: number = 1,
|
||||||
|
limit: number = 10,
|
||||||
|
search: string = "",
|
||||||
|
searchColumn: string = "",
|
||||||
|
companyCode: string = "*"
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
logger.info(`DataflowService: 테이블 데이터 조회 시작 - ${tableName}`);
|
||||||
|
|
||||||
|
// 테이블 존재 여부 확인 (정보 스키마 사용)
|
||||||
|
const tableExists = await prisma.$queryRaw`
|
||||||
|
SELECT table_name
|
||||||
|
FROM information_schema.tables
|
||||||
|
WHERE table_name = ${tableName.toLowerCase()}
|
||||||
|
AND table_schema = 'public'
|
||||||
|
`;
|
||||||
|
|
||||||
|
if (
|
||||||
|
!tableExists ||
|
||||||
|
(Array.isArray(tableExists) && tableExists.length === 0)
|
||||||
|
) {
|
||||||
|
throw new Error(`테이블 '${tableName}'이 존재하지 않습니다.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 전체 데이터 개수 조회
|
||||||
|
let totalCountQuery = `SELECT COUNT(*) as total FROM "${tableName}"`;
|
||||||
|
let dataQuery = `SELECT * FROM "${tableName}"`;
|
||||||
|
|
||||||
|
// 검색 조건 추가
|
||||||
|
if (search && searchColumn) {
|
||||||
|
const whereCondition = `WHERE "${searchColumn}" ILIKE '%${search}%'`;
|
||||||
|
totalCountQuery += ` ${whereCondition}`;
|
||||||
|
dataQuery += ` ${whereCondition}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 페이징 처리
|
||||||
|
const offset = (page - 1) * limit;
|
||||||
|
dataQuery += ` ORDER BY 1 LIMIT ${limit} OFFSET ${offset}`;
|
||||||
|
|
||||||
|
// 실제 쿼리 실행
|
||||||
|
const [totalResult, dataResult] = await Promise.all([
|
||||||
|
prisma.$queryRawUnsafe(totalCountQuery),
|
||||||
|
prisma.$queryRawUnsafe(dataQuery),
|
||||||
|
]);
|
||||||
|
|
||||||
|
const total =
|
||||||
|
Array.isArray(totalResult) && totalResult.length > 0
|
||||||
|
? Number((totalResult[0] as any).total)
|
||||||
|
: 0;
|
||||||
|
|
||||||
|
const data = Array.isArray(dataResult) ? dataResult : [];
|
||||||
|
|
||||||
|
const result = {
|
||||||
|
data,
|
||||||
|
pagination: {
|
||||||
|
page,
|
||||||
|
limit,
|
||||||
|
total,
|
||||||
|
totalPages: Math.ceil(total / limit),
|
||||||
|
hasNext: page < Math.ceil(total / limit),
|
||||||
|
hasPrev: page > 1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
`DataflowService: 테이블 데이터 조회 완료 - ${tableName}, 총 ${total}건 중 ${data.length}건 조회`
|
||||||
|
);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
} catch (error) {
|
||||||
|
logger.error(
|
||||||
|
`DataflowService: 테이블 데이터 조회 실패 - ${tableName}`,
|
||||||
|
error
|
||||||
|
);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,6 @@ interface ConnectionConfig {
|
||||||
|
|
||||||
// 단순 키값 연결 설정
|
// 단순 키값 연결 설정
|
||||||
interface SimpleKeySettings {
|
interface SimpleKeySettings {
|
||||||
syncDirection: "unidirectional" | "bidirectional";
|
|
||||||
notes: string;
|
notes: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -94,7 +93,6 @@ export const ConnectionSetupModal: React.FC<ConnectionSetupModalProps> = ({
|
||||||
|
|
||||||
// 연결 종류별 설정 상태
|
// 연결 종류별 설정 상태
|
||||||
const [simpleKeySettings, setSimpleKeySettings] = useState<SimpleKeySettings>({
|
const [simpleKeySettings, setSimpleKeySettings] = useState<SimpleKeySettings>({
|
||||||
syncDirection: "bidirectional",
|
|
||||||
notes: "",
|
notes: "",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -130,7 +128,6 @@ export const ConnectionSetupModal: React.FC<ConnectionSetupModalProps> = ({
|
||||||
|
|
||||||
// 단순 키값 연결 기본값 설정
|
// 단순 키값 연결 기본값 설정
|
||||||
setSimpleKeySettings({
|
setSimpleKeySettings({
|
||||||
syncDirection: "bidirectional",
|
|
||||||
notes: `${fromTableName}과 ${toTableName} 간의 키값 연결`,
|
notes: `${fromTableName}과 ${toTableName} 간의 키값 연결`,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -238,25 +235,6 @@ export const ConnectionSetupModal: React.FC<ConnectionSetupModalProps> = ({
|
||||||
<span className="text-sm font-medium">단순 키값 연결 설정</span>
|
<span className="text-sm font-medium">단순 키값 연결 설정</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
<div>
|
|
||||||
<Label htmlFor="syncDirection" className="text-sm">
|
|
||||||
동기화 방향
|
|
||||||
</Label>
|
|
||||||
<Select
|
|
||||||
value={simpleKeySettings.syncDirection}
|
|
||||||
onValueChange={(value: "unidirectional" | "bidirectional") =>
|
|
||||||
setSimpleKeySettings({ ...simpleKeySettings, syncDirection: value })
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<SelectTrigger className="text-sm">
|
|
||||||
<SelectValue />
|
|
||||||
</SelectTrigger>
|
|
||||||
<SelectContent>
|
|
||||||
<SelectItem value="unidirectional">단방향 (소스 → 타겟)</SelectItem>
|
|
||||||
<SelectItem value="bidirectional">양방향 (소스 ↔ 타겟)</SelectItem>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</div>
|
|
||||||
<div>
|
<div>
|
||||||
<Label htmlFor="notes" className="text-sm">
|
<Label htmlFor="notes" className="text-sm">
|
||||||
연결 설명
|
연결 설명
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ export const DataFlowDesigner: React.FC<DataFlowDesignerProps> = ({ companyCode,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
} | null>(null);
|
} | null>(null);
|
||||||
const [relationships, setRelationships] = useState<TableRelationship[]>([]);
|
const [relationships, setRelationships] = useState<TableRelationship[]>([]); // eslint-disable-line @typescript-eslint/no-unused-vars
|
||||||
const toastShownRef = useRef(false);
|
const toastShownRef = useRef(false);
|
||||||
|
|
||||||
// 키보드 이벤트 핸들러 (Del 키로 선택된 노드 삭제)
|
// 키보드 이벤트 핸들러 (Del 키로 선택된 노드 삭제)
|
||||||
|
|
|
||||||
|
|
@ -57,12 +57,8 @@ export interface DataBridge {
|
||||||
relationshipId: number;
|
relationshipId: number;
|
||||||
fromTableName: string;
|
fromTableName: string;
|
||||||
fromColumnName: string;
|
fromColumnName: string;
|
||||||
fromKeyValue: string;
|
|
||||||
fromRecordId?: string;
|
|
||||||
toTableName: string;
|
toTableName: string;
|
||||||
toColumnName: string;
|
toColumnName: string;
|
||||||
toKeyValue: string;
|
|
||||||
toRecordId?: string;
|
|
||||||
connectionType: string;
|
connectionType: string;
|
||||||
companyCode: string;
|
companyCode: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
|
|
@ -78,6 +74,19 @@ export interface DataBridge {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 테이블 데이터 조회 응답 타입
|
||||||
|
export interface TableDataResponse {
|
||||||
|
data: Record<string, unknown>[];
|
||||||
|
pagination: {
|
||||||
|
page: number;
|
||||||
|
limit: number;
|
||||||
|
total: number;
|
||||||
|
totalPages: number;
|
||||||
|
hasNext: boolean;
|
||||||
|
hasPrev: boolean;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// 테이블 간 데이터 관계 설정 API 클래스
|
// 테이블 간 데이터 관계 설정 API 클래스
|
||||||
export class DataFlowAPI {
|
export class DataFlowAPI {
|
||||||
/**
|
/**
|
||||||
|
|
@ -225,12 +234,8 @@ export class DataFlowAPI {
|
||||||
relationshipId: number;
|
relationshipId: number;
|
||||||
fromTableName: string;
|
fromTableName: string;
|
||||||
fromColumnName: string;
|
fromColumnName: string;
|
||||||
fromKeyValue: string;
|
|
||||||
fromRecordId?: string;
|
|
||||||
toTableName: string;
|
toTableName: string;
|
||||||
toColumnName: string;
|
toColumnName: string;
|
||||||
toKeyValue: string;
|
|
||||||
toRecordId?: string;
|
|
||||||
connectionType: string;
|
connectionType: string;
|
||||||
bridgeData?: Record<string, unknown>;
|
bridgeData?: Record<string, unknown>;
|
||||||
}): Promise<DataBridge> {
|
}): Promise<DataBridge> {
|
||||||
|
|
@ -283,4 +288,39 @@ export class DataFlowAPI {
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ==================== 테이블 데이터 조회 API ====================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 테이블 실제 데이터 조회 (페이징)
|
||||||
|
*/
|
||||||
|
static async getTableData(
|
||||||
|
tableName: string,
|
||||||
|
page: number = 1,
|
||||||
|
limit: number = 10,
|
||||||
|
search: string = "",
|
||||||
|
searchColumn: string = "",
|
||||||
|
): Promise<TableDataResponse> {
|
||||||
|
try {
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
page: page.toString(),
|
||||||
|
limit: limit.toString(),
|
||||||
|
...(search && { search }),
|
||||||
|
...(searchColumn && { searchColumn }),
|
||||||
|
});
|
||||||
|
|
||||||
|
const response = await apiClient.get<ApiResponse<TableDataResponse>>(
|
||||||
|
`/dataflow/table-data/${tableName}?${params}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!response.data.success) {
|
||||||
|
throw new Error(response.data.message || "테이블 데이터 조회에 실패했습니다.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.data.data as TableDataResponse;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("테이블 데이터 조회 오류:", error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue