새로고침해도 상태 유지하는 선택박스 만들었음
This commit is contained in:
@@ -10,6 +10,7 @@ import {
|
||||
PivotFlatRow,
|
||||
PivotFlatColumn,
|
||||
PivotCellValue,
|
||||
PivotColumnHeaderCell,
|
||||
DateGroupInterval,
|
||||
AggregationType,
|
||||
SummaryDisplayMode,
|
||||
@@ -76,6 +77,31 @@ export function pathToKey(path: string[]): string {
|
||||
return path.join("||");
|
||||
}
|
||||
|
||||
/**
|
||||
* 모든 가능한 경로 생성 (열 전체 확장용)
|
||||
*/
|
||||
function generateAllPaths(
|
||||
data: Record<string, any>[],
|
||||
fields: PivotFieldConfig[]
|
||||
): string[] {
|
||||
const allPaths: string[] = [];
|
||||
|
||||
// 각 레벨까지의 고유 경로 수집
|
||||
for (let depth = 1; depth <= fields.length; depth++) {
|
||||
const fieldsAtDepth = fields.slice(0, depth);
|
||||
const pathSet = new Set<string>();
|
||||
|
||||
data.forEach((row) => {
|
||||
const path = fieldsAtDepth.map((f) => getFieldValue(row, f));
|
||||
pathSet.add(pathToKey(path));
|
||||
});
|
||||
|
||||
pathSet.forEach((pathKey) => allPaths.push(pathKey));
|
||||
}
|
||||
|
||||
return allPaths;
|
||||
}
|
||||
|
||||
/**
|
||||
* 키를 경로로 변환
|
||||
*/
|
||||
@@ -326,6 +352,66 @@ function getMaxColumnLevel(
|
||||
return Math.min(maxLevel, totalFields - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 다중 행 열 헤더 생성
|
||||
* 각 레벨별로 셀과 colSpan 정보를 반환
|
||||
*/
|
||||
function buildColumnHeaderLevels(
|
||||
nodes: PivotHeaderNode[],
|
||||
totalLevels: number
|
||||
): PivotColumnHeaderCell[][] {
|
||||
if (totalLevels === 0 || nodes.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const levels: PivotColumnHeaderCell[][] = Array.from(
|
||||
{ length: totalLevels },
|
||||
() => []
|
||||
);
|
||||
|
||||
// 리프 노드 수 계산 (colSpan 계산용)
|
||||
function countLeaves(node: PivotHeaderNode): number {
|
||||
if (!node.children || node.children.length === 0 || !node.isExpanded) {
|
||||
return 1;
|
||||
}
|
||||
return node.children.reduce((sum, child) => sum + countLeaves(child), 0);
|
||||
}
|
||||
|
||||
// 트리 순회하며 각 레벨에 셀 추가
|
||||
function traverse(node: PivotHeaderNode, level: number) {
|
||||
const colSpan = countLeaves(node);
|
||||
|
||||
levels[level].push({
|
||||
caption: node.caption,
|
||||
colSpan,
|
||||
path: node.path,
|
||||
level,
|
||||
});
|
||||
|
||||
if (node.children && node.isExpanded) {
|
||||
for (const child of node.children) {
|
||||
traverse(child, level + 1);
|
||||
}
|
||||
} else if (level < totalLevels - 1) {
|
||||
// 확장되지 않은 노드는 다음 레벨들에 빈 셀로 채움
|
||||
for (let i = level + 1; i < totalLevels; i++) {
|
||||
levels[i].push({
|
||||
caption: "",
|
||||
colSpan,
|
||||
path: node.path,
|
||||
level: i,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const node of nodes) {
|
||||
traverse(node, 0);
|
||||
}
|
||||
|
||||
return levels;
|
||||
}
|
||||
|
||||
// ==================== 데이터 매트릭스 생성 ====================
|
||||
|
||||
/**
|
||||
@@ -735,12 +821,11 @@ export function processPivotData(
|
||||
uniqueValues.forEach((val) => expandedRowSet.add(val));
|
||||
}
|
||||
|
||||
if (expandedColumnPaths.length === 0 && columnFields.length > 0) {
|
||||
const firstField = columnFields[0];
|
||||
const uniqueValues = new Set(
|
||||
filteredData.map((row) => getFieldValue(row, firstField))
|
||||
);
|
||||
uniqueValues.forEach((val) => expandedColSet.add(val));
|
||||
// 열은 항상 전체 확장 (열 헤더는 확장/축소 UI가 없음)
|
||||
// 모든 가능한 열 경로를 확장 상태로 설정
|
||||
if (columnFields.length > 0) {
|
||||
const allColumnPaths = generateAllPaths(filteredData, columnFields);
|
||||
allColumnPaths.forEach((pathKey) => expandedColSet.add(pathKey));
|
||||
}
|
||||
|
||||
// 헤더 트리 생성
|
||||
@@ -788,6 +873,12 @@ export function processPivotData(
|
||||
grandTotals.grand
|
||||
);
|
||||
|
||||
// 다중 행 열 헤더 생성
|
||||
const columnHeaderLevels = buildColumnHeaderLevels(
|
||||
columnHeaders,
|
||||
columnFields.length
|
||||
);
|
||||
|
||||
return {
|
||||
rowHeaders,
|
||||
columnHeaders,
|
||||
@@ -799,6 +890,7 @@ export function processPivotData(
|
||||
caption: path[path.length - 1] || "",
|
||||
span: 1,
|
||||
})),
|
||||
columnHeaderLevels,
|
||||
grandTotals,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user