Skip to content

Commit

Permalink
Merge branch 'master' into latest
Browse files Browse the repository at this point in the history
  • Loading branch information
lijinke666 committed Feb 23, 2024
2 parents c4cf12f + 8d9c5b2 commit d2d4d85
Show file tree
Hide file tree
Showing 24 changed files with 301 additions and 103 deletions.
57 changes: 57 additions & 0 deletions packages/s2-core/__tests__/bugs/issue-2528-spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/**
* @description spec for issue #2528
* https://github.com/antvis/S2/issues/2528
*/

import * as mockDataConfig from '../data/simple-table-data.json';
import { getContainer } from '../util/helpers';
import type { SpreadSheet, S2DataConfig, S2Options } from '@/index';
import { TableSheet } from '@/sheet-type';

const s2DataConfig: S2DataConfig = {
...mockDataConfig,
meta: [{ field: 'cost', formatter: (v) => `${v}-@` }],
};

const s2Options: S2Options = {
width: 800,
height: 400,
};

describe('Table Sheet Editable Formatter Tests', () => {
let s2: SpreadSheet;

beforeEach(() => {
s2 = new TableSheet(getContainer(), s2DataConfig, s2Options);

s2.render();
});

test('should get formatted data', () => {
const costValues = s2.interaction
.getPanelGroupAllDataCells()
.filter((cell) => cell.getMeta().valueField === 'cost')
.map((cell) => cell.getFieldValue());

expect(costValues).toEqual(['2-@', '2-@', '2-@']);
});

test('should only format data once after data edited', () => {
const id = '0-root[&]cost';
const inputValue = 'test';

// 模拟一次编辑 (更新第一行的 cost)
const displayData = s2.dataSet.getDisplayDataSet();
displayData[0].cost = inputValue;
s2.dataSet.displayFormattedValueMap?.set(id, inputValue);

s2.render();

const costValues = s2.interaction
.getPanelGroupAllDataCells()
.filter((cell) => cell.getMeta().valueField === 'cost')
.map((cell) => cell.getFieldValue());

expect(costValues).toEqual([inputValue, '2-@', '2-@']);
});
});
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import * as mockDataConfig from 'tests/data/simple-data.json';
import { createMockCellInfo, getContainer } from 'tests/util/helpers';
import {
createMockCellInfo,
createPivotSheet,
getContainer,
sleep,
} from 'tests/util/helpers';
import { size, sumBy } from 'lodash';
import { getTooltipData, mergeCellInfo } from '../../src/utils/tooltip';
import { PivotSheet, SpreadSheet } from '@/sheet-type';
Expand All @@ -20,8 +25,8 @@ const s2Options: S2Options = {
describe('Interaction Multi Selection Tests', () => {
let s2: SpreadSheet;

const expectNodes = (ids: string[] = []) => {
const state = s2.interaction.getState();
const expectNodes = (ids: string[] = [], instance: SpreadSheet = s2) => {
const state = instance.interaction.getState();
const nodeIds = state.nodes.map((node) => node.id);
expect(nodeIds).toEqual(ids);
};
Expand Down Expand Up @@ -120,7 +125,11 @@ describe('Interaction Multi Selection Tests', () => {
cell: rowRootCell,
});

expectNodes(['root[&]中国[&]浙江[&]义乌', 'root[&]中国[&]浙江[&]杭州']);
expectNodes([
'root[&]中国[&]浙江',
'root[&]中国[&]浙江[&]义乌',
'root[&]中国[&]浙江[&]杭州',
]);

const tooltipData = getTestTooltipData(rowRootCell);

Expand Down Expand Up @@ -150,11 +159,67 @@ describe('Interaction Multi Selection Tests', () => {
cell: colRootCell,
});

expectNodes(['root[&]中国[&]浙江[&]price', 'root[&]中国[&]浙江[&]cost']);
expectNodes([
'root[&]中国[&]浙江',
'root[&]中国[&]浙江[&]price',
'root[&]中国[&]浙江[&]cost',
]);

const tooltipData = getTestTooltipData(colRootCell);

expect(getSelectedCount(tooltipData.summaries)).toEqual(4);
expect(getSelectedSum(tooltipData.summaries)).toEqual(6);
});

// https://github.com/antvis/S2/issues/2503
test('should keep all cell highlighted after scroll', async () => {
const pivotSheet = createPivotSheet(
{
style: {
// 显示滚动条
cellCfg: {
width: 200,
},
},
},
{ useSimpleData: false },
);

pivotSheet.render();

const colRootCell = pivotSheet.interaction.getAllColHeaderCells()[0];

pivotSheet.interaction.selectHeaderCell({
cell: colRootCell,
});

await sleep(100);

pivotSheet.updateScrollOffset({
offsetX: {
value: 100,
animate: true,
},
});

await sleep(500);

expectNodes(
[
'root[&]家具[&]桌子',
'root[&]家具[&]桌子[&]number',
'root[&]家具[&]沙发',
'root[&]家具[&]沙发[&]number',
],
pivotSheet,
);

const interactedCells = pivotSheet.interaction.getInteractedCells();

['root[&]家具[&]桌子', 'root[&]家具[&]沙发'].forEach((id) => {
expect(
interactedCells.find((cell) => cell.getMeta().id === id),
).toBeTruthy();
});
});
});
1 change: 1 addition & 0 deletions packages/s2-core/__tests__/unit/facet/pivot-facet-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ jest.mock('@/data-set/pivot-data-set', () => {
getDimensionValues: actualPivotDataSet.prototype.getDimensionValues,
getFieldsAndPivotMetaByField:
actualPivotDataSet.prototype.getFieldsAndPivotMetaByField,
displayFormattedValueMap: new Map(),
};
}),
};
Expand Down
1 change: 1 addition & 0 deletions packages/s2-core/__tests__/unit/facet/table-facet-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ jest.mock('@/sheet-type', () => {
},
dataSet: {
isEmpty: jest.fn(),
displayFormattedValueMap: new Map(),
},
};
}),
Expand Down
6 changes: 5 additions & 1 deletion packages/s2-core/__tests__/unit/utils/tooltip-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -450,9 +450,13 @@ describe('Tooltip Utils Tests', () => {
let s2: SpreadSheet;

const getMockTooltipData = (cell: S2CellType) => {
const node = cell.getMeta() as Node;
// #getSelectedCellIndexes mock
node.isLeaf = true;

jest.spyOn(s2.interaction, 'getState').mockImplementationOnce(() => ({
cells: [getCellMeta(cell)],
nodes: [cell.getMeta() as Node],
nodes: [node],
}));

jest
Expand Down
1 change: 1 addition & 0 deletions packages/s2-core/__tests__/util/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ export const createFakeSpreadSheet = () => {
getMultiData() {
return [];
},
displayFormattedValueMap: new Map(),
} as unknown as any;
s2.facet = {
layoutResult: {
Expand Down
3 changes: 2 additions & 1 deletion packages/s2-core/src/cell/base-cell.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ import type { GuiIcon } from '../common/icons/gui-icon';
import { checkIsLinkField } from '../utils/interaction/link-field';
import type { Node } from '../facet/layout/node';
import type { ViewMeta } from '../common/interface/basic';
import { customMerge } from '../utils/merge';

export abstract class BaseCell<T extends SimpleBBox> extends Group {
// cell's data meta info
Expand Down Expand Up @@ -113,7 +114,7 @@ export abstract class BaseCell<T extends SimpleBBox> extends Group {
}

public setMeta(viewMeta: T) {
this.meta = viewMeta;
this.meta = customMerge(this.meta, viewMeta);
}

public getIconStyle() {
Expand Down
12 changes: 8 additions & 4 deletions packages/s2-core/src/cell/data-cell.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,8 @@ export class DataCell extends BaseCell<ViewMeta> {
}
}

public setMeta(viewMeta: ViewMeta) {
super.setMeta(viewMeta);
public setMeta(viewMeta: Partial<ViewMeta>) {
super.setMeta(viewMeta as ViewMeta);
this.initCell();
}

Expand Down Expand Up @@ -293,12 +293,16 @@ export class DataCell extends BaseCell<ViewMeta> {
formattedValue: EMPTY_PLACEHOLDER,
};
}
const { rowId, valueField, fieldValue, data } = this.meta;

const { rowId, valueField, fieldValue, data, id } = this.meta;
const displayFormattedValue =
this.spreadsheet.dataSet.displayFormattedValueMap?.get(id);
const rowMeta = this.spreadsheet.dataSet.getFieldMeta(rowId);
const fieldId = rowMeta ? rowId : valueField;
const formatter = this.spreadsheet.dataSet.getFieldFormatter(fieldId);
// TODO: 这里只用 formatter(fieldValue, this.meta) 即可, 为了保持兼容, 暂时在第三个参入传入 meta 信息
const formattedValue = formatter(fieldValue, data, this.meta);
const formattedValue =
displayFormattedValue ?? formatter(fieldValue, data, this.meta);

return {
value: fieldValue,
Expand Down
1 change: 0 additions & 1 deletion packages/s2-core/src/cell/table-data-cell.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {
getOrCreateResizeAreaGroupById,
getResizeAreaAttrs,
} from '../utils/interaction/resize';
import { checkIsLinkField } from '../utils/interaction/link-field';

export class TableDataCell extends DataCell {
protected getLinkFieldStyle() {
Expand Down
3 changes: 3 additions & 0 deletions packages/s2-core/src/data-set/base-data-set.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ export abstract class BaseDataSet {
// 透视表入口对象实例
public spreadsheet: SpreadSheet;

// 单元格所对应格式化后的值(用于编辑表)
public displayFormattedValueMap = new Map<string, string>();

public constructor(spreadsheet: SpreadSheet) {
this.spreadsheet = spreadsheet;
}
Expand Down
48 changes: 42 additions & 6 deletions packages/s2-core/src/facet/base-facet.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { IElement, IGroup, Event as GraphEvent } from '@antv/g-canvas';
import type { Event as GraphEvent, IElement, IGroup } from '@antv/g-canvas';
import { Group } from '@antv/g-canvas';
import { Wheel, type GestureEvent } from '@antv/g-gesture';
import { interpolateArray } from 'd3-interpolate';
Expand All @@ -24,6 +24,7 @@ import {
KEY_GROUP_ROW_RESIZE_AREA,
OriginEventType,
S2Event,
ScrollDirection,
ScrollbarPositionType,
} from '../common/constant';
import { DEFAULT_PAGE_INDEX } from '../common/constant/pagination';
Expand Down Expand Up @@ -74,7 +75,6 @@ import {
optimizeScrollXY,
translateGroup,
} from './utils';
import type { BaseHeader, BaseHeaderConfig } from './header/base';

export abstract class BaseFacet {
// spreadsheet instance
Expand Down Expand Up @@ -133,6 +133,8 @@ export abstract class BaseFacet {
layoutResult?: LayoutResult,
): ViewCellHeights;

protected scrollDirection: ScrollDirection;

protected scrollFrameId: ReturnType<typeof requestAnimationFrame> = null;

get scrollBarTheme() {
Expand Down Expand Up @@ -183,26 +185,57 @@ export abstract class BaseFacet {
this.hScrollBar?.show();
};

onContainerWheelForMobileCompatibility = () => {
const canvas = this.spreadsheet.getCanvasElement();
let startY: number;
let endY: number;

canvas.addEventListener('touchstart', (event) => {
startY = event.touches[0].clientY;
});

canvas.addEventListener('touchend', (event) => {
endY = event.changedTouches[0].clientY;
if (endY < startY) {
this.scrollDirection = ScrollDirection.SCROLL_UP;
} else if (endY > startY) {
this.scrollDirection = ScrollDirection.SCROLL_DOWN;
}
});
};

onContainerWheel = () => {
this.onContainerWheelForPc();
this.onContainerWheelForMobile();
};

// [email protected] 手指快速往上滚动时, deltaY 有时会为负数, 导致向下滚动时然后回弹, 看起来就像表格在抖动, 需要判断滚动方向, 修正一下.
getMobileWheelDeltaY = (deltaY: number) => {
if (this.scrollDirection === ScrollDirection.SCROLL_UP) {
return Math.max(0, deltaY);
}

if (this.scrollDirection === ScrollDirection.SCROLL_DOWN) {
return Math.min(0, deltaY);
}

return deltaY;
};

onContainerWheelForPc = () => {
const canvas = this.spreadsheet.getCanvasElement();
canvas?.addEventListener('wheel', this.onWheel);
};

onContainerWheelForMobile = () => {
// mock wheel event fo mobile
this.mobileWheel = new Wheel(this.spreadsheet.container);

this.mobileWheel.on('wheel', (ev: GestureEvent) => {
this.spreadsheet.hideTooltip();
const originEvent = ev.event;
const { deltaX, deltaY, x, y } = ev;
// The coordinates of mobile and pc are three times different
// TODO: 手指快速往上滚动时, deltaY 有时会为负数, 导致向下滚动时然后回弹, 看起来就像表格在抖动, 需要判断滚动方向, next 版本未复现
const { deltaX, deltaY: defaultDeltaY, x, y } = ev;
const deltaY = this.getMobileWheelDeltaY(defaultDeltaY);

this.onWheel({
...originEvent,
deltaX,
Expand All @@ -211,6 +244,8 @@ export abstract class BaseFacet {
offsetY: y,
} as unknown as WheelEvent);
});

this.onContainerWheelForMobileCompatibility();
};

bindEvents = () => {
Expand Down Expand Up @@ -930,6 +965,7 @@ export abstract class BaseFacet {
const { interaction } = this.spreadsheet.options;

if (interaction.overscrollBehavior !== 'auto') {
this.cancelScrollFrame();
this.stopScrollChaining(event);
}
};
Expand Down
4 changes: 1 addition & 3 deletions packages/s2-core/src/interaction/root.ts
Original file line number Diff line number Diff line change
Expand Up @@ -323,12 +323,10 @@ export class RootInteraction {
return;
}

// 高亮所有的子节点, 但是只有叶子节点需要参与数据计算
const needCalcNodes = childrenNodes.filter((node) => node?.isLeaf);
// 兼容行列多选 (高亮 行/列头 以及相对应的数值单元格)
this.changeState({
cells: selectedCells,
nodes: needCalcNodes,
nodes: childrenNodes,
stateName: InteractionStateName.SELECTED,
});

Expand Down
Loading

0 comments on commit d2d4d85

Please sign in to comment.