11
This commit is contained in:
@@ -21,7 +21,7 @@ import {
|
||||
Move,
|
||||
FileSpreadsheet,
|
||||
List,
|
||||
LayoutPanelRight,
|
||||
PanelRight,
|
||||
} from "lucide-react";
|
||||
import { dataApi } from "@/lib/api/data";
|
||||
import { entityJoinApi } from "@/lib/api/entityJoin";
|
||||
@@ -3524,7 +3524,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||
{columnsToShow.map((col, idx) => (
|
||||
<th
|
||||
key={idx}
|
||||
className="px-3 py-2 text-left text-xs font-medium tracking-wider text-muted-foreground uppercase whitespace-nowrap"
|
||||
className="px-3 py-[7px] text-left text-[9px] font-bold tracking-[0.04em] text-muted-foreground uppercase whitespace-nowrap"
|
||||
style={{
|
||||
width: col.width && col.width <= 100 ? `${col.width}%` : "auto",
|
||||
textAlign: col.align || "left",
|
||||
@@ -3534,7 +3534,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||
</th>
|
||||
))}
|
||||
{hasGroupedLeftActions && (
|
||||
<th className="bg-muted sticky right-0 z-10 px-3 py-2 text-right text-xs font-medium tracking-wider text-muted-foreground uppercase whitespace-nowrap" style={{ width: "80px" }}>
|
||||
<th className="bg-muted sticky right-0 z-10 px-3 py-[7px] text-right text-[9px] font-bold tracking-[0.04em] text-muted-foreground uppercase whitespace-nowrap" style={{ width: "80px" }}>
|
||||
</th>
|
||||
)}
|
||||
</tr>
|
||||
@@ -3621,7 +3621,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||
{columnsToShow.map((col, idx) => (
|
||||
<th
|
||||
key={idx}
|
||||
className="px-3 py-2 text-left text-xs font-medium tracking-wider text-muted-foreground uppercase whitespace-nowrap"
|
||||
className="px-3 py-[7px] text-left text-[9px] font-bold tracking-[0.04em] text-muted-foreground uppercase whitespace-nowrap"
|
||||
style={{
|
||||
width: col.width && col.width <= 100 ? `${col.width}%` : "auto",
|
||||
textAlign: col.align || "left",
|
||||
@@ -3631,7 +3631,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||
</th>
|
||||
))}
|
||||
{hasLeftTableActions && (
|
||||
<th className="bg-muted sticky right-0 z-10 px-3 py-2 text-right text-xs font-medium tracking-wider text-muted-foreground uppercase whitespace-nowrap" style={{ width: "80px" }}>
|
||||
<th className="bg-muted sticky right-0 z-10 px-3 py-[7px] text-right text-[9px] font-bold tracking-[0.04em] text-muted-foreground uppercase whitespace-nowrap" style={{ width: "80px" }}>
|
||||
</th>
|
||||
)}
|
||||
</tr>
|
||||
@@ -3972,17 +3972,17 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||
>
|
||||
<div className="flex w-full items-center justify-between gap-2">
|
||||
<div className="flex min-w-0 flex-1 items-center gap-2">
|
||||
<LayoutPanelRight className="h-4 w-4 shrink-0 text-muted-foreground" />
|
||||
<PanelRight className="h-4 w-4 shrink-0 text-muted-foreground" />
|
||||
{/* 탭이 없으면 제목만, 있으면 탭으로 전환 (2px primary 밑줄 인디케이터) */}
|
||||
{(componentConfig.rightPanel?.additionalTabs?.length || 0) > 0 ? (
|
||||
<div className="flex items-center gap-0">
|
||||
<button
|
||||
onClick={() => handleTabChange(0)}
|
||||
className={cn(
|
||||
"px-3 py-1 text-sm font-medium transition-colors",
|
||||
"px-3.5 py-2 text-[10px] font-semibold transition-all -mb-px",
|
||||
activeTabIndex === 0
|
||||
? "text-primary border-b-2 border-primary font-semibold bg-primary/5"
|
||||
: "text-foreground/70 hover:text-foreground hover:bg-muted/30"
|
||||
? "text-primary border-b-2 border-primary"
|
||||
: "text-muted-foreground border-b-2 border-transparent hover:text-foreground"
|
||||
)}
|
||||
>
|
||||
{componentConfig.rightPanel?.title || "기본"}
|
||||
@@ -3992,10 +3992,10 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||
key={tab.tabId || `tab-${index}`}
|
||||
onClick={() => handleTabChange(index + 1)}
|
||||
className={cn(
|
||||
"px-3 py-1 text-sm font-medium transition-colors",
|
||||
"px-3.5 py-2 text-[10px] font-semibold transition-all -mb-px",
|
||||
activeTabIndex === index + 1
|
||||
? "text-primary border-b-2 border-primary font-semibold bg-primary/5"
|
||||
: "text-foreground/70 hover:text-foreground hover:bg-muted/30"
|
||||
? "text-primary border-b-2 border-primary"
|
||||
: "text-muted-foreground border-b-2 border-transparent hover:text-foreground"
|
||||
)}
|
||||
>
|
||||
{tab.label || `탭 ${index + 1}`}
|
||||
@@ -4120,7 +4120,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||
<th
|
||||
key={col.name}
|
||||
className={cn(
|
||||
"text-muted-foreground px-3 py-2 text-left text-xs font-semibold",
|
||||
"text-muted-foreground px-3 py-[7px] text-left text-[9px] font-bold uppercase tracking-[0.04em]",
|
||||
isDropTarget && "border-l-[3px] border-l-primary bg-primary/5",
|
||||
canDragTabColumns && "cursor-grab active:cursor-grabbing",
|
||||
isDragging && "opacity-50",
|
||||
@@ -4136,7 +4136,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||
);
|
||||
})}
|
||||
{hasTabActions && (
|
||||
<th className="text-muted-foreground px-3 py-2 text-right text-xs font-semibold">작업</th>
|
||||
<th className="text-muted-foreground px-3 py-[7px] text-right text-[9px] font-bold uppercase tracking-[0.04em]">작업</th>
|
||||
)}
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -4157,13 +4157,13 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||
<React.Fragment key={tabItemId}>
|
||||
<tr
|
||||
className={cn(
|
||||
"cursor-pointer border-b border-border/40 transition-colors",
|
||||
isTabExpanded ? "bg-primary/5" : idx % 2 === 1 ? "bg-muted/10 hover:bg-muted/30" : "hover:bg-muted/30",
|
||||
"group/action cursor-pointer border-b border-border/50 transition-[background] duration-75",
|
||||
isTabExpanded ? "bg-primary/5" : idx % 2 === 1 ? "bg-muted/50 hover:bg-accent" : "hover:bg-accent",
|
||||
)}
|
||||
onClick={() => toggleRightItemExpansion(`tab_${activeTabIndex}_${tabItemId}`)}
|
||||
>
|
||||
{tabSummaryColumns.map((col: any) => (
|
||||
<td key={col.name} className="px-3 py-2 text-xs" style={{ overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
|
||||
<td key={col.name} className="px-3 py-2 text-[11px]" style={{ overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
|
||||
{col.type === "progress"
|
||||
? renderProgressCell(col, item, selectedLeftItem)
|
||||
: formatCellValue(
|
||||
@@ -4256,7 +4256,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||
<th
|
||||
key={col.name}
|
||||
className={cn(
|
||||
"text-muted-foreground px-3 py-2 text-left text-xs font-semibold",
|
||||
"text-muted-foreground px-3 py-[7px] text-left text-[9px] font-bold uppercase tracking-[0.04em]",
|
||||
isDropTarget && "border-l-[3px] border-l-primary bg-primary/5",
|
||||
canDragListTabColumns && "cursor-grab active:cursor-grabbing",
|
||||
isDragging && "opacity-50",
|
||||
@@ -4272,7 +4272,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||
);
|
||||
})}
|
||||
{hasTabActions && (
|
||||
<th className="text-muted-foreground px-3 py-2 text-right text-xs font-semibold">작업</th>
|
||||
<th className="text-muted-foreground px-3 py-[7px] text-right text-[9px] font-bold uppercase tracking-[0.04em]">작업</th>
|
||||
)}
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -4292,13 +4292,13 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||
<React.Fragment key={tabItemId}>
|
||||
<tr
|
||||
className={cn(
|
||||
"cursor-pointer border-b border-border/40 transition-colors",
|
||||
isTabExpanded ? "bg-primary/5" : idx % 2 === 1 ? "bg-muted/10 hover:bg-muted/30" : "hover:bg-muted/30",
|
||||
"group/action cursor-pointer border-b border-border/50 transition-[background] duration-75",
|
||||
isTabExpanded ? "bg-primary/5" : idx % 2 === 1 ? "bg-muted/50 hover:bg-accent" : "hover:bg-accent",
|
||||
)}
|
||||
onClick={() => toggleRightItemExpansion(`tab_${activeTabIndex}_${tabItemId}`)}
|
||||
>
|
||||
{listSummaryColumns.map((col: any) => (
|
||||
<td key={col.name} className="px-3 py-2 text-xs" style={{ overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
|
||||
<td key={col.name} className="px-3 py-2 text-[11px]" style={{ overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
|
||||
{col.type === "progress"
|
||||
? renderProgressCell(col, item, selectedLeftItem)
|
||||
: formatCellValue(
|
||||
@@ -4670,7 +4670,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||
<th
|
||||
key={idx}
|
||||
className={cn(
|
||||
"text-muted-foreground px-3 py-2 text-left text-xs font-semibold whitespace-nowrap",
|
||||
"text-muted-foreground px-3 py-[7px] text-left text-[9px] font-bold uppercase tracking-[0.04em] whitespace-nowrap",
|
||||
isDropTarget && "border-l-[3px] border-l-primary bg-primary/5",
|
||||
isDraggable && "cursor-grab active:cursor-grabbing",
|
||||
isDragging && "opacity-50",
|
||||
@@ -4689,26 +4689,29 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||
</th>
|
||||
);
|
||||
})}
|
||||
{/* 수정 또는 삭제 버튼이 하나라도 활성화되어 있을 때만 작업 컬럼 표시 */}
|
||||
{!isDesignMode &&
|
||||
((componentConfig.rightPanel?.editButton?.enabled ?? true) ||
|
||||
(componentConfig.rightPanel?.deleteButton?.enabled ?? true)) && (
|
||||
<th className="text-muted-foreground px-3 py-2 text-right text-xs font-semibold" style={{ width: '80px' }}>
|
||||
{(() => {
|
||||
const rightEditVisible = (componentConfig.rightPanel?.showEdit ?? componentConfig.rightPanel?.editButton?.enabled) !== false;
|
||||
const rightDeleteVisible = (componentConfig.rightPanel?.showDelete ?? componentConfig.rightPanel?.deleteButton?.enabled) !== false;
|
||||
return !isDesignMode && (rightEditVisible || rightDeleteVisible) ? (
|
||||
<th className="bg-background text-muted-foreground sticky right-0 z-10 px-3 py-[7px] text-right text-[9px] font-bold uppercase tracking-[0.04em]" style={{ width: '80px' }}>
|
||||
작업
|
||||
</th>
|
||||
)}
|
||||
) : null;
|
||||
})()}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{filteredData.map((item, idx) => {
|
||||
const itemId = item.id || item.ID || idx;
|
||||
const rightEditVisible = (componentConfig.rightPanel?.showEdit ?? componentConfig.rightPanel?.editButton?.enabled) !== false;
|
||||
const rightDeleteVisible = (componentConfig.rightPanel?.showDelete ?? componentConfig.rightPanel?.deleteButton?.enabled) !== false;
|
||||
|
||||
return (
|
||||
<tr key={itemId} className={cn("group/action border-b border-border/40 transition-colors hover:bg-muted/30", idx % 2 === 1 && "bg-muted/10")}>
|
||||
<tr key={itemId} className={cn("group/action border-b border-border/50 transition-[background] duration-75 hover:bg-accent", idx % 2 === 1 && "bg-muted/50")}>
|
||||
{columnsToShow.map((col, colIdx) => (
|
||||
<td
|
||||
key={colIdx}
|
||||
className="px-3 py-2 text-xs"
|
||||
className="px-3 py-2 text-[11px]"
|
||||
style={{ textAlign: col.align || "left", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}
|
||||
>
|
||||
{col.type === "progress"
|
||||
@@ -4722,12 +4725,10 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||
</td>
|
||||
))}
|
||||
{/* 수정 또는 삭제 버튼이 하나라도 활성화되어 있을 때만 작업 셀 표시 */}
|
||||
{!isDesignMode &&
|
||||
((componentConfig.rightPanel?.editButton?.enabled ?? true) ||
|
||||
(componentConfig.rightPanel?.deleteButton?.enabled ?? true)) && (
|
||||
<td className="px-3 py-2 text-right text-sm whitespace-nowrap group/action">
|
||||
{!isDesignMode && (rightEditVisible || rightDeleteVisible) && (
|
||||
<td className="bg-card sticky right-0 z-10 px-3 py-2 text-right text-sm whitespace-nowrap group-hover/action:bg-accent">
|
||||
<div className="flex justify-end gap-1 opacity-0 transition-opacity group-hover/action:opacity-100">
|
||||
{(componentConfig.rightPanel?.editButton?.enabled ?? true) && (
|
||||
{rightEditVisible && (
|
||||
<Button
|
||||
variant={
|
||||
componentConfig.rightPanel?.editButton?.buttonVariant || "outline"
|
||||
@@ -4743,7 +4744,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||
{componentConfig.rightPanel?.editButton?.buttonLabel || "수정"}
|
||||
</Button>
|
||||
)}
|
||||
{(componentConfig.rightPanel?.deleteButton?.enabled ?? true) && (
|
||||
{rightDeleteVisible && (
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
@@ -4801,8 +4802,8 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||
return sum + w;
|
||||
}, 0);
|
||||
|
||||
const hasEditButton = !isDesignMode && (componentConfig.rightPanel?.editButton?.enabled ?? true);
|
||||
const hasDeleteButton = !isDesignMode && (componentConfig.rightPanel?.deleteButton?.enabled ?? true);
|
||||
const hasEditButton = !isDesignMode && (componentConfig.rightPanel?.showEdit ?? componentConfig.rightPanel?.editButton?.enabled) !== false;
|
||||
const hasDeleteButton = !isDesignMode && (componentConfig.rightPanel?.showDelete ?? componentConfig.rightPanel?.deleteButton?.enabled) !== false;
|
||||
const hasActions = hasEditButton || hasDeleteButton;
|
||||
|
||||
return filteredData.length > 0 ? (
|
||||
@@ -4814,14 +4815,14 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||
{columnsToDisplay.map((col) => (
|
||||
<th
|
||||
key={col.name}
|
||||
className="text-muted-foreground px-3 py-2 text-left text-xs font-semibold whitespace-nowrap"
|
||||
className="text-muted-foreground px-3 py-[7px] text-left text-[9px] font-bold uppercase tracking-[0.04em] whitespace-nowrap"
|
||||
style={{ width: col.width && col.width <= 100 ? `${col.width}%` : "auto" }}
|
||||
>
|
||||
{col.label}
|
||||
</th>
|
||||
))}
|
||||
{hasActions && (
|
||||
<th className="text-muted-foreground px-3 py-2 text-right text-xs font-semibold" style={{ width: '80px' }}>작업</th>
|
||||
<th className="bg-background text-muted-foreground sticky right-0 z-10 px-3 py-[7px] text-right text-[9px] font-bold uppercase tracking-[0.04em]" style={{ width: '80px' }}>작업</th>
|
||||
)}
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -4849,13 +4850,13 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||
<React.Fragment key={itemId}>
|
||||
<tr
|
||||
className={cn(
|
||||
"group/action cursor-pointer border-b border-border/40 transition-colors",
|
||||
isExpanded ? "bg-primary/5" : idx % 2 === 1 ? "bg-muted/10 hover:bg-muted/30" : "hover:bg-muted/30",
|
||||
"group/action cursor-pointer border-b border-border/50 transition-[background] duration-75",
|
||||
isExpanded ? "bg-primary/5" : idx % 2 === 1 ? "bg-muted/50 hover:bg-accent" : "hover:bg-accent",
|
||||
)}
|
||||
onClick={() => toggleRightItemExpansion(itemId)}
|
||||
>
|
||||
{columnsToDisplay.map((col) => (
|
||||
<td key={col.name} className="px-3 py-2 text-xs" style={{ overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
|
||||
<td key={col.name} className="px-3 py-2 text-[11px]" style={{ overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
|
||||
{formatCellValue(
|
||||
col.name,
|
||||
getEntityJoinValue(item, col.name),
|
||||
@@ -4865,7 +4866,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||
</td>
|
||||
))}
|
||||
{hasActions && (
|
||||
<td className="px-3 py-2 text-right">
|
||||
<td className="bg-card sticky right-0 z-10 px-3 py-2 text-right group-hover/action:bg-accent">
|
||||
<div className="flex items-center justify-end gap-1 opacity-0 transition-opacity group-hover/action:opacity-100">
|
||||
{hasEditButton && (
|
||||
<Button size="sm" variant="ghost" className="h-7 px-2 text-xs"
|
||||
|
||||
Reference in New Issue
Block a user