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: Partitioned Table UI Enhancements #2110

Merged
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
4caeb92
feat: Partitioned Table UI Enhancements
AkshatJawne Jun 26, 2024
a2f8b9b
modify data extraction and test case
AkshatJawne Jun 26, 2024
831bae4
change name to baseTable and remove unnecessary border
AkshatJawne Jun 26, 2024
45bc6d8
make changes according to review
AkshatJawne Jun 27, 2024
81bdecc
fix formatting issues
AkshatJawne Jun 27, 2024
42dc49d
fix more formatting issues
AkshatJawne Jun 27, 2024
8cff366
small visual changes
AkshatJawne Jun 28, 2024
8ed8875
resolve merge conflicts
AkshatJawne Jul 2, 2024
a97cf27
fix formatting issues
AkshatJawne Jul 2, 2024
01a3225
make changes based on review
AkshatJawne Jul 4, 2024
16db737
temp workaround
AkshatJawne Jul 4, 2024
bc17e40
refactor logic to update partition options
AkshatJawne Jul 4, 2024
9bf8999
WIP fixing rendering issues
AkshatJawne Jul 5, 2024
99096c2
WIP state not working as intended
AkshatJawne Jul 5, 2024
804592b
fix empty table bug
AkshatJawne Jul 8, 2024
292e1ad
WIP still investigating cause of chromium failures
AkshatJawne Jul 9, 2024
dbf69a2
WIP fix formatting issue
AkshatJawne Jul 9, 2024
420bf9e
WIP small changes
AkshatJawne Jul 12, 2024
0762fbb
WIP fix formatter file not getting pushed
AkshatJawne Jul 12, 2024
82f72cb
WIP wanting to test change
AkshatJawne Jul 12, 2024
41bc31a
WIP test context menu change
AkshatJawne Jul 12, 2024
30226d6
WIP test chamhe
AkshatJawne Jul 12, 2024
1601d84
WIP revert old changes
AkshatJawne Jul 12, 2024
a092033
WIP Bender solution
AkshatJawne Jul 16, 2024
7c82824
fix issues with empty table
AkshatJawne Jul 17, 2024
d9fc4ca
remove null check
AkshatJawne Jul 17, 2024
e588409
remove early return
AkshatJawne Jul 17, 2024
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
144 changes: 86 additions & 58 deletions packages/iris-grid/src/IrisGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ import {
IrisGridContextMenuHandler,
IrisGridCopyCellMouseHandler,
IrisGridDataSelectMouseHandler,
IrisGridPartitionedTableMouseHandler,
IrisGridFilterMouseHandler,
IrisGridRowTreeMouseHandler,
IrisGridSortMouseHandler,
Expand Down Expand Up @@ -734,6 +735,7 @@ class IrisGrid extends Component<IrisGridProps, IrisGridState> {
new IrisGridContextMenuHandler(this, dh),
new IrisGridDataSelectMouseHandler(this),
new PendingMouseHandler(this),
new IrisGridPartitionedTableMouseHandler(this),
];
if (canCopy) {
keyHandlers.push(new CopyKeyHandler(this));
Expand Down Expand Up @@ -1781,12 +1783,17 @@ class IrisGrid extends Component<IrisGridProps, IrisGridState> {
* Rebuilds all the current filters. Necessary if something like the time zone has changed.
*/
rebuildFilters(): void {
log.debug('Rebuilding filters');

const { model } = this.props;
const { advancedFilters, quickFilters } = this.state;
const { columns, formatter } = model;

if (advancedFilters.size === 0 && quickFilters.size === 0) {
// No need to rebuild filters if no filters are set
return;
}

log.debug('Rebuilding filters');

const newAdvancedFilters = new Map();
const newQuickFilters = new Map();

Expand All @@ -1812,8 +1819,8 @@ class IrisGrid extends Component<IrisGridProps, IrisGridState> {
filter: this.makeQuickFilter(column, text, formatter.timeZone),
});
});

this.startLoading('Rebuilding filters...', { resetRanges: true });

this.setState({
quickFilters: newQuickFilters,
advancedFilters: newAdvancedFilters,
Expand Down Expand Up @@ -2024,11 +2031,15 @@ class IrisGrid extends Component<IrisGridProps, IrisGridState> {

async loadPartitionsTable(model: PartitionedGridModel): Promise<void> {
try {
const partitionConfig = await this.getInitialPartitionConfig(model);
this.setState(
{ isSelectingPartition: true, partitionConfig },
this.loadTableState
);
const { partitionConfig } = this.state;
if (!partitionConfig) {
this.startLoading('Loading partitions...', {
loadingCancelShown: false,
resetRanges: true,
});
this.initializePartitionConfig(model);
}
this.setState({ isSelectingPartition: true }, this.loadTableState);
} catch (error) {
if (!PromiseUtils.isCanceled(error)) {
this.handleTableLoadError(error);
Expand All @@ -2037,19 +2048,9 @@ class IrisGrid extends Component<IrisGridProps, IrisGridState> {
}

/**
* Gets the initial partition config for the currently set model.
* Sorts the key table and gets the first key.
* If the table is ticking, it will wait for the first tick.
* Initialize the partition config to the default partition.
*/
async getInitialPartitionConfig(
model: PartitionedGridModel
): Promise<PartitionConfig> {
const { partitionConfig } = this.state;
if (partitionConfig !== undefined) {
// User already has a partition selected, just use that
return partitionConfig;
}

async initializePartitionConfig(model: PartitionedGridModel): Promise<void> {
const keyTable = await this.pending.add(
model.partitionKeysTable(),
resolved => resolved.close()
Expand All @@ -2060,37 +2061,63 @@ class IrisGrid extends Component<IrisGridProps, IrisGridState> {
keyTable.applySort(sorts);
keyTable.setViewport(0, 0);

return new Promise((resolve, reject) => {
// We want to wait for the first UPDATED event instead of just getting viewport data here
// It's possible that the key table does not have any rows of data yet, so just wait until it does have one
keyTable.addEventListener(
dh.Table.EVENT_UPDATED,
(event: CustomEvent<DhType.ViewportData>) => {
try {
const { detail: data } = event;
if (data.rows.length === 0) {
// Table is empty, wait for the next updated event
return;
}
const row = data.rows[0];
// Core JSAPI returns undefined for null table values, IrisGridPartitionSelector expects null
// https://github.com/deephaven/deephaven-core/issues/5400
const values = keyTable.columns.map(
column => row.get(column) ?? null
);
const newPartition: PartitionConfig = {
partitions: values,
mode: 'partition',
};
keyTable.close();
resolve(newPartition);
} catch (e) {
keyTable.close();
reject(e);
// We want to wait for the first UPDATED event instead of just getting viewport data here
// It's possible that the key table does not have any rows of data yet, so just wait until it does have one
keyTable.addEventListener(
dh.Table.EVENT_UPDATED,
(event: CustomEvent<DhType.ViewportData>) => {
try {
const { detail: data } = event;
if (data.rows.length === 0) {
// We received an update and the table is still empty. Stop showing the loading spinner so we know
this.stopLoading();
return;
}
const row = data.rows[0];
const values = keyTable.columns.map(column => row.get(column));
const newPartition: PartitionConfig = {
partitions: values,
mode: model.isPartitionAwareSourceTable ? 'partition' : 'keys',
};
keyTable.close();
this.setState({
loadingSpinnerShown: false,
partitionConfig: newPartition,
});
} catch (e) {
keyTable.close();
log.error('Error getting initial partition config', e);
}
}
);
}

/**
* Selects a partition key from the table based on the provided row index.
*
* @param rowIndex The index of the row from which the partition will be selected.
* @returns A promise that resolves when the partition key has been successfully selected.
*/
selectPartitionKeyFromTable(rowIndex: GridRangeIndex): void {
const { model } = this.props;
assertNotNull(rowIndex);
if (isPartitionedGridModel(model)) {
const data = this.getRowDataMap(rowIndex);
const partitionColumnSet = new Set(
model.partitionColumns.map(column => column.name)
);
});
const values = Object.entries(data)
.filter(([key, _]) => partitionColumnSet.has(key))
.map(([key, columnData]) => columnData.value);
const newPartition: PartitionConfig = {
partitions: values,
mode: 'partition',
};
this.setState({
isSelectingPartition: true,
partitionConfig: newPartition,
});
}
}

copyCell(
Expand Down Expand Up @@ -2532,7 +2559,10 @@ class IrisGrid extends Component<IrisGridProps, IrisGridState> {

handlePartitionChange(partitionConfig: PartitionConfig): void {
this.startLoading('Partitioning...');
this.setState({ partitionConfig });
const { partitionConfig: prevConfig } = this.state;
if (prevConfig !== partitionConfig) {
this.setState({ partitionConfig });
}
}

handleTableLoadError(error: unknown): void {
Expand Down Expand Up @@ -4700,15 +4730,13 @@ class IrisGrid extends Component<IrisGridProps, IrisGridState> {
unmountOnExit
>
<div className="iris-grid-partition-selector-wrapper iris-grid-bar iris-grid-bar-primary">
{isPartitionedGridModel(model) &&
model.isPartitionRequired &&
partitionConfig && (
<IrisGridPartitionSelector
model={model}
partitionConfig={partitionConfig}
onChange={this.handlePartitionChange}
/>
)}
{isPartitionedGridModel(model) && model.isPartitionRequired && (
<IrisGridPartitionSelector
model={model}
partitionConfig={partitionConfig}
onChange={this.handlePartitionChange}
/>
)}
</div>
</CSSTransition>
<CSSTransition
Expand Down
3 changes: 1 addition & 2 deletions packages/iris-grid/src/IrisGridPartitionSelector.scss
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@
}
.partition-button-group {
display: flex;
border: 1px var(--dh-color-hr);
border-style: none solid;
border-right: 1px solid var(--dh-color-hr);
padding: 0 $spacer-2;
gap: $spacer-2;
}
Expand Down
3 changes: 3 additions & 0 deletions packages/iris-grid/src/IrisGridPartitionSelector.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ function makeModel(
Promise.resolve(irisGridTestUtils.makeTable())
),
partitionColumns: columns,
partitionBaseTable: jest.fn(() =>
Promise.resolve(irisGridTestUtils.makeTable())
),
} as unknown as PartitionedGridModel;
return model;
}
Expand Down
Loading
Loading