POP 레이아웃 v3.0 아키텍처로 전환 - Section 요소 완전 제거
디자이너/뷰어 렌더링 통일 - react-grid-layout 제거, CSS Grid 1fr 단위 사용 반응형 모드 자동 전환 - useResponsiveMode 훅 추가 디자이너 UI 개선 - 컴포넌트 헤더/삭제 아이콘 제거, 전체 영역 드래그
This commit is contained in:
@@ -4894,7 +4894,8 @@ export class ScreenManagementService {
|
||||
/**
|
||||
* POP 레이아웃 저장
|
||||
* - screen_layouts_pop 테이블에 화면당 1개 레코드 저장
|
||||
* - v2 형식으로 저장 (version: "pop-2.0")
|
||||
* - v3 형식 지원 (version: "pop-3.0", 섹션 제거)
|
||||
* - v2/v1 하위 호환
|
||||
*/
|
||||
async saveLayoutPop(
|
||||
screenId: number,
|
||||
@@ -4905,11 +4906,16 @@ export class ScreenManagementService {
|
||||
console.log(`=== POP 레이아웃 저장 시작 ===`);
|
||||
console.log(`화면 ID: ${screenId}, 회사: ${companyCode}`);
|
||||
|
||||
// v2 구조 확인
|
||||
// 버전 감지
|
||||
const isV3 = layoutData.version === "pop-3.0" ||
|
||||
(layoutData.layouts && layoutData.components && !layoutData.sections);
|
||||
const isV2 = layoutData.version === "pop-2.0" ||
|
||||
(layoutData.layouts && layoutData.sections && layoutData.components);
|
||||
|
||||
if (isV2) {
|
||||
if (isV3) {
|
||||
const componentCount = Object.keys(layoutData.components || {}).length;
|
||||
console.log(`v3 레이아웃: ${componentCount}개 컴포넌트 (섹션 없음)`);
|
||||
} else if (isV2) {
|
||||
const sectionCount = Object.keys(layoutData.sections || {}).length;
|
||||
const componentCount = Object.keys(layoutData.components || {}).length;
|
||||
console.log(`v2 레이아웃: ${sectionCount}개 섹션, ${componentCount}개 컴포넌트`);
|
||||
@@ -4933,13 +4939,50 @@ export class ScreenManagementService {
|
||||
throw new Error("이 화면의 POP 레이아웃을 저장할 권한이 없습니다.");
|
||||
}
|
||||
|
||||
// 버전 정보 보장 (v2 우선, v1은 프론트엔드에서 마이그레이션 후 저장 권장)
|
||||
// SUPER_ADMIN인 경우: 화면 정의의 company_code로 저장 (로드와 동일하게)
|
||||
const targetCompanyCode = companyCode === "*"
|
||||
? (existingScreen.company_code || "*")
|
||||
: companyCode;
|
||||
|
||||
console.log(`저장 대상 company_code: ${targetCompanyCode} (사용자: ${companyCode}, 화면: ${existingScreen.company_code})`);
|
||||
|
||||
// 버전 정보 보장
|
||||
let dataToSave: any;
|
||||
if (isV2) {
|
||||
if (isV3) {
|
||||
dataToSave = {
|
||||
...layoutData,
|
||||
version: "pop-3.0",
|
||||
};
|
||||
|
||||
// canvasGrid.rows 검증 및 보정
|
||||
if (dataToSave.settings?.canvasGrid) {
|
||||
if (!dataToSave.settings.canvasGrid.rows) {
|
||||
console.warn("canvasGrid.rows 없음, 기본값 24로 설정");
|
||||
dataToSave.settings.canvasGrid.rows = 24;
|
||||
}
|
||||
// 구버전 rowHeight 필드 제거
|
||||
if (dataToSave.settings.canvasGrid.rowHeight) {
|
||||
console.warn("구버전 rowHeight 필드 제거");
|
||||
delete dataToSave.settings.canvasGrid.rowHeight;
|
||||
}
|
||||
}
|
||||
} else if (isV2) {
|
||||
dataToSave = {
|
||||
...layoutData,
|
||||
version: "pop-2.0",
|
||||
};
|
||||
|
||||
// canvasGrid.rows 검증 및 보정
|
||||
if (dataToSave.settings?.canvasGrid) {
|
||||
if (!dataToSave.settings.canvasGrid.rows) {
|
||||
console.warn("canvasGrid.rows 없음, 기본값 24로 설정");
|
||||
dataToSave.settings.canvasGrid.rows = 24;
|
||||
}
|
||||
if (dataToSave.settings.canvasGrid.rowHeight) {
|
||||
console.warn("구버전 rowHeight 필드 제거");
|
||||
delete dataToSave.settings.canvasGrid.rowHeight;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// v1 형식으로 저장 (하위 호환)
|
||||
dataToSave = {
|
||||
@@ -4954,10 +4997,10 @@ export class ScreenManagementService {
|
||||
VALUES ($1, $2, $3, NOW(), NOW(), $4, $4)
|
||||
ON CONFLICT (screen_id, company_code)
|
||||
DO UPDATE SET layout_data = $3, updated_at = NOW(), updated_by = $4`,
|
||||
[screenId, companyCode, JSON.stringify(dataToSave), userId || null],
|
||||
[screenId, targetCompanyCode, JSON.stringify(dataToSave), userId || null],
|
||||
);
|
||||
|
||||
console.log(`POP 레이아웃 저장 완료 (version: ${dataToSave.version})`);
|
||||
console.log(`POP 레이아웃 저장 완료 (version: ${dataToSave.version}, company: ${targetCompanyCode})`);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user