flowExecutionService 트랜잭션 처리 개선 및 데이터 변경 추적 로직 수정
This commit is contained in:
@@ -1669,53 +1669,53 @@ export function FlowWidget({
|
||||
>
|
||||
<Filter className="mr-1 h-3 w-3" />
|
||||
검색
|
||||
</Button>
|
||||
)}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* 필터/그룹 설정 버튼 */}
|
||||
|
||||
{/* 필터/그룹 설정 버튼 */}
|
||||
<div className="flex items-center gap-1 border-r border-border pr-2">
|
||||
<Button
|
||||
<Button
|
||||
variant={searchFilterColumns.size > 0 ? "default" : "ghost"}
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
if (!isPreviewMode) {
|
||||
setIsFilterSettingOpen(true);
|
||||
}
|
||||
}}
|
||||
disabled={isPreviewMode}
|
||||
}}
|
||||
disabled={isPreviewMode}
|
||||
className="h-7 text-xs"
|
||||
title="검색 필터 설정"
|
||||
>
|
||||
>
|
||||
<Filter className="mr-1 h-3 w-3" />
|
||||
필터
|
||||
{searchFilterColumns.size > 0 && (
|
||||
{searchFilterColumns.size > 0 && (
|
||||
<span className="ml-1 rounded-full bg-white/20 px-1.5 text-[10px]">
|
||||
{searchFilterColumns.size}
|
||||
{searchFilterColumns.size}
|
||||
</span>
|
||||
)}
|
||||
</Button>
|
||||
)}
|
||||
</Button>
|
||||
<Button
|
||||
variant={groupByColumns.length > 0 ? "default" : "ghost"}
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
if (!isPreviewMode) {
|
||||
setIsGroupSettingOpen(true);
|
||||
}
|
||||
}}
|
||||
disabled={isPreviewMode}
|
||||
}}
|
||||
disabled={isPreviewMode}
|
||||
className="h-7 text-xs"
|
||||
title="그룹 설정"
|
||||
>
|
||||
>
|
||||
<Layers className="mr-1 h-3 w-3" />
|
||||
그룹
|
||||
{groupByColumns.length > 0 && (
|
||||
{groupByColumns.length > 0 && (
|
||||
<span className="ml-1 rounded-full bg-white/20 px-1.5 text-[10px]">
|
||||
{groupByColumns.length}
|
||||
{groupByColumns.length}
|
||||
</span>
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 새로고침 */}
|
||||
<div className="ml-auto flex items-center gap-1">
|
||||
@@ -1731,7 +1731,7 @@ export function FlowWidget({
|
||||
새로고침
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 검색 필터 입력 영역 */}
|
||||
{searchFilterColumns.size > 0 && (
|
||||
@@ -1859,20 +1859,20 @@ export function FlowWidget({
|
||||
{groupByColumns.length > 0 && groupedData.length > 0 ? (
|
||||
// 그룹화된 렌더링 (기존 방식 유지)
|
||||
<div className="overflow-x-auto">
|
||||
<Table noWrapper>
|
||||
<Table noWrapper>
|
||||
<TableHeader className="sticky top-0 z-30 bg-background shadow-sm">
|
||||
<TableRow className="hover:bg-muted/50">
|
||||
{allowDataMove && (
|
||||
<TableRow className="hover:bg-muted/50">
|
||||
{allowDataMove && (
|
||||
<TableHead className="bg-background sticky left-0 z-40 w-12 border-b px-6 py-3 text-center">
|
||||
<Checkbox
|
||||
checked={selectedRows.size === stepData.length && stepData.length > 0}
|
||||
onCheckedChange={toggleAllRows}
|
||||
/>
|
||||
</TableHead>
|
||||
)}
|
||||
{stepDataColumns.map((col) => (
|
||||
<TableHead
|
||||
key={col}
|
||||
<Checkbox
|
||||
checked={selectedRows.size === stepData.length && stepData.length > 0}
|
||||
onCheckedChange={toggleAllRows}
|
||||
/>
|
||||
</TableHead>
|
||||
)}
|
||||
{stepDataColumns.map((col) => (
|
||||
<TableHead
|
||||
key={col}
|
||||
className="bg-background border-b px-6 py-3 text-sm font-semibold whitespace-nowrap cursor-pointer hover:bg-muted/50"
|
||||
onClick={() => handleSort(col)}
|
||||
>
|
||||
@@ -1884,68 +1884,68 @@ export function FlowWidget({
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</TableHead>
|
||||
))}
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
</TableHead>
|
||||
))}
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{groupedData.flatMap((group) => {
|
||||
const isCollapsed = collapsedGroups.has(group.groupKey);
|
||||
const groupRows = [
|
||||
<TableRow key={`group-${group.groupKey}`}>
|
||||
<TableCell
|
||||
colSpan={stepDataColumns.length + (allowDataMove ? 1 : 0)}
|
||||
className="bg-muted/50 border-b"
|
||||
const isCollapsed = collapsedGroups.has(group.groupKey);
|
||||
const groupRows = [
|
||||
<TableRow key={`group-${group.groupKey}`}>
|
||||
<TableCell
|
||||
colSpan={stepDataColumns.length + (allowDataMove ? 1 : 0)}
|
||||
className="bg-muted/50 border-b"
|
||||
>
|
||||
<div
|
||||
className="flex items-center gap-3 p-2 cursor-pointer hover:bg-muted"
|
||||
onClick={() => toggleGroupCollapse(group.groupKey)}
|
||||
>
|
||||
<div
|
||||
className="flex items-center gap-3 p-2 cursor-pointer hover:bg-muted"
|
||||
onClick={() => toggleGroupCollapse(group.groupKey)}
|
||||
>
|
||||
{isCollapsed ? (
|
||||
<ChevronRight className="h-4 w-4 flex-shrink-0" />
|
||||
) : (
|
||||
<ChevronDown className="h-4 w-4 flex-shrink-0" />
|
||||
)}
|
||||
<span className="font-medium text-sm flex-1">{group.groupKey}</span>
|
||||
<span className="text-muted-foreground text-xs">({group.count}건)</span>
|
||||
</div>
|
||||
</TableCell>
|
||||
</TableRow>,
|
||||
];
|
||||
{isCollapsed ? (
|
||||
<ChevronRight className="h-4 w-4 flex-shrink-0" />
|
||||
) : (
|
||||
<ChevronDown className="h-4 w-4 flex-shrink-0" />
|
||||
)}
|
||||
<span className="font-medium text-sm flex-1">{group.groupKey}</span>
|
||||
<span className="text-muted-foreground text-xs">({group.count}건)</span>
|
||||
</div>
|
||||
</TableCell>
|
||||
</TableRow>,
|
||||
];
|
||||
|
||||
if (!isCollapsed) {
|
||||
const dataRows = group.items.map((row, itemIndex) => {
|
||||
if (!isCollapsed) {
|
||||
const dataRows = group.items.map((row, itemIndex) => {
|
||||
const actualIndex = sortedDisplayData.indexOf(row);
|
||||
return (
|
||||
<TableRow
|
||||
key={`${group.groupKey}-${itemIndex}`}
|
||||
className={`h-16 transition-colors hover:bg-muted/50 ${selectedRows.has(actualIndex) ? "bg-primary/5" : ""}`}
|
||||
>
|
||||
{allowDataMove && (
|
||||
<TableCell className="bg-background sticky left-0 z-10 border-b px-6 py-3 text-center">
|
||||
<Checkbox
|
||||
checked={selectedRows.has(actualIndex)}
|
||||
onCheckedChange={() => toggleRowSelection(actualIndex)}
|
||||
/>
|
||||
</TableCell>
|
||||
)}
|
||||
{stepDataColumns.map((col) => (
|
||||
<TableCell key={col} className="h-16 border-b px-6 py-3 text-sm whitespace-nowrap">
|
||||
{formatValue(row[col])}
|
||||
</TableCell>
|
||||
))}
|
||||
</TableRow>
|
||||
);
|
||||
});
|
||||
groupRows.push(...dataRows);
|
||||
}
|
||||
return (
|
||||
<TableRow
|
||||
key={`${group.groupKey}-${itemIndex}`}
|
||||
className={`h-16 transition-colors hover:bg-muted/50 ${selectedRows.has(actualIndex) ? "bg-primary/5" : ""}`}
|
||||
>
|
||||
{allowDataMove && (
|
||||
<TableCell className="bg-background sticky left-0 z-10 border-b px-6 py-3 text-center">
|
||||
<Checkbox
|
||||
checked={selectedRows.has(actualIndex)}
|
||||
onCheckedChange={() => toggleRowSelection(actualIndex)}
|
||||
/>
|
||||
</TableCell>
|
||||
)}
|
||||
{stepDataColumns.map((col) => (
|
||||
<TableCell key={col} className="h-16 border-b px-6 py-3 text-sm whitespace-nowrap">
|
||||
{formatValue(row[col])}
|
||||
</TableCell>
|
||||
))}
|
||||
</TableRow>
|
||||
);
|
||||
});
|
||||
groupRows.push(...dataRows);
|
||||
}
|
||||
|
||||
return groupRows;
|
||||
return groupRows;
|
||||
})}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
) : (
|
||||
) : (
|
||||
// 일반 렌더링 - SingleTableWithSticky 사용
|
||||
<SingleTableWithSticky
|
||||
visibleColumns={tableColumns}
|
||||
|
||||
Reference in New Issue
Block a user