(core) Fix 'select by' when adding summary table widget to page

Summary:
When adding a summary table widget to a page and using 'select by' in the add widget config (as opposed to in the right panel for an existing widget):

1. If an equivalent summary table already exists, use its referencing columns (if any) to construct link nodes. Previously the source table columns were being used instead, which could include referencing columns that don't have any equivalent in the summary table, and exclude referencing columns in the summary table.
2. If no such summary table exists yet, then keep using the source table columns, but only the selected groupby columns, and
3. After the summary table is created, correct the `linkTargetColRef` (which points to a source table column) to the corresponding column from the new summary table instead.

This fixes bugs which only appeared recently since 'select by' for a summary table previously involved no target columns.

Test Plan: Added two new tests to `nbrowser/SelectBySummaryRef`, and confirmed that they fail without the fixes to all three points above.

Reviewers: dsagal

Reviewed By: dsagal

Subscribers: dsagal

Differential Revision: https://phab.getgrist.com/D3527
This commit is contained in:
Alex Hall
2022-07-18 13:39:58 +02:00
parent f39b496563
commit 4b258ae0fa
4 changed files with 69 additions and 25 deletions

View File

@@ -25,7 +25,7 @@ import {reportError} from 'app/client/models/AppModel';
import {ColumnRec, ViewSectionRec} from 'app/client/models/DocModel';
import {GridOptions} from 'app/client/ui/GridOptions';
import {attachPageWidgetPicker, IPageWidget, toPageWidget} from 'app/client/ui/PageWidgetPicker';
import {linkFromId, linkId, selectBy} from 'app/client/ui/selectBy';
import {linkId, selectBy} from 'app/client/ui/selectBy';
import {CustomSectionConfig} from 'app/client/ui/CustomSectionConfig';
import {VisibleFieldsConfig} from 'app/client/ui/VisibleFieldsConfig';
import {IWidgetType, widgetTypes} from 'app/client/ui/widgetTypes';
@@ -409,7 +409,7 @@ export class RightPanel extends Disposable {
)
);
link.onWrite((val) => this._gristDoc.saveLink(linkFromId(val)));
link.onWrite((val) => this._gristDoc.saveLink(val));
return [
this._disableIfReadonly(),
cssLabel('DATA TABLE'),

View File

@@ -4,6 +4,7 @@ import { getReferencedTableId } from 'app/common/gristTypes';
import { IOptionFull } from 'grainjs';
import assert from 'assert';
import * as gutil from "app/common/gutil";
import isEqual = require('lodash/isEqual');
// some unicode characters
const BLACK_CIRCLE = '\u2022';
@@ -243,24 +244,44 @@ function fromPageWidget(docModel: DocModel, pageWidget: IPageWidget): LinkNode[]
if (typeof pageWidget.table !== 'number') { return []; }
const table = docModel.tables.getRowModel(pageWidget.table);
let table = docModel.tables.getRowModel(pageWidget.table);
const isSummary = pageWidget.summarize;
const groupbyColumns = isSummary ? new Set(pageWidget.columns) : undefined;
let tableExists = true;
if (isSummary) {
const summaryTable = docModel.tables.rowModels.find(
t => t?.summarySourceTable.peek() && isEqual(t.summarySourceColRefs.peek(), groupbyColumns));
if (summaryTable) {
// The selected source table and groupby columns correspond to this existing summary table.
table = summaryTable;
} else {
// This summary table doesn't exist yet. `fromColumns` will be using columns from the source table.
// Make sure it only uses columns that are in the selected groupby columns.
// The resulting targetColRef will incorrectly be from the source table,
// but will be corrected in GristDoc.saveLink after the summary table is created.
tableExists = false;
}
}
const mainNode: LinkNode = {
tableId: table.primaryTableId.peek(),
isSummary,
groupbyColumns: isSummary ? new Set(pageWidget.columns) : undefined,
groupbyColumns,
widgetType: pageWidget.type,
ancestors: new Set(),
section: docModel.viewSections.getRowModel(pageWidget.section),
};
return fromColumns(table, mainNode);
return fromColumns(table, mainNode, tableExists);
}
function fromColumns(table: TableRec, mainNode: LinkNode): LinkNode[] {
function fromColumns(table: TableRec, mainNode: LinkNode, tableExists: boolean = true): LinkNode[] {
const nodes = [mainNode];
const columns = table.columns.peek().peek();
for (const column of columns) {
if (!tableExists && !mainNode.groupbyColumns!.has(column.getRowId())) {
continue;
}
const tableId = getReferencedTableId(column.type.peek());
if (tableId) {
nodes.push({...mainNode, tableId, column});