fix: 피벗 ConfigPanel — 컬럼별 area dropdown 폐기, 메타 옵션 8종으로 교체

T4 (3e6bce70d) 의 ④ 피벗 설정이 빌더에서 row/column/data/filter 를 컬럼별
dropdown 으로 미리 정해버려 피벗의 본질 (사용자 자유 분석) 을 흐림. 본체
(FieldPanel / FieldChooser) 가 영역 배치 담당하도록 일관성 정리 (Excel 피벗
패턴).

삭제 — "사번 [row▼] / 사용자ID [row▼] ..." 컬럼별 area dropdown 매핑 67줄

신규 ④ 피벗 설정 — 메타 토글 8종 (CPRow + CPSwitch)
- 차트 표시 (pivotChart.enabled)
- 필드 선택기 (pivotFieldChooser.enabled)
- 행 총계 (pivotTotals.showRowGrandTotals)
- 열 총계 (pivotTotals.showColumnGrandTotals)
- 셀 병합 (pivotStyle.mergeCells)
- 행 교대 색 (pivotStyle.alternateRowColors)
- 엑셀 내보내기 (pivotExportConfig.excel)
- PDF 내보내기 (pivotExportConfig.pdf)

빌더 = "피벗에 어떤 도구/표시를 켤지" 만 결정.
본체 = row/column/data/filter 영역 배치 + drag-and-drop + drilldown + filter
+ chart 등 분석 인터랙션 담당 (이미 T3b 통째 흡수됨).

다른 viewMode (grouped: groupBy / card: cardColumnMapping) 는 본체 분석 UI
가 없으므로 ConfigPanel 이 핵심 — pivot 만 메타 패턴으로 가는 게 맞다
(Codex GO 판정).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
DDD1542
2026-04-29 16:33:13 +09:00
parent 3003a056d9
commit 3ed53a6708
@@ -281,73 +281,122 @@ export const InvTableConfigPanel: React.FC<InvTableConfigPanelProps> = ({
)}
{displayMode === "pivot" && (
<CPSection title="④ 피벗 설정" desc="row · column · data 영역에 컬럼 배치">
{columns.length === 0 ? (
<Hint tone="warn"> .</Hint>
) : (
<>
<Hint>
. data .
</Hint>
{columns.map((col, idx) => {
const fields = current.pivotFields ?? [];
const fieldIdx = fields.findIndex((f) => f.field === col.key);
const field = fieldIdx >= 0 ? fields[fieldIdx] : undefined;
const area = field?.area ?? "none";
const summaryType = field?.summaryType ?? "sum";
const updateField = (next: Partial<NonNullable<TableConfig["pivotFields"]>[number]> | "remove") => {
const list = [...fields];
if (next === "remove") {
if (fieldIdx >= 0) list.splice(fieldIdx, 1);
} else if (fieldIdx >= 0) {
list[fieldIdx] = { ...list[fieldIdx], ...next };
} else {
list.push({
field: col.key,
caption: col.label || col.key,
area: "row",
...next,
});
}
patch({ pivotFields: list });
};
return (
<CPRow key={col.key} label={col.label || col.key}>
<div style={{ display: "flex", gap: 6, alignItems: "center" }}>
<CPSelect
value={area}
onChange={(v) => {
if (v === "none") updateField("remove");
else updateField({ area: v as any });
}}
searchable={false}
>
<option value="none"></option>
<option value="row">row</option>
<option value="column">column</option>
<option value="data">data</option>
<option value="filter">filter</option>
</CPSelect>
{area === "data" && (
<CPSelect
value={summaryType}
onChange={(v) => updateField({ summaryType: v as any })}
searchable={false}
>
<option value="sum"></option>
<option value="count"></option>
<option value="avg"></option>
<option value="min"></option>
<option value="max"></option>
<option value="countDistinct"> </option>
</CPSelect>
)}
</div>
</CPRow>
);
})}
</>
)}
<CPSection title="④ 피벗 설정" desc="본체 분석 UI에서 사용할 표시 옵션">
{/* 피벗 필드 배치는 PivotView 본체의 FieldPanel/FieldChooser가 담당한다. ConfigPanel은 메타 옵션만 관리한다. */}
<CPRow label="차트 표시">
<CPSwitch
value={current.pivotChart?.enabled ?? false}
onChange={(v) =>
patch({
pivotChart: {
type: current.pivotChart?.type ?? "bar",
position: current.pivotChart?.position ?? "bottom",
...current.pivotChart,
enabled: v,
},
})
}
/>
</CPRow>
<CPRow label="필드 선택기">
<CPSwitch
value={current.pivotFieldChooser?.enabled ?? true}
onChange={(v) =>
patch({
pivotFieldChooser: {
...current.pivotFieldChooser,
enabled: v,
},
})
}
/>
</CPRow>
<CPRow label="행 총계">
<CPSwitch
value={current.pivotTotals?.showRowGrandTotals ?? true}
onChange={(v) =>
patch({
pivotTotals: {
...current.pivotTotals,
showRowGrandTotals: v,
},
})
}
/>
</CPRow>
<CPRow label="열 총계">
<CPSwitch
value={current.pivotTotals?.showColumnGrandTotals ?? true}
onChange={(v) =>
patch({
pivotTotals: {
...current.pivotTotals,
showColumnGrandTotals: v,
},
})
}
/>
</CPRow>
<CPRow label="셀 병합">
<CPSwitch
value={current.pivotStyle?.mergeCells ?? false}
onChange={(v) =>
patch({
pivotStyle: {
theme: current.pivotStyle?.theme ?? "default",
headerStyle: current.pivotStyle?.headerStyle ?? "default",
cellPadding: current.pivotStyle?.cellPadding ?? "normal",
borderStyle: current.pivotStyle?.borderStyle ?? "light",
...current.pivotStyle,
mergeCells: v,
},
})
}
/>
</CPRow>
<CPRow label="행 교대 색">
<CPSwitch
value={current.pivotStyle?.alternateRowColors ?? true}
onChange={(v) =>
patch({
pivotStyle: {
theme: current.pivotStyle?.theme ?? "default",
headerStyle: current.pivotStyle?.headerStyle ?? "default",
cellPadding: current.pivotStyle?.cellPadding ?? "normal",
borderStyle: current.pivotStyle?.borderStyle ?? "light",
...current.pivotStyle,
alternateRowColors: v,
},
})
}
/>
</CPRow>
<CPRow label="엑셀 내보내기">
<CPSwitch
value={current.pivotExportConfig?.excel ?? false}
onChange={(v) =>
patch({
pivotExportConfig: {
...current.pivotExportConfig,
excel: v,
},
})
}
/>
</CPRow>
<CPRow label="PDF 내보내기">
<CPSwitch
value={current.pivotExportConfig?.pdf ?? false}
onChange={(v) =>
patch({
pivotExportConfig: {
...current.pivotExportConfig,
pdf: v,
},
})
}
/>
</CPRow>
</CPSection>
)}