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(tooltip): enhance tooltip #862

Merged
merged 10 commits into from Dec 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 6 additions & 4 deletions CONTRIBUTING.md
Expand Up @@ -38,7 +38,7 @@
2. 安装依赖:`yarn bootstrap` 或者 `yarn`
3. 提交你的改动,commit 请遵守 [AngularJS Git Commit Message Conventions](https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit#heading=h.uyo6cb12dt6w)
4. 如果你的改动是修复 bug, 还可以在提交信息后面加上 `close #issue 号`, 这样可以在 pr 合并后,可以自动关闭对应的 issue, 比如 `fix: render bug close #123`
5. 确保加上了对应的单元测试
5. 确保加上了对应的单元测试和文档 (如有必要)
6. 所有 Lint 和 Test 检查通过后,并且 review 通过,我们会合并你的 pr.

![preview](https://gw.alipayobjects.com/zos/antfincdn/ssOxFrycD/86339514-5f9a-4101-8690-e47c97cd8af5.png)
Expand All @@ -54,6 +54,8 @@ npm i -g yarn
1. `yarn bootstrap` 安装依赖
2. `yarn site:bootstrap` 安装网站相关依赖
3. `yarn site:start` 启动本地的 `S2` 网站
4. `yarn core:start` 可视化的方式调试测试
5. `yarn build` 构建 `S2`, 输出 `umd`, `esm` 和 `lib` 目录
6. `yarn test` 运行单元格测试
4. `yarn core:start` 可视化的方式调试核心层测试 (基于 jest-electron)
5. `yarn react:start` 可视化的方式调试组件层测试 (基于 jest-electron)
6. `yarn react:playground` 启动本地的组件层demo (基于 vite)
7. `yarn build` 构建 `@antv/s2` 和 `@antv/s2-react` 两个包, 分别输出 `umd`, `esm` 和 `lib` 目录
8. `yarn test` 运行单元格测试
8 changes: 4 additions & 4 deletions README.en-US.md
Expand Up @@ -197,14 +197,14 @@ yarn site:bootstrap
yarn site:start
```

## 👬 Contributors

![https://github.com/antvis/s2/graphs/contributors](https://contrib.rocks/image?repo=antvis/s2)

## 📧 Contact Us

<img src="width: 100%; height: auto" href="https://gw.alipayobjects.com/zos/antfincdn/2zjO70QLdp/7939a108-930c-42a9-a0d3-fbfdc2cc44cf.jpg" alt="S2"></a>

## 👬 Contributors

![https://github.com/antvis/s2/graphs/contributors](https://contrib.rocks/image?repo=antvis/s2)

## 📄 License

MIT@[AntV](https://github.com/antvis).
18 changes: 15 additions & 3 deletions README.md
Expand Up @@ -179,14 +179,26 @@ git clone git@github.com:antvis/S2.git

cd S2

yarn
# 安装依赖
yarn # 或者 yarn bootstrap

# 调试 s2-core
yarn core:start

# 本地启动官网
# 调试 s2-react
yarn react:playground

yarn site:bootstrap
# 单元测试
yarn test

# 打包
yarn build

# 代码风格和类型检测
yarn lint

# 本地启动官网
yarn site:bootstrap
yarn site:start
```

Expand Down
15 changes: 12 additions & 3 deletions packages/s2-core/README.md
Expand Up @@ -174,14 +174,23 @@ git clone git@github.com:antvis/S2.git

cd S2

yarn
# 安装依赖
yarn # 或者 yarn bootstrap

# 调试
yarn core:start

# 本地启动官网
# 单元测试
yarn test

yarn site:bootstrap
# 打包
yarn build

# 代码风格和类型检测
yarn lint

# 本地启动官网
yarn site:bootstrap
yarn site:start
```

Expand Down
@@ -1,9 +1,17 @@
import { createFakeSpreadSheet, createMockCellInfo } from 'tests/util/helpers';
import {
createFakeSpreadSheet,
createMockCellInfo,
sleep,
} from 'tests/util/helpers';
import { Event as GEvent } from '@antv/g-canvas';
import { DataCellClick } from '@/interaction/base-interaction/click';
import { S2Options } from '@/common/interface';
import { SpreadSheet } from '@/sheet-type';
import { InteractionStateName, S2Event } from '@/common/constant';
import {
HOVER_FOCUS_TIME,
InteractionStateName,
S2Event,
} from '@/common/constant';

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

Expand All @@ -22,6 +30,9 @@ describe('Interaction Data Cell Click Tests', () => {
trend: false,
},
},
interaction: {
hoverHighlight: true,
},
} as S2Options;
s2.isTableMode = jest.fn(() => true);
});
Expand Down Expand Up @@ -76,4 +87,32 @@ describe('Interaction Data Cell Click Tests', () => {
record: mockCellData.data,
});
});

test('should clear hover timer when data cell toggle click', async () => {
const showTooltipWithInfoSpy = jest
.spyOn(s2, 'showTooltipWithInfo')
.mockImplementation(() => {});

const event = {
stopPropagation() {},
} as unknown as GEvent;

// trigger hover
s2.emit(S2Event.DATA_CELL_HOVER, event);

// select
s2.emit(S2Event.DATA_CELL_CLICK, event);
// unselect
s2.emit(S2Event.DATA_CELL_CLICK, event);

// wait hover focus time trigger
await sleep(HOVER_FOCUS_TIME + 500);

expect(s2.interaction.getCurrentStateName()).not.toEqual(
InteractionStateName.HOVER_FOCUS,
);

// only call show tooltip once for cell clicked
expect(showTooltipWithInfoSpy).toHaveReturnedTimes(1);
});
});
Expand Up @@ -160,6 +160,45 @@ describe('Interaction Brush Selection Tests', () => {
).toHaveBeenCalled();
});

// https://github.com/antvis/S2/issues/852
test('should clear brush selection state when mouse down and context menu clicked', () => {
const globalMouseUp = jest.fn();
mockSpreadSheetInstance.on(S2Event.GLOBAL_MOUSE_UP, globalMouseUp);

emitEvent(S2Event.DATA_CELL_MOUSE_DOWN, {
layerX: 10,
layerY: 20,
});
emitEvent(S2Event.DATA_CELL_MOUSE_MOVE, {
layerX: 12,
layerY: 22,
});

expect(brushSelectionInstance.brushSelectionStage).toEqual(
InteractionBrushSelectionStage.DRAGGED,
);

emitEvent(S2Event.GLOBAL_CONTEXT_MENU, {});

expect(globalMouseUp).not.toHaveBeenCalled();
expect(brushSelectionInstance.brushSelectionStage).toEqual(
InteractionBrushSelectionStage.UN_DRAGGED,
);
expect(
brushSelectionInstance.spreadsheet.interaction.hasIntercepts([
InterceptType.HOVER,
]),
).toBeFalsy();
expect(
brushSelectionInstance.spreadsheet.interaction.hasIntercepts([
InterceptType.BRUSH_SELECTION,
]),
).toBeFalsy();
expect(
brushSelectionInstance.hidePrepareSelectMaskShape,
).toHaveReturnedTimes(1);
});

test('should skip brush selection if mouse move less than valid distance', () => {
emitEvent(S2Event.DATA_CELL_MOUSE_MOVE, {});

Expand Down
112 changes: 73 additions & 39 deletions packages/s2-core/__tests__/unit/sheet-type/pivot-sheet-spec.ts
Expand Up @@ -62,10 +62,36 @@ describe('PivotSheet Tests', () => {
return {
[CellTypes.ROW_CELL]: 'row',
[CellTypes.COL_CELL]: 'col',
[CellTypes.DATA_CELL]: 'cell',
[CellTypes.DATA_CELL]: 'data',
[CellTypes.CORNER_CELL]: 'corner',
}[cellType];
};

test('should support callback tooltip content for string', () => {
s2.showTooltip({
position: {
x: 10,
y: 10,
},
content: () => 'custom callback content',
});

expect(s2.tooltip.container.innerHTML).toEqual('custom callback content');
});

test('should support callback tooltip content for element', () => {
const content = document.createElement('div');
s2.showTooltip({
position: {
x: 10,
y: 10,
},
content: () => content,
});

expect(s2.tooltip.container.contains(content)).toBeTruthy();
});

test('should init tooltip', () => {
s2.showTooltip({ position: { x: 0, y: 0 } });

Expand Down Expand Up @@ -157,7 +183,12 @@ describe('PivotSheet Tests', () => {
expect(sheet.tooltip.container.innerHTML).toEqual(tooltipContent);
});

test.each([CellTypes.ROW_CELL, CellTypes.COL_CELL, CellTypes.DATA_CELL])(
test.each([
CellTypes.ROW_CELL,
CellTypes.COL_CELL,
CellTypes.DATA_CELL,
CellTypes.CORNER_CELL,
])(
'should use %o tooltip content from tooltip config first for string content',
(cellType) => {
const tooltipContent = `${cellType} tooltip content`;
Expand Down Expand Up @@ -417,43 +448,6 @@ describe('PivotSheet Tests', () => {
expect(afterRender).toHaveBeenCalledTimes(1);
});

test('should destroy sheet', () => {
const facetDestroySpy = jest
.spyOn(s2.facet, 'destroy')
.mockImplementation(() => {});

const hdAdapterDestroySpy = jest
.spyOn(s2.hdAdapter, 'destroy')
.mockImplementation(() => {});

s2.render(false);

s2.store.set('test', 111);
s2.tooltip.container.classList.add('destroy-test');
s2.interaction.addIntercepts([InterceptType.HOVER]);
s2.interaction.interactions.set('test-interaction', null);
s2.destroy();

// clear store
expect(s2.store.size()).toEqual(0);
// clear interaction
expect(s2.interaction.getState()).toEqual({
cells: [],
force: false,
});
expect(s2.interaction.getHoverTimer()).toBeNull();
expect(s2.interaction.interactions.size).toEqual(0);
expect(s2.interaction.intercepts.size).toEqual(0);
expect(s2.interaction.eventController.canvasEventHandlers).toHaveLength(0);
expect(s2.interaction.eventController.domEventListeners).toHaveLength(0);
// destroy tooltip
expect(s2.tooltip.container.children).toHaveLength(0);
// destroy facet
expect(facetDestroySpy).toHaveBeenCalledTimes(1);
// destroy hdAdapter
expect(hdAdapterDestroySpy).toHaveBeenCalledTimes(1);
});

test('should updatePagination', () => {
s2.updatePagination({
current: 2,
Expand Down Expand Up @@ -665,6 +659,46 @@ describe('PivotSheet Tests', () => {
expect(renderSpy).toHaveBeenCalledTimes(2);
});

test('should destroy sheet', () => {
const facetDestroySpy = jest
.spyOn(s2.facet, 'destroy')
.mockImplementation(() => {});

const hdAdapterDestroySpy = jest
.spyOn(s2.hdAdapter, 'destroy')
.mockImplementation(() => {});

s2.render(false);

s2.store.set('test', 111);
s2.tooltip.container.classList.add('destroy-test');
s2.interaction.addIntercepts([InterceptType.HOVER]);
s2.interaction.interactions.set('test-interaction', null);
s2.container.on('test-event', () => {});
s2.destroy();

// clear store
expect(s2.store.size()).toEqual(0);
// clear interaction
expect(s2.interaction.getState()).toEqual({
cells: [],
force: false,
});
expect(s2.interaction.getHoverTimer()).toBeNull();
expect(s2.interaction.interactions.size).toEqual(0);
expect(s2.interaction.intercepts.size).toEqual(0);
expect(s2.interaction.eventController.canvasEventHandlers).toHaveLength(0);
expect(s2.interaction.eventController.domEventListeners).toHaveLength(0);
// destroy tooltip
expect(s2.tooltip.container.children).toHaveLength(0);
// destroy facet
expect(facetDestroySpy).toHaveBeenCalledTimes(1);
// destroy hdAdapter
expect(hdAdapterDestroySpy).toHaveBeenCalledTimes(1);
// clear all canvas events
expect(s2.getEvents()).toEqual({});
});

describe('Test Layout by dataCfg fields', () => {
beforeEach(() => {
s2.destroy();
Expand Down
15 changes: 8 additions & 7 deletions packages/s2-core/__tests__/unit/ui/tooltip/index-spec.ts
@@ -1,4 +1,4 @@
import { createFakeSpreadSheet } from 'tests/util/helpers';
import { createFakeSpreadSheet, sleep } from 'tests/util/helpers';
import type { SpreadSheet } from '@/sheet-type/spread-sheet';
import { BaseTooltip } from '@/ui/tooltip';
import { TOOLTIP_CONTAINER_CLS, TOOLTIP_POSITION_OFFSET } from '@/common';
Expand Down Expand Up @@ -127,30 +127,30 @@ describe('Tooltip Tests', () => {
expect(tooltip.container.innerHTML).toEqual('text');
});

test('should display custom dom element', () => {
test('should display custom dom element', async () => {
const element1 = document.createElement('span');
const element2 = document.createElement('span');

const position = {
x: 10,
y: 10,
};

element1.className = 'text1';
element2.className = 'text2';

tooltip.show({
position,
content: element1,
});

expect(tooltip.container.querySelector('.text1')).toBeTruthy();
expect(tooltip.container.contains(element1)).toBeTruthy();

tooltip.show({
position,
content: element2,
});

expect(tooltip.container.querySelector('.text2')).toBeTruthy();
await sleep(500);

expect(tooltip.container.contains(element2)).toBeTruthy();
expect(tooltip.container.children).toHaveLength(1);
});

Expand Down Expand Up @@ -193,6 +193,7 @@ describe('Tooltip Tests', () => {
});

expect(tooltip.container.querySelector('.text')).toBeTruthy();
expect(tooltip.container.contains(element)).toBeTruthy();
});

test('should replace tooltip content by call method', () => {
Expand Down