feat: Enhance SelectedItemsDetailInputComponent with improved FK mapping and performance optimizations
- Implemented automatic detection of sourceKeyField based on component configuration, enhancing data handling flexibility. - Updated SelectedItemsDetailInputConfigPanel to support automatic FK detection and mapping, streamlining configuration. - Improved database connection logic for DATE types to prevent timezone-related issues. - Optimized memoization and state management for better overall component performance and user experience.
This commit is contained in:
parent
52d95b4798
commit
afc66a4971
|
|
@ -0,0 +1,85 @@
|
|||
/**
|
||||
* BOM Screen - Restoration Verification
|
||||
* Screen 4168 - verify split panel, BOM list, and tree with child items
|
||||
*/
|
||||
import { chromium } from 'playwright';
|
||||
import { mkdirSync, existsSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
|
||||
const SCREENSHOT_DIR = join(process.cwd(), 'bom-detail-test-screenshots');
|
||||
|
||||
async function ensureDir(dir) {
|
||||
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
||||
}
|
||||
|
||||
async function screenshot(page, name) {
|
||||
ensureDir(SCREENSHOT_DIR);
|
||||
await page.screenshot({ path: join(SCREENSHOT_DIR, `${name}.png`), fullPage: true });
|
||||
console.log(` [Screenshot] ${name}.png`);
|
||||
}
|
||||
|
||||
async function sleep(ms) {
|
||||
return new Promise((r) => setTimeout(r, ms));
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const browser = await chromium.launch({ headless: true });
|
||||
const page = await browser.newPage({ viewport: { width: 1400, height: 900 } });
|
||||
|
||||
try {
|
||||
console.log('\n--- Step 1-2: Login ---');
|
||||
await page.goto('http://localhost:9771/login', { waitUntil: 'load', timeout: 45000 });
|
||||
await page.locator('input[type="text"], input[placeholder*="ID"]').first().fill('topseal_admin');
|
||||
await page.locator('input[type="password"]').first().fill('qlalfqjsgh11');
|
||||
await Promise.all([
|
||||
page.waitForNavigation({ waitUntil: 'domcontentloaded', timeout: 20000 }).catch(() => {}),
|
||||
page.locator('button:has-text("로그인")').first().click(),
|
||||
]);
|
||||
await sleep(3000);
|
||||
|
||||
console.log('\n--- Step 4-5: Navigate to screen 4168 ---');
|
||||
await page.goto('http://localhost:9771/screens/4168', { waitUntil: 'load', timeout: 45000 });
|
||||
await sleep(5000);
|
||||
|
||||
console.log('\n--- Step 6: Screenshot after load ---');
|
||||
await screenshot(page, '10-bom-4168-initial');
|
||||
|
||||
const hasBomList = (await page.locator('text="BOM 목록"').count()) > 0;
|
||||
const hasSplitPanel = (await page.locator('text="BOM 상세정보"').count()) > 0 || hasBomList;
|
||||
const rowCount = await page.locator('table tbody tr').count();
|
||||
const hasBomRows = rowCount > 0;
|
||||
|
||||
console.log('\n========== INITIAL STATE (Step 7) ==========');
|
||||
console.log('BOM management screen loaded:', hasBomList || hasSplitPanel ? 'YES' : 'CHECK');
|
||||
console.log('Split panel (BOM list left):', hasSplitPanel ? 'YES' : 'NO');
|
||||
console.log('BOM data rows visible:', hasBomRows ? `YES (${rowCount} rows)` : 'NO');
|
||||
|
||||
if (hasBomRows) {
|
||||
console.log('\n--- Step 8-9: Click first row ---');
|
||||
await page.locator('table tbody tr').first().click();
|
||||
await sleep(5000);
|
||||
|
||||
console.log('\n--- Step 10: Screenshot after row click ---');
|
||||
await screenshot(page, '11-bom-4168-after-click');
|
||||
|
||||
const noDataMsg = (await page.locator('text="등록된 하위 품목이 없습니다"').count()) > 0;
|
||||
const treeArea = page.locator('div:has-text("BOM 구성"), div:has-text("BOM 상세정보")').first();
|
||||
const treeText = (await treeArea.textContent().catch(() => '') || '').substring(0, 600);
|
||||
const hasChildItems = !noDataMsg && (treeText.includes('품번') || treeText.includes('레벨') || treeText.length > 150);
|
||||
|
||||
console.log('\n========== AFTER ROW CLICK (Step 11) ==========');
|
||||
console.log('BOM tree shows child items:', hasChildItems ? 'YES' : noDataMsg ? 'NO (empty message)' : 'CHECK');
|
||||
console.log('Tree preview:', treeText.substring(0, 300) + (treeText.length > 300 ? '...' : ''));
|
||||
} else {
|
||||
console.log('\n--- No BOM rows to click ---');
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
console.error('Error:', err.message);
|
||||
try { await page.screenshot({ path: join(SCREENSHOT_DIR, '99-error.png'), fullPage: true }); } catch (e) {}
|
||||
} finally {
|
||||
await browser.close();
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
|
|
@ -6,7 +6,7 @@ import { Loader2 } from "lucide-react";
|
|||
import { apiClient } from "@/lib/api/client";
|
||||
|
||||
/**
|
||||
* /screen/COMPANY_7_167 → /screens/4153 리다이렉트
|
||||
* /screen/{screenCode} → /screens/{screenId} 리다이렉트
|
||||
* 메뉴 URL이 screenCode 기반이므로, screenId로 변환 후 이동
|
||||
*/
|
||||
export default function ScreenCodeRedirectPage() {
|
||||
|
|
@ -26,12 +26,14 @@ export default function ScreenCodeRedirectPage() {
|
|||
const resolve = async () => {
|
||||
try {
|
||||
const res = await apiClient.get("/screen-management/screens", {
|
||||
params: { screenCode },
|
||||
params: { searchTerm: screenCode, size: 50 },
|
||||
});
|
||||
const screens = res.data?.data || [];
|
||||
if (screens.length > 0) {
|
||||
const id = screens[0].screenId || screens[0].screen_id;
|
||||
router.replace(`/screens/${id}`);
|
||||
const items = res.data?.data?.data || res.data?.data || [];
|
||||
const arr = Array.isArray(items) ? items : [];
|
||||
const exact = arr.find((s: any) => s.screenCode === screenCode);
|
||||
const target = exact || arr[0];
|
||||
if (target) {
|
||||
router.replace(`/screens/${target.screenId || target.screen_id}`);
|
||||
} else {
|
||||
router.replace("/");
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue