Introduce multi selection
Summary: Make sure DataTable supports multiselection, which works largely the same as before, with a few changes * shift + click and ctrl + click work as expected * shift + keyboard navigation works as expected * drag selection works as expected * drag selection when dragging accross screens, or Shift icmw with HOME / END / PageUp / PageDown works as expect * text selection stil works as expected The context menu items have been updated as well * filter will filter on all the distinct values in the selection * copying cells will copy all cells of the given column in the selection, separated by newline * copying rows / creating a past will create a json array of the selection Not done yet - Shifting the selection after inserting rows hasn't been implemented yet - I'm not entirely happy with the context menu trigger, maybe a hamburger button in the toolbar will be better Reviewed By: nikoant Differential Revision: D26548228 fbshipit-source-id: 5d1cddd6aad02ce9649d7980ab3a223e222da893
This commit is contained in:
committed by
Facebook GitHub Bot
parent
5c3a8742ef
commit
59a1327261
@@ -55,15 +55,15 @@ test('update and append', async () => {
|
||||
expect(elem.length).toBe(1);
|
||||
expect(elem[0].parentElement).toMatchInlineSnapshot(`
|
||||
<div
|
||||
class="css-1rnoidw-TableBodyRowContainer efe0za01"
|
||||
class="css-tihkal-TableBodyRowContainer efe0za01"
|
||||
>
|
||||
<div
|
||||
class="ant-table-cell css-1g4z4wd-TableBodyColumnContainer efe0za00"
|
||||
class="ant-table-cell css-1u65yt0-TableBodyColumnContainer efe0za00"
|
||||
>
|
||||
test DataTable
|
||||
</div>
|
||||
<div
|
||||
class="ant-table-cell css-1g4z4wd-TableBodyColumnContainer efe0za00"
|
||||
class="ant-table-cell css-1u65yt0-TableBodyColumnContainer efe0za00"
|
||||
>
|
||||
true
|
||||
</div>
|
||||
@@ -112,15 +112,15 @@ test('column visibility', async () => {
|
||||
expect(elem.length).toBe(1);
|
||||
expect(elem[0].parentElement).toMatchInlineSnapshot(`
|
||||
<div
|
||||
class="css-1rnoidw-TableBodyRowContainer efe0za01"
|
||||
class="css-tihkal-TableBodyRowContainer efe0za01"
|
||||
>
|
||||
<div
|
||||
class="ant-table-cell css-1g4z4wd-TableBodyColumnContainer efe0za00"
|
||||
class="ant-table-cell css-1u65yt0-TableBodyColumnContainer efe0za00"
|
||||
>
|
||||
test DataTable
|
||||
</div>
|
||||
<div
|
||||
class="ant-table-cell css-1g4z4wd-TableBodyColumnContainer efe0za00"
|
||||
class="ant-table-cell css-1u65yt0-TableBodyColumnContainer efe0za00"
|
||||
>
|
||||
true
|
||||
</div>
|
||||
@@ -137,10 +137,10 @@ test('column visibility', async () => {
|
||||
expect(elem.length).toBe(1);
|
||||
expect(elem[0].parentElement).toMatchInlineSnapshot(`
|
||||
<div
|
||||
class="css-1rnoidw-TableBodyRowContainer efe0za01"
|
||||
class="css-tihkal-TableBodyRowContainer efe0za01"
|
||||
>
|
||||
<div
|
||||
class="ant-table-cell css-1g4z4wd-TableBodyColumnContainer efe0za00"
|
||||
class="ant-table-cell css-1u65yt0-TableBodyColumnContainer efe0za00"
|
||||
>
|
||||
test DataTable
|
||||
</div>
|
||||
@@ -510,3 +510,114 @@ test('compute filters', () => {
|
||||
expect(data.filter(filter)).toEqual([]);
|
||||
}
|
||||
});
|
||||
|
||||
test('onSelect callback fires, and in order', () => {
|
||||
const events: any[] = [];
|
||||
const ds = createTestDataSource();
|
||||
const ref = createRef<TableManager>();
|
||||
const rendering = render(
|
||||
<DataTable
|
||||
dataSource={ds}
|
||||
columns={columns}
|
||||
tableManagerRef={ref}
|
||||
_testHeight={400}
|
||||
onSelect={(item, items) => {
|
||||
events.push([item, items]);
|
||||
}}
|
||||
/>,
|
||||
);
|
||||
|
||||
const item1 = {
|
||||
title: 'item 1',
|
||||
done: false,
|
||||
};
|
||||
const item2 = {
|
||||
title: 'item 2',
|
||||
done: false,
|
||||
};
|
||||
const item3 = {
|
||||
title: 'item 3',
|
||||
done: false,
|
||||
};
|
||||
act(() => {
|
||||
ds.clear();
|
||||
ds.append(item1);
|
||||
ds.append(item2);
|
||||
ds.append(item3);
|
||||
ref.current!.selectItem(2);
|
||||
});
|
||||
|
||||
expect(events.splice(0)).toEqual([
|
||||
[undefined, []],
|
||||
[item3, [item3]],
|
||||
]);
|
||||
|
||||
act(() => {
|
||||
ref.current!.addRangeToSelection(0, 0);
|
||||
});
|
||||
|
||||
expect(events.splice(0)).toEqual([
|
||||
[item1, [item1, item3]], // order preserved!
|
||||
]);
|
||||
|
||||
rendering.unmount();
|
||||
});
|
||||
|
||||
test('selection always has the latest state', () => {
|
||||
const events: any[] = [];
|
||||
const ds = createTestDataSource();
|
||||
const ref = createRef<TableManager>();
|
||||
const rendering = render(
|
||||
<DataTable
|
||||
dataSource={ds}
|
||||
columns={columns}
|
||||
tableManagerRef={ref}
|
||||
_testHeight={400}
|
||||
onSelect={(item, items) => {
|
||||
events.push([item, items]);
|
||||
}}
|
||||
/>,
|
||||
);
|
||||
|
||||
const item1 = {
|
||||
title: 'item 1',
|
||||
done: false,
|
||||
};
|
||||
const item2 = {
|
||||
title: 'item 2',
|
||||
done: false,
|
||||
};
|
||||
const item3 = {
|
||||
title: 'item 3',
|
||||
done: false,
|
||||
};
|
||||
act(() => {
|
||||
ds.clear();
|
||||
ds.append(item1);
|
||||
ds.append(item2);
|
||||
ds.append(item3);
|
||||
ref.current!.selectItem(2);
|
||||
});
|
||||
|
||||
expect(events.splice(0)).toEqual([
|
||||
[undefined, []],
|
||||
[item3, [item3]],
|
||||
]);
|
||||
|
||||
const item3updated = {
|
||||
title: 'item 3 updated',
|
||||
done: false,
|
||||
};
|
||||
act(() => {
|
||||
ds.update(2, item3updated);
|
||||
});
|
||||
act(() => {
|
||||
ref.current!.addRangeToSelection(0, 0);
|
||||
});
|
||||
|
||||
expect(events.splice(0)).toEqual([
|
||||
[item1, [item1, item3updated]], // update reflected in callback!
|
||||
]);
|
||||
|
||||
rendering.unmount();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user