Merge branch 'mhkim-node' of http://39.117.244.52:3000/kjs/ERP-node into jskim-node
This commit is contained in:
commit
ba39ebf341
|
|
@ -153,6 +153,7 @@ backend-node/uploads/
|
||||||
uploads/
|
uploads/
|
||||||
*.jpg
|
*.jpg
|
||||||
*.jpeg
|
*.jpeg
|
||||||
|
*.png
|
||||||
*.gif
|
*.gif
|
||||||
*.pdf
|
*.pdf
|
||||||
*.doc
|
*.doc
|
||||||
|
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 329 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 342 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 25 KiB |
|
|
@ -402,19 +402,10 @@ select {
|
||||||
/* 필요시 특정 컴포넌트에 대한 스타일 오버라이드를 여기에 추가 */
|
/* 필요시 특정 컴포넌트에 대한 스타일 오버라이드를 여기에 추가 */
|
||||||
/* 예: Calendar, Table 등의 미세 조정 */
|
/* 예: Calendar, Table 등의 미세 조정 */
|
||||||
|
|
||||||
/* 모바일에서 테이블 레이아웃 고정 (화면 밖으로 넘어가지 않도록) */
|
/* 테이블 레이아웃 고정 (셀 내용이 영역을 벗어나지 않도록) */
|
||||||
@media (max-width: 639px) {
|
|
||||||
.table-mobile-fixed {
|
.table-mobile-fixed {
|
||||||
table-layout: fixed;
|
table-layout: fixed;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* 데스크톱에서 테이블 레이아웃 자동 (기본값이지만 명시적으로 설정) */
|
|
||||||
@media (min-width: 640px) {
|
|
||||||
.table-mobile-fixed {
|
|
||||||
table-layout: auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 그리드선 숨기기 */
|
/* 그리드선 숨기기 */
|
||||||
.hide-grid td,
|
.hide-grid td,
|
||||||
|
|
|
||||||
|
|
@ -583,7 +583,7 @@ const RealtimePreviewDynamicComponent: React.FC<RealtimePreviewProps> = ({
|
||||||
const needsStripBorder = isV2HorizLabel || isButtonComponent;
|
const needsStripBorder = isV2HorizLabel || isButtonComponent;
|
||||||
const safeComponentStyle = needsStripBorder
|
const safeComponentStyle = needsStripBorder
|
||||||
? (() => {
|
? (() => {
|
||||||
const { borderWidth, borderColor, borderStyle, border, borderRadius, ...rest } = componentStyle as any;
|
const { borderWidth, borderColor, borderStyle, border, ...rest } = componentStyle as any;
|
||||||
return rest;
|
return rest;
|
||||||
})()
|
})()
|
||||||
: componentStyle;
|
: componentStyle;
|
||||||
|
|
|
||||||
|
|
@ -2670,7 +2670,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||||
<td
|
<td
|
||||||
key={colIdx}
|
key={colIdx}
|
||||||
className="px-3 py-2 text-sm whitespace-nowrap text-foreground"
|
className="px-3 py-2 text-sm whitespace-nowrap text-foreground"
|
||||||
style={{ textAlign: col.align || "left" }}
|
style={{ textAlign: col.align || "left", overflow: "hidden", textOverflow: "ellipsis" }}
|
||||||
>
|
>
|
||||||
{formatCellValue(
|
{formatCellValue(
|
||||||
col.name,
|
col.name,
|
||||||
|
|
@ -2732,7 +2732,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||||
<td
|
<td
|
||||||
key={colIdx}
|
key={colIdx}
|
||||||
className="px-3 py-2 text-sm whitespace-nowrap text-foreground"
|
className="px-3 py-2 text-sm whitespace-nowrap text-foreground"
|
||||||
style={{ textAlign: col.align || "left" }}
|
style={{ textAlign: col.align || "left", overflow: "hidden", textOverflow: "ellipsis" }}
|
||||||
>
|
>
|
||||||
{formatCellValue(
|
{formatCellValue(
|
||||||
col.name,
|
col.name,
|
||||||
|
|
@ -3415,7 +3415,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||||
<td
|
<td
|
||||||
key={colIdx}
|
key={colIdx}
|
||||||
className="px-3 py-2 text-sm whitespace-nowrap text-foreground"
|
className="px-3 py-2 text-sm whitespace-nowrap text-foreground"
|
||||||
style={{ textAlign: col.align || "left" }}
|
style={{ textAlign: col.align || "left", overflow: "hidden", textOverflow: "ellipsis" }}
|
||||||
>
|
>
|
||||||
{formatCellValue(
|
{formatCellValue(
|
||||||
col.name,
|
col.name,
|
||||||
|
|
|
||||||
|
|
@ -379,12 +379,33 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
||||||
}
|
}
|
||||||
}, [tableConfig.selectedTable, currentUserId]);
|
}, [tableConfig.selectedTable, currentUserId]);
|
||||||
|
|
||||||
// columnVisibility 변경 시 컬럼 순서 및 가시성 적용
|
// columnVisibility 변경 시 컬럼 순서, 가시성, 너비 적용
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (columnVisibility.length > 0) {
|
if (columnVisibility.length > 0) {
|
||||||
const newOrder = columnVisibility.map((cv) => cv.columnName).filter((name) => name !== "__checkbox__"); // 체크박스 제외
|
const newOrder = columnVisibility.map((cv) => cv.columnName).filter((name) => name !== "__checkbox__"); // 체크박스 제외
|
||||||
setColumnOrder(newOrder);
|
setColumnOrder(newOrder);
|
||||||
|
|
||||||
|
// 너비 적용
|
||||||
|
const newWidths: Record<string, number> = {};
|
||||||
|
columnVisibility.forEach((cv) => {
|
||||||
|
if (cv.width) {
|
||||||
|
newWidths[cv.columnName] = cv.width;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (Object.keys(newWidths).length > 0) {
|
||||||
|
setColumnWidths((prev) => ({ ...prev, ...newWidths }));
|
||||||
|
|
||||||
|
// table_column_widths_* localStorage도 동기화 (초기 너비 로드 시 올바른 값 사용)
|
||||||
|
if (tableConfig.selectedTable && userId) {
|
||||||
|
const widthsKey = `table_column_widths_${tableConfig.selectedTable}_${userId}`;
|
||||||
|
try {
|
||||||
|
const existing = localStorage.getItem(widthsKey);
|
||||||
|
const merged = existing ? { ...JSON.parse(existing), ...newWidths } : newWidths;
|
||||||
|
localStorage.setItem(widthsKey, JSON.stringify(merged));
|
||||||
|
} catch { /* ignore */ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// localStorage에 저장 (사용자별)
|
// localStorage에 저장 (사용자별)
|
||||||
if (tableConfig.selectedTable && currentUserId) {
|
if (tableConfig.selectedTable && currentUserId) {
|
||||||
const storageKey = `table_column_visibility_${tableConfig.selectedTable}_${currentUserId}`;
|
const storageKey = `table_column_visibility_${tableConfig.selectedTable}_${currentUserId}`;
|
||||||
|
|
|
||||||
|
|
@ -570,6 +570,8 @@ export const ButtonPrimaryComponent: React.FC<ButtonPrimaryComponentProps> = ({
|
||||||
...restComponentStyle,
|
...restComponentStyle,
|
||||||
width: "100%",
|
width: "100%",
|
||||||
height: "100%",
|
height: "100%",
|
||||||
|
borderRadius: _br || "0.5rem",
|
||||||
|
overflow: "hidden",
|
||||||
};
|
};
|
||||||
|
|
||||||
// 디자인 모드 스타일
|
// 디자인 모드 스타일
|
||||||
|
|
|
||||||
|
|
@ -3607,7 +3607,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||||
<td
|
<td
|
||||||
key={colIdx}
|
key={colIdx}
|
||||||
className="px-3 py-2 text-sm whitespace-nowrap text-foreground"
|
className="px-3 py-2 text-sm whitespace-nowrap text-foreground"
|
||||||
style={{ textAlign: col.align || "left" }}
|
style={{ textAlign: col.align || "left", overflow: "hidden", textOverflow: "ellipsis" }}
|
||||||
>
|
>
|
||||||
{formatCellValue(
|
{formatCellValue(
|
||||||
col.name,
|
col.name,
|
||||||
|
|
@ -3704,7 +3704,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||||
<td
|
<td
|
||||||
key={colIdx}
|
key={colIdx}
|
||||||
className="px-3 py-2 text-sm whitespace-nowrap text-foreground"
|
className="px-3 py-2 text-sm whitespace-nowrap text-foreground"
|
||||||
style={{ textAlign: col.align || "left" }}
|
style={{ textAlign: col.align || "left", overflow: "hidden", textOverflow: "ellipsis" }}
|
||||||
>
|
>
|
||||||
{formatCellValue(
|
{formatCellValue(
|
||||||
col.name,
|
col.name,
|
||||||
|
|
@ -4201,7 +4201,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||||
onClick={() => toggleRightItemExpansion(`tab_${activeTabIndex}_${tabItemId}`)}
|
onClick={() => toggleRightItemExpansion(`tab_${activeTabIndex}_${tabItemId}`)}
|
||||||
>
|
>
|
||||||
{tabSummaryColumns.map((col: any) => (
|
{tabSummaryColumns.map((col: any) => (
|
||||||
<td key={col.name} className="px-3 py-2 text-xs">
|
<td key={col.name} className="px-3 py-2 text-xs" style={{ overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
|
||||||
{col.type === "progress"
|
{col.type === "progress"
|
||||||
? renderProgressCell(col, item, selectedLeftItem)
|
? renderProgressCell(col, item, selectedLeftItem)
|
||||||
: formatCellValue(
|
: formatCellValue(
|
||||||
|
|
@ -4317,7 +4317,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||||
onClick={() => toggleRightItemExpansion(`tab_${activeTabIndex}_${tabItemId}`)}
|
onClick={() => toggleRightItemExpansion(`tab_${activeTabIndex}_${tabItemId}`)}
|
||||||
>
|
>
|
||||||
{listSummaryColumns.map((col: any) => (
|
{listSummaryColumns.map((col: any) => (
|
||||||
<td key={col.name} className="px-3 py-2 text-xs">
|
<td key={col.name} className="px-3 py-2 text-xs" style={{ overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
|
||||||
{col.type === "progress"
|
{col.type === "progress"
|
||||||
? renderProgressCell(col, item, selectedLeftItem)
|
? renderProgressCell(col, item, selectedLeftItem)
|
||||||
: formatCellValue(
|
: formatCellValue(
|
||||||
|
|
@ -4709,8 +4709,8 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||||
{columnsToShow.map((col, colIdx) => (
|
{columnsToShow.map((col, colIdx) => (
|
||||||
<td
|
<td
|
||||||
key={colIdx}
|
key={colIdx}
|
||||||
className="px-3 py-2 text-xs whitespace-nowrap"
|
className="px-3 py-2 text-xs"
|
||||||
style={{ textAlign: col.align || "left" }}
|
style={{ textAlign: col.align || "left", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}
|
||||||
>
|
>
|
||||||
{col.type === "progress"
|
{col.type === "progress"
|
||||||
? renderProgressCell(col, item, selectedLeftItem)
|
? renderProgressCell(col, item, selectedLeftItem)
|
||||||
|
|
@ -4856,7 +4856,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||||
onClick={() => toggleRightItemExpansion(itemId)}
|
onClick={() => toggleRightItemExpansion(itemId)}
|
||||||
>
|
>
|
||||||
{columnsToDisplay.map((col) => (
|
{columnsToDisplay.map((col) => (
|
||||||
<td key={col.name} className="px-3 py-2 text-xs">
|
<td key={col.name} className="px-3 py-2 text-xs" style={{ overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
|
||||||
{formatCellValue(
|
{formatCellValue(
|
||||||
col.name,
|
col.name,
|
||||||
getEntityJoinValue(item, col.name),
|
getEntityJoinValue(item, col.name),
|
||||||
|
|
|
||||||
|
|
@ -521,12 +521,33 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
||||||
}
|
}
|
||||||
}, [tableConfig.selectedTable, currentUserId]);
|
}, [tableConfig.selectedTable, currentUserId]);
|
||||||
|
|
||||||
// columnVisibility 변경 시 컬럼 순서 및 가시성 적용
|
// columnVisibility 변경 시 컬럼 순서, 가시성, 너비 적용
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (columnVisibility.length > 0) {
|
if (columnVisibility.length > 0) {
|
||||||
const newOrder = columnVisibility.map((cv) => cv.columnName).filter((name) => name !== "__checkbox__"); // 체크박스 제외
|
const newOrder = columnVisibility.map((cv) => cv.columnName).filter((name) => name !== "__checkbox__"); // 체크박스 제외
|
||||||
setColumnOrder(newOrder);
|
setColumnOrder(newOrder);
|
||||||
|
|
||||||
|
// 너비 적용
|
||||||
|
const newWidths: Record<string, number> = {};
|
||||||
|
columnVisibility.forEach((cv) => {
|
||||||
|
if (cv.width) {
|
||||||
|
newWidths[cv.columnName] = cv.width;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (Object.keys(newWidths).length > 0) {
|
||||||
|
setColumnWidths((prev) => ({ ...prev, ...newWidths }));
|
||||||
|
|
||||||
|
// table_column_widths_* localStorage도 동기화 (초기 너비 로드 시 올바른 값 사용)
|
||||||
|
if (tableConfig.selectedTable && userId) {
|
||||||
|
const widthsKey = `table_column_widths_${tableConfig.selectedTable}_${userId}`;
|
||||||
|
try {
|
||||||
|
const existing = localStorage.getItem(widthsKey);
|
||||||
|
const merged = existing ? { ...JSON.parse(existing), ...newWidths } : newWidths;
|
||||||
|
localStorage.setItem(widthsKey, JSON.stringify(merged));
|
||||||
|
} catch { /* ignore */ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// localStorage에 저장 (사용자별)
|
// localStorage에 저장 (사용자별)
|
||||||
if (tableConfig.selectedTable && currentUserId) {
|
if (tableConfig.selectedTable && currentUserId) {
|
||||||
const storageKey = `table_column_visibility_${tableConfig.selectedTable}_${currentUserId}`;
|
const storageKey = `table_column_visibility_${tableConfig.selectedTable}_${currentUserId}`;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue