Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: selected cell highlight #1878

Merged
merged 27 commits into from
Dec 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
408b79f
Merge pull request #1 from antvis/master
LHC8888 Oct 18, 2022
c4239b7
Merge pull request #2 from antvis/master
LHC8888 Oct 30, 2022
511d3c2
feat: upgrade selectedCellHighlight option & 修复 selectedCellHighlight…
LHC8888 Oct 30, 2022
c1c6e89
feat: selectedCellHighlight option 复制功能
LHC8888 Oct 30, 2022
5d92f37
fix: selectedCellHighlight 为 false 的情况
LHC8888 Nov 1, 2022
06677b4
fix: 修复单测报错
LHC8888 Nov 1, 2022
f15385d
feat: 补充单测
LHC8888 Nov 5, 2022
c70434a
feat: selectedCellHighlight 配置项补充文档
LHC8888 Nov 6, 2022
54d8532
Merge branch 'master' into feat-selectedCellHighlight
xingwanying Nov 9, 2022
3ab9c34
refactor: 调整 BaseDataSet.getRowData 为抽象方法
LHC8888 Nov 9, 2022
714147f
refactor: remove unused code
LHC8888 Nov 9, 2022
8c0d9b9
refactor: 调整 selectedCellHighlight option 实现逻辑
LHC8888 Nov 12, 2022
9e67823
feat: 修改文档 & react playground
LHC8888 Nov 12, 2022
d51ba0e
refactor: 调整 selectedCellHighlight option 复制实现
LHC8888 Nov 13, 2022
22fff32
feat: 调整单测
LHC8888 Nov 13, 2022
b692446
Merge branch 'feat-selectedCellHighlight' of github.com:LHC8888/S2 in…
LHC8888 Nov 13, 2022
5b40a2c
fix: type error
LHC8888 Nov 14, 2022
0f33e48
Merge pull request #4 from antvis/master
LHC8888 Nov 15, 2022
7ace4ee
refactor: selectedCellHighlight option 调整数据单元格点击事件 headerCells 存储逻辑
LHC8888 Dec 3, 2022
8e04e68
feat: selectedCellHighlight option 统一刷选的交互 & afterSelectDataCells 函数提取
LHC8888 Dec 3, 2022
4152f74
refactor: remove duplicate constant
LHC8888 Dec 3, 2022
1348cac
refactor: selectedCellHighlight option selectedCellHighlightAdaptor 调…
LHC8888 Dec 3, 2022
362b721
Merge branch 'master' into feat-selectedCellHighlight
LHC8888 Dec 19, 2022
1a77fac
Merge branch 'master' into feat-selectedCellHighlight
stone-lyl Dec 20, 2022
ab0be37
fix: lint error
LHC8888 Dec 20, 2022
f9cd9b8
fix: unit test
LHC8888 Dec 20, 2022
e4e26b5
Merge branch 'master' into feat-selectedCellHighlight
stone-lyl Dec 22, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ import type { S2Options } from '@/common/interface';
import type { SpreadSheet } from '@/sheet-type';
import {
HOVER_FOCUS_DURATION,
type InteractionCellSelectedHighlightType,
InteractionName,
InteractionStateName,
InterceptType,
S2Event,
} from '@/common/constant';
import type { Node } from '@/facet/layout/node';

jest.mock('@/interaction/event-controller');

Expand Down Expand Up @@ -50,6 +52,7 @@ describe('Interaction Data Cell Click Tests', () => {
expect(s2.interaction.getState()).toEqual({
cells: [mockCellInfo.mockCellMeta],
stateName: InteractionStateName.SELECTED,
onUpdateCells: expect.any(Function),
});
expect(s2.showTooltipWithInfo).toHaveBeenCalled();
});
Expand All @@ -68,6 +71,7 @@ describe('Interaction Data Cell Click Tests', () => {
expect(s2.interaction.getState()).toEqual({
cells: [mockCellInfo.mockCellMeta],
stateName: InteractionStateName.SELECTED,
onUpdateCells: expect.any(Function),
});
});

Expand Down Expand Up @@ -160,4 +164,66 @@ describe('Interaction Data Cell Click Tests', () => {
expect(s2.interaction.isHoverFocusState()).toBeFalsy();
expect(clearHoverTimerSpy).toHaveBeenCalledTimes(2);
});

test('should highlight the column header cell when data cell clicked', () => {
const headerCellId0 = 'header-0';
const headerCellId1 = 'header-1';
const columnNode: Array<Partial<Node>> = [
{
belongsCell: {
getMeta: () => ({
id: headerCellId0,
colIndex: -1,
rowIndex: -1,
}),
} as any,
id: headerCellId0,
},
{
belongsCell: {
getMeta: () => ({
id: headerCellId1,
colIndex: -1,
rowIndex: -1,
}),
} as any,
id: headerCellId1,
},
];
s2.getColumnNodes = jest.fn(() => columnNode) as any;
s2.getRowNodes = jest.fn(() => []);

const firstDataCellInfo = createMockCellInfo(
`${headerCellId0}[&]first-data-cell`,
);
s2.getCell = () => firstDataCellInfo.mockCell as any;

s2.setOptions({
interaction: {
selectedCellHighlight: {
colHeader: true,
} as InteractionCellSelectedHighlightType,
},
});

const mockHeaderCellInfo = createMockCellInfo(headerCellId0, {
colIndex: columnNode[0].belongsCell.getMeta().colIndex,
rowIndex: columnNode[0].belongsCell.getMeta().rowIndex,
});

s2.interaction.getAllColHeaderCells = jest.fn();
s2.interaction.updateCells = jest.fn();

s2.emit(S2Event.DATA_CELL_CLICK, {
stopPropagation() {},
} as unknown as GEvent);

expect(s2.interaction.getState()).toEqual({
cells: [firstDataCellInfo.mockCellMeta, mockHeaderCellInfo.mockCellMeta],
stateName: InteractionStateName.SELECTED,
onUpdateCells: expect.any(Function),
});
expect(s2.interaction.getAllColHeaderCells).toHaveBeenCalled();
expect(s2.interaction.updateCells).toHaveBeenCalled();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,12 @@ describe('Interaction Data Cell Brush Selection Tests', () => {
mockSpreadSheetInstance.showTooltipWithInfo = jest.fn();
mockRootInteraction.getPanelGroupAllDataCells = () =>
panelGroupAllDataCells;
mockRootInteraction.getSelectedCellHighlight = () => ({
rowHeader: false,
colHeader: false,
rowCells: false,
colCells: false,
});
mockSpreadSheetInstance.interaction = mockRootInteraction;
mockSpreadSheetInstance.render();
mockSpreadSheetInstance.facet.layoutResult.colLeafNodes = Array.from(
Expand Down Expand Up @@ -135,6 +141,12 @@ describe('Interaction Data Cell Brush Selection Tests', () => {
mockSpreadSheetInstance.setOptions({
interaction: { selectedCellHighlight: true },
});
mockRootInteraction.getSelectedCellHighlight = () => ({
rowHeader: true,
colHeader: true,
rowCells: false,
colCells: false,
});

brushSelectionInstance.getBrushRange = () => {
return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ describe('Interaction Data Cell Multi Selection Tests', () => {
expect(s2.interaction.getState()).toEqual({
cells: [mockCellA.mockCellMeta, mockCellB.mockCellMeta],
stateName: InteractionStateName.SELECTED,
onUpdateCells: expect.any(Function),
});

expect(
Expand Down Expand Up @@ -151,6 +152,7 @@ describe('Interaction Data Cell Multi Selection Tests', () => {
expect(s2.interaction.getState()).toEqual({
cells: [mockCellB.mockCellMeta],
stateName: InteractionStateName.SELECTED,
onUpdateCells: expect.any(Function),
});

expect(
Expand Down
21 changes: 21 additions & 0 deletions packages/s2-core/__tests__/unit/utils/export/copy-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,27 @@ describe('List Table Core Data Process', () => {
const data = getSelectedData(sss);
expect(data).toBe(convertString(newLineText));
});

it('should copy row data when select data row cell', () => {
s2.setOptions({
interaction: {
selectedCellHighlight: {
rowCells: true,
},
},
});

const cell = s2.interaction
.getAllCells()
.filter(({ cellType }) => cellType === CellTypes.DATA_CELL)[0];

s2.interaction.changeState({
cells: [getCellMeta(cell)],
stateName: InteractionStateName.SELECTED,
});

expect(getSelectedData(s2).split('\t').length).toBe(5);
});
});

describe('Pivot Table Core Data Process', () => {
Expand Down
4 changes: 3 additions & 1 deletion packages/s2-core/__tests__/util/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,12 +124,13 @@ export function getGradient(

export const createMockCellInfo = (
cellId: string,
{ colIndex = 0, rowIndex = 0 } = {},
{ colIndex = 0, rowIndex = 0, colId = '0' } = {},
) => {
const mockCellViewMeta: Partial<ViewMeta> = {
id: cellId,
colIndex,
rowIndex,
colId,
type: undefined,
x: 0,
y: 0,
Expand All @@ -154,6 +155,7 @@ export const createMockCellInfo = (
'y',
'update',
'spreadsheet',
'colId',
]);
const mockCell = {
...mockCellViewMeta,
Expand Down
13 changes: 10 additions & 3 deletions packages/s2-core/src/cell/data-cell.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ import type {
ViewMetaIndexType,
} from '../common/interface';
import { getBorderPositionAndStyle, getMaxTextWidth } from '../utils/cell/cell';
import { includeCell } from '../utils/cell/data-cell';
import {
includeCell,
shouldUpdateBySelectedCellsHighlight,
updateBySelectedCellsHighlight,
} from '../utils/cell/data-cell';
import { getIconPositionCfg } from '../utils/condition/condition';
import { renderLine, renderRect, updateShapeAttr } from '../utils/g-renders';
import { EMPTY_PLACEHOLDER } from '../common/constant/basic';
Expand Down Expand Up @@ -80,6 +84,7 @@ export class DataCell extends BaseCell<ViewMeta> {

protected handleSelect(cells: CellMeta[]) {
const currentCellType = cells?.[0]?.type;

switch (currentCellType) {
// 列多选
case CellTypes.COL_CELL:
Expand All @@ -91,7 +96,9 @@ export class DataCell extends BaseCell<ViewMeta> {
break;
// 单元格单选/多选
case CellTypes.DATA_CELL:
if (includeCell(cells, this)) {
if (shouldUpdateBySelectedCellsHighlight(this.spreadsheet)) {
updateBySelectedCellsHighlight(cells, this, this.spreadsheet);
} else if (includeCell(cells, this)) {
this.updateByState(InteractionStateName.SELECTED);
} else if (
this.spreadsheet.options.interaction.selectedCellsSpotlight
Expand Down Expand Up @@ -134,7 +141,7 @@ export class DataCell extends BaseCell<ViewMeta> {

public update() {
const stateName = this.spreadsheet.interaction.getCurrentStateName();
const cells = this.spreadsheet.interaction.getCells();
const cells = this.spreadsheet.interaction.getCells([CellTypes.DATA_CELL]);

if (stateName === InteractionStateName.ALL_SELECTED) {
this.updateByState(InteractionStateName.SELECTED);
Expand Down
8 changes: 6 additions & 2 deletions packages/s2-core/src/cell/header-cell.ts
Original file line number Diff line number Diff line change
Expand Up @@ -325,10 +325,11 @@ export abstract class HeaderCell extends BaseCell<Node> {
}
}

protected handleSelect(cells: CellMeta[], nodes: Node[]) {
protected handleSelect(cells: Array<CellMeta>, nodes: Node[]) {
if (includeCell(cells, this)) {
this.updateByState(InteractionStateName.SELECTED);
}

const selectedNodeIds = map(nodes, 'id');
if (includes(selectedNodeIds, this.meta.id)) {
this.updateByState(InteractionStateName.SELECTED);
Expand Down Expand Up @@ -382,7 +383,10 @@ export abstract class HeaderCell extends BaseCell<Node> {
public update() {
const { interaction } = this.spreadsheet;
const stateInfo = interaction?.getState();
const cells = interaction?.getCells();
const cells = interaction?.getCells([
CellTypes.COL_CELL,
CellTypes.ROW_CELL,
]);

if (!first(cells)) {
return;
Expand Down
7 changes: 7 additions & 0 deletions packages/s2-core/src/common/constant/interaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,3 +112,10 @@ export enum ScrollDirection {
LEADING = 'leading',
TRAILING = 'trailing',
}

export interface InteractionCellSelectedHighlightType {
rowHeader?: boolean; // 高亮行头
colHeader?: boolean; // 高亮列头
rowCells?: boolean; // 高亮选中单元格所在行
colCells?: boolean; // 高亮选中单元格所在列
}
2 changes: 2 additions & 0 deletions packages/s2-core/src/common/interface/basic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -515,3 +515,5 @@ export interface GridInfo {
cols: number[];
rows: number[];
}

export type RowData = Data | DataType;
4 changes: 3 additions & 1 deletion packages/s2-core/src/common/interface/interaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type {
CellTypes,
InterceptType,
ScrollbarPositionType,
InteractionCellSelectedHighlightType,
} from '../constant';
import type {
BaseCell,
Expand Down Expand Up @@ -35,6 +36,7 @@ export interface CellMeta {
colIndex: number;
rowIndex: number;
type: CellTypes;
rowQuery?: Record<string, any>;
[key: string]: unknown;
}

Expand Down Expand Up @@ -169,7 +171,7 @@ export interface InteractionOptions {
// https://developer.mozilla.org/zh-CN/docs/Web/API/EventTarget/addEventListener
eventListenerOptions?: boolean | AddEventListenerOptions;
// highlight col and row header for selected cell
selectedCellHighlight?: boolean;
selectedCellHighlight?: boolean | InteractionCellSelectedHighlightType;
// https://developer.mozilla.org/en-US/docs/Web/CSS/overscroll-behavior
overscrollBehavior?: 'auto' | 'none' | 'contain';
/** ***********CUSTOM INTERACTION HOOKS**************** */
Expand Down
7 changes: 7 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 @@ -23,6 +23,7 @@ import {
getValueRangeState,
setValueRangeState,
} from '../utils/condition/state-controller';
import type { CellMeta, RowData } from '../common';
import type { CellDataParams, DataType } from './index';

export abstract class BaseDataSet {
Expand Down Expand Up @@ -177,4 +178,10 @@ export abstract class BaseDataSet {
public moreThanOneValue() {
return this.fields?.values?.length > 1;
}

/**
* get a row cells data including cell
* @param cells
*/
public abstract getRowData(cells: CellMeta): RowData;
}
6 changes: 6 additions & 0 deletions packages/s2-core/src/data-set/pivot-data-set.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import type {
PartDrillDownFieldInLevel,
S2DataConfig,
ViewMeta,
RowData,
} from '../common/interface';
import { Node } from '../facet/layout/node';
import {
Expand All @@ -56,6 +57,7 @@ import {
} from '../utils/dataset/pivot-data-set';
import { calcActionByType } from '../utils/number-calculate';
import { handleSortAction } from '../utils/sort-action';
import type { CellMeta } from '../common';
import { BaseDataSet } from './base-data-set';
import type {
CellDataParams,
Expand Down Expand Up @@ -618,4 +620,8 @@ export class PivotDataSet extends BaseDataSet {
private isCustomMeasuresPosition(customValueOrder?: number) {
return isNumber(customValueOrder);
}

public getRowData(cell: CellMeta): RowData {
return this.getMultiData(cell.rowQuery);
}
}
6 changes: 6 additions & 0 deletions packages/s2-core/src/data-set/table-data-set.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { each, orderBy, filter, includes, isFunction, isObject } from 'lodash';
import { isAscSort, isDescSort } from '..';
import type { S2DataConfig } from '../common/interface';
import type { CellMeta } from '../common';
import type { RowData } from '../common/interface/basic';
import type { CellDataParams, DataType } from './interface';
import { BaseDataSet } from './base-data-set';

Expand Down Expand Up @@ -167,4 +169,8 @@ export class TableDataSet extends BaseDataSet {
public getMultiData(query: DataType, isTotals?: boolean): DataType[] {
return this.displayData;
}

public getRowData(cell: CellMeta): RowData {
return this.getCellData({ query: { rowIndex: cell.rowIndex } });
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ import type {
} from '../../../common/interface';
import {
getCellMeta,
updateRowColCells,
getInteractionCells,
afterSelectDataCells,
} from '../../../utils/interaction/select-event';
import {
getTooltipOptions,
Expand All @@ -30,7 +31,7 @@ export class DataCellClick extends BaseEvent implements BaseEventImplement {
this.spreadsheet.on(S2Event.DATA_CELL_CLICK, (event: CanvasEvent) => {
event.stopPropagation();

const { interaction, options } = this.spreadsheet;
const { interaction } = this.spreadsheet;
interaction.clearHoverTimer();

if (interaction.hasIntercepts([InterceptType.CLICK])) {
Expand Down Expand Up @@ -60,15 +61,12 @@ export class DataCellClick extends BaseEvent implements BaseEventImplement {
}

interaction.changeState({
stone-lyl marked this conversation as resolved.
Show resolved Hide resolved
cells: [getCellMeta(cell)],
cells: getInteractionCells(getCellMeta(cell), this.spreadsheet),
stateName: InteractionStateName.SELECTED,
onUpdateCells: afterSelectDataCells,
});
this.spreadsheet.emit(S2Event.GLOBAL_SELECTED, [cell]);
this.showTooltip(event, meta);

if (options.interaction.selectedCellHighlight) {
updateRowColCells(meta);
}
});
}

Expand Down
Loading