feat: Add image thumbnail rendering in SplitPanelLayoutComponent
- Introduced SplitPanelCellImage component to handle image rendering for table cells, supporting both object IDs and file paths. - Enhanced formatCellValue function to display image thumbnails for columns with input type "image". - Updated column input types loading logic to accommodate special rendering for images in the right panel. - Improved error handling for image loading failures, ensuring a better user experience when images cannot be displayed.
This commit is contained in:
111
backend-node/src/controllers/bomController.ts
Normal file
111
backend-node/src/controllers/bomController.ts
Normal file
@@ -0,0 +1,111 @@
|
||||
/**
|
||||
* BOM 이력/버전 관리 컨트롤러
|
||||
*/
|
||||
|
||||
import { Request, Response } from "express";
|
||||
import { logger } from "../utils/logger";
|
||||
import * as bomService from "../services/bomService";
|
||||
|
||||
// ─── 이력 (History) ─────────────────────────────
|
||||
|
||||
export async function getBomHistory(req: Request, res: Response) {
|
||||
try {
|
||||
const { bomId } = req.params;
|
||||
const companyCode = (req as any).user?.companyCode || "*";
|
||||
const tableName = (req.query.tableName as string) || undefined;
|
||||
|
||||
const data = await bomService.getBomHistory(bomId, companyCode, tableName);
|
||||
res.json({ success: true, data });
|
||||
} catch (error: any) {
|
||||
logger.error("BOM 이력 조회 실패", { error: error.message });
|
||||
res.status(500).json({ success: false, message: error.message });
|
||||
}
|
||||
}
|
||||
|
||||
export async function addBomHistory(req: Request, res: Response) {
|
||||
try {
|
||||
const { bomId } = req.params;
|
||||
const companyCode = (req as any).user?.companyCode || "*";
|
||||
const changedBy = (req as any).user?.userName || (req as any).user?.userId || "";
|
||||
|
||||
const { change_type, change_description, revision, version, tableName } = req.body;
|
||||
if (!change_type) {
|
||||
res.status(400).json({ success: false, message: "change_type은 필수입니다" });
|
||||
return;
|
||||
}
|
||||
|
||||
const result = await bomService.addBomHistory(bomId, companyCode, {
|
||||
change_type,
|
||||
change_description,
|
||||
revision,
|
||||
version,
|
||||
changed_by: changedBy,
|
||||
}, tableName);
|
||||
res.json({ success: true, data: result });
|
||||
} catch (error: any) {
|
||||
logger.error("BOM 이력 등록 실패", { error: error.message });
|
||||
res.status(500).json({ success: false, message: error.message });
|
||||
}
|
||||
}
|
||||
|
||||
// ─── 버전 (Version) ─────────────────────────────
|
||||
|
||||
export async function getBomVersions(req: Request, res: Response) {
|
||||
try {
|
||||
const { bomId } = req.params;
|
||||
const companyCode = (req as any).user?.companyCode || "*";
|
||||
const tableName = (req.query.tableName as string) || undefined;
|
||||
|
||||
const data = await bomService.getBomVersions(bomId, companyCode, tableName);
|
||||
res.json({ success: true, data });
|
||||
} catch (error: any) {
|
||||
logger.error("BOM 버전 목록 조회 실패", { error: error.message });
|
||||
res.status(500).json({ success: false, message: error.message });
|
||||
}
|
||||
}
|
||||
|
||||
export async function createBomVersion(req: Request, res: Response) {
|
||||
try {
|
||||
const { bomId } = req.params;
|
||||
const companyCode = (req as any).user?.companyCode || "*";
|
||||
const createdBy = (req as any).user?.userName || (req as any).user?.userId || "";
|
||||
const { tableName, detailTable } = req.body || {};
|
||||
|
||||
const result = await bomService.createBomVersion(bomId, companyCode, createdBy, tableName, detailTable);
|
||||
res.json({ success: true, data: result });
|
||||
} catch (error: any) {
|
||||
logger.error("BOM 버전 생성 실패", { error: error.message });
|
||||
res.status(500).json({ success: false, message: error.message });
|
||||
}
|
||||
}
|
||||
|
||||
export async function loadBomVersion(req: Request, res: Response) {
|
||||
try {
|
||||
const { bomId, versionId } = req.params;
|
||||
const companyCode = (req as any).user?.companyCode || "*";
|
||||
const { tableName, detailTable } = req.body || {};
|
||||
|
||||
const result = await bomService.loadBomVersion(bomId, versionId, companyCode, tableName, detailTable);
|
||||
res.json({ success: true, data: result });
|
||||
} catch (error: any) {
|
||||
logger.error("BOM 버전 불러오기 실패", { error: error.message });
|
||||
res.status(500).json({ success: false, message: error.message });
|
||||
}
|
||||
}
|
||||
|
||||
export async function deleteBomVersion(req: Request, res: Response) {
|
||||
try {
|
||||
const { bomId, versionId } = req.params;
|
||||
const tableName = (req.query.tableName as string) || undefined;
|
||||
|
||||
const deleted = await bomService.deleteBomVersion(bomId, versionId, tableName);
|
||||
if (!deleted) {
|
||||
res.status(404).json({ success: false, message: "버전을 찾을 수 없습니다" });
|
||||
return;
|
||||
}
|
||||
res.json({ success: true });
|
||||
} catch (error: any) {
|
||||
logger.error("BOM 버전 삭제 실패", { error: error.message });
|
||||
res.status(500).json({ success: false, message: error.message });
|
||||
}
|
||||
}
|
||||
@@ -115,7 +115,7 @@ export async function getDistinctColumnValues(req: AuthenticatedRequest, res: Re
|
||||
export async function getEntityOptions(req: AuthenticatedRequest, res: Response) {
|
||||
try {
|
||||
const { tableName } = req.params;
|
||||
const { value = "id", label = "name" } = req.query;
|
||||
const { value = "id", label = "name", fields } = req.query;
|
||||
|
||||
// tableName 유효성 검증
|
||||
if (!tableName || tableName === "undefined" || tableName === "null") {
|
||||
@@ -167,9 +167,21 @@ export async function getEntityOptions(req: AuthenticatedRequest, res: Response)
|
||||
? `WHERE ${whereConditions.join(" AND ")}`
|
||||
: "";
|
||||
|
||||
// autoFill용 추가 컬럼 처리
|
||||
let extraColumns = "";
|
||||
if (fields && typeof fields === "string") {
|
||||
const requestedFields = fields.split(",").map((f) => f.trim()).filter(Boolean);
|
||||
const validExtra = requestedFields.filter(
|
||||
(f) => existingColumns.has(f) && f !== valueColumn && f !== effectiveLabelColumn
|
||||
);
|
||||
if (validExtra.length > 0) {
|
||||
extraColumns = ", " + validExtra.map((f) => `"${f}"`).join(", ");
|
||||
}
|
||||
}
|
||||
|
||||
// 쿼리 실행 (최대 500개)
|
||||
const query = `
|
||||
SELECT ${valueColumn} as value, ${effectiveLabelColumn} as label
|
||||
SELECT ${valueColumn} as value, ${effectiveLabelColumn} as label${extraColumns}
|
||||
FROM ${tableName}
|
||||
${whereClause}
|
||||
ORDER BY ${effectiveLabelColumn} ASC
|
||||
@@ -184,6 +196,7 @@ export async function getEntityOptions(req: AuthenticatedRequest, res: Response)
|
||||
labelColumn: effectiveLabelColumn,
|
||||
companyCode,
|
||||
rowCount: result.rowCount,
|
||||
extraFields: extraColumns ? true : false,
|
||||
});
|
||||
|
||||
res.json({
|
||||
|
||||
@@ -958,13 +958,14 @@ export async function addTableData(
|
||||
}
|
||||
|
||||
// 데이터 추가
|
||||
await tableManagementService.addTableData(tableName, data);
|
||||
const result = await tableManagementService.addTableData(tableName, data);
|
||||
|
||||
logger.info(`테이블 데이터 추가 완료: ${tableName}`);
|
||||
logger.info(`테이블 데이터 추가 완료: ${tableName}, id: ${result.insertedId}`);
|
||||
|
||||
const response: ApiResponse<null> = {
|
||||
const response: ApiResponse<{ id: string | null }> = {
|
||||
success: true,
|
||||
message: "테이블 데이터를 성공적으로 추가했습니다.",
|
||||
data: { id: result.insertedId },
|
||||
};
|
||||
|
||||
res.status(201).json(response);
|
||||
|
||||
Reference in New Issue
Block a user