mirror of
https://github.com/gristlabs/grist-core.git
synced 2024-10-27 20:44:07 +00:00
(core) recursiveMoveToCursorPos with new kinds of linking involving lists
Summary: Constructs a ClientQuery in a similar way to LinkingState to handle lists. Test Plan: Extended SelectBySummary and SelectByRefList tests. Reviewers: dsagal Reviewed By: dsagal Subscribers: paulfitz Differential Revision: https://phab.getgrist.com/D3030
This commit is contained in:
parent
c4fb40e0bd
commit
1a8abdcd96
@ -5,11 +5,15 @@
|
|||||||
|
|
||||||
import {AccessRules} from 'app/client/aclui/AccessRules';
|
import {AccessRules} from 'app/client/aclui/AccessRules';
|
||||||
import {ActionLog} from 'app/client/components/ActionLog';
|
import {ActionLog} from 'app/client/components/ActionLog';
|
||||||
|
import * as BaseView from 'app/client/components/BaseView';
|
||||||
import * as CodeEditorPanel from 'app/client/components/CodeEditorPanel';
|
import * as CodeEditorPanel from 'app/client/components/CodeEditorPanel';
|
||||||
import * as commands from 'app/client/components/commands';
|
import * as commands from 'app/client/components/commands';
|
||||||
import {CursorPos} from 'app/client/components/Cursor';
|
import {CursorPos} from 'app/client/components/Cursor';
|
||||||
|
import {CursorMonitor, ViewCursorPos} from "app/client/components/CursorMonitor";
|
||||||
import {DocComm, DocUserAction} from 'app/client/components/DocComm';
|
import {DocComm, DocUserAction} from 'app/client/components/DocComm';
|
||||||
import * as DocConfigTab from 'app/client/components/DocConfigTab';
|
import * as DocConfigTab from 'app/client/components/DocConfigTab';
|
||||||
|
import {Drafts} from "app/client/components/Drafts";
|
||||||
|
import {EditorMonitor} from "app/client/components/EditorMonitor";
|
||||||
import * as GridView from 'app/client/components/GridView';
|
import * as GridView from 'app/client/components/GridView';
|
||||||
import {Importer} from 'app/client/components/Importer';
|
import {Importer} from 'app/client/components/Importer';
|
||||||
import {ActionGroupWithCursorPos, UndoStack} from 'app/client/components/UndoStack';
|
import {ActionGroupWithCursorPos, UndoStack} from 'app/client/components/UndoStack';
|
||||||
@ -28,39 +32,35 @@ import {DocInfoRec, DocModel, ViewRec, ViewSectionRec} from 'app/client/models/D
|
|||||||
import {DocPageModel} from 'app/client/models/DocPageModel';
|
import {DocPageModel} from 'app/client/models/DocPageModel';
|
||||||
import {UserError} from 'app/client/models/errors';
|
import {UserError} from 'app/client/models/errors';
|
||||||
import {urlState} from 'app/client/models/gristUrlState';
|
import {urlState} from 'app/client/models/gristUrlState';
|
||||||
import {QuerySetManager} from 'app/client/models/QuerySet';
|
import {getFilterFunc, QuerySetManager} from 'app/client/models/QuerySet';
|
||||||
import {getUserOrgPrefObs} from "app/client/models/UserPrefs";
|
import {getUserOrgPrefObs} from "app/client/models/UserPrefs";
|
||||||
import {App} from 'app/client/ui/App';
|
import {App} from 'app/client/ui/App';
|
||||||
import {DocHistory} from 'app/client/ui/DocHistory';
|
import {DocHistory} from 'app/client/ui/DocHistory';
|
||||||
|
import {startDocTour} from "app/client/ui/DocTour";
|
||||||
import {showDocSettingsModal} from 'app/client/ui/DocumentSettings';
|
import {showDocSettingsModal} from 'app/client/ui/DocumentSettings';
|
||||||
import {IPageWidget, toPageWidget} from 'app/client/ui/PageWidgetPicker';
|
import {IPageWidget, toPageWidget} from 'app/client/ui/PageWidgetPicker';
|
||||||
import {IPageWidgetLink, linkFromId, selectBy} from 'app/client/ui/selectBy';
|
import {IPageWidgetLink, linkFromId, selectBy} from 'app/client/ui/selectBy';
|
||||||
import {startWelcomeTour} from 'app/client/ui/welcomeTour';
|
import {startWelcomeTour} from 'app/client/ui/welcomeTour';
|
||||||
import {startDocTour} from "app/client/ui/DocTour";
|
|
||||||
import {isNarrowScreen, mediaSmall, testId} from 'app/client/ui2018/cssVars';
|
import {isNarrowScreen, mediaSmall, testId} from 'app/client/ui2018/cssVars';
|
||||||
import {IconName} from 'app/client/ui2018/IconList';
|
import {IconName} from 'app/client/ui2018/IconList';
|
||||||
|
import {FieldEditor} from "app/client/widgets/FieldEditor";
|
||||||
import {ActionGroup} from 'app/common/ActionGroup';
|
import {ActionGroup} from 'app/common/ActionGroup';
|
||||||
|
import {ClientQuery} from "app/common/ActiveDocAPI";
|
||||||
import {delay} from 'app/common/delay';
|
import {delay} from 'app/common/delay';
|
||||||
import {DisposableWithEvents} from 'app/common/DisposableWithEvents';
|
import {DisposableWithEvents} from 'app/common/DisposableWithEvents';
|
||||||
import {isSchemaAction} from 'app/common/DocActions';
|
import {isSchemaAction} from 'app/common/DocActions';
|
||||||
import {OpenLocalDocResult} from 'app/common/DocListAPI';
|
import {OpenLocalDocResult} from 'app/common/DocListAPI';
|
||||||
|
import {isList, isRefListType, RecalcWhen} from 'app/common/gristTypes';
|
||||||
import {HashLink, IDocPage} from 'app/common/gristUrls';
|
import {HashLink, IDocPage} from 'app/common/gristUrls';
|
||||||
import {RecalcWhen} from 'app/common/gristTypes';
|
|
||||||
import {undef, waitObs} from 'app/common/gutil';
|
import {undef, waitObs} from 'app/common/gutil';
|
||||||
import {LocalPlugin} from "app/common/plugin";
|
import {LocalPlugin} from "app/common/plugin";
|
||||||
import {StringUnion} from 'app/common/StringUnion';
|
import {StringUnion} from 'app/common/StringUnion';
|
||||||
import {TableData} from 'app/common/TableData';
|
import {TableData} from 'app/common/TableData';
|
||||||
import {DocStateComparison} from 'app/common/UserAPI';
|
import {DocStateComparison} from 'app/common/UserAPI';
|
||||||
import {Computed, dom, Emitter, Holder, IDomComponent, subscribe, toKo} from 'grainjs';
|
import {Computed, dom, Emitter, Holder, IDisposable, IDomComponent, Observable, styled, subscribe, toKo} from 'grainjs';
|
||||||
import {IDisposable, Observable, styled} from 'grainjs';
|
|
||||||
import * as ko from 'knockout';
|
import * as ko from 'knockout';
|
||||||
import cloneDeepWith = require('lodash/cloneDeepWith');
|
import cloneDeepWith = require('lodash/cloneDeepWith');
|
||||||
import isEqual = require('lodash/isEqual');
|
import isEqual = require('lodash/isEqual');
|
||||||
import * as BaseView from 'app/client/components/BaseView';
|
|
||||||
import { CursorMonitor, ViewCursorPos } from "app/client/components/CursorMonitor";
|
|
||||||
import { EditorMonitor } from "app/client/components/EditorMonitor";
|
|
||||||
import { FieldEditor } from "app/client/widgets/FieldEditor";
|
|
||||||
import { Drafts } from "app/client/components/Drafts";
|
|
||||||
|
|
||||||
const G = getBrowserGlobals('document', 'window');
|
const G = getBrowserGlobals('document', 'window');
|
||||||
|
|
||||||
@ -678,25 +678,28 @@ export class GristDoc extends DisposableWithEvents {
|
|||||||
const isSrcSummary = srcSection.table.peek().summarySource.peek().id.peek();
|
const isSrcSummary = srcSection.table.peek().summarySource.peek().id.peek();
|
||||||
if (!colId && !isSrcSummary) {
|
if (!colId && !isSrcSummary) {
|
||||||
// Simple case - source linked by rowId, not a summary.
|
// Simple case - source linked by rowId, not a summary.
|
||||||
|
if (isList(controller)) {
|
||||||
|
// Should be a reference list. Pick the first reference.
|
||||||
|
controller = controller[1]; // [0] is the L type code, [1] is the first value
|
||||||
|
}
|
||||||
srcRowId = controller;
|
srcRowId = controller;
|
||||||
} else {
|
} else {
|
||||||
const srcTable = await this._getTableData(srcSection);
|
const srcTable = await this._getTableData(srcSection);
|
||||||
if (!colId) {
|
const query: ClientQuery = {tableId: srcTable.tableId, filters: {}, operations: {}};
|
||||||
|
if (colId) {
|
||||||
|
query.operations![colId] = isRefListType(section.linkSrcCol.peek().type.peek()) ? 'intersects' : 'in';
|
||||||
|
query.filters[colId] = isList(controller) ? controller.slice(1) : [controller];
|
||||||
|
} else {
|
||||||
// must be a summary -- otherwise dealt with earlier.
|
// must be a summary -- otherwise dealt with earlier.
|
||||||
const destTable = await this._getTableData(section);
|
const destTable = await this._getTableData(section);
|
||||||
const filter: { [key: string]: any } = {};
|
for (const srcCol of srcSection.table.peek().groupByColumns.peek()) {
|
||||||
for (const c of srcSection.table.peek().columns.peek().peek()) {
|
const filterColId = srcCol.summarySource.peek().colId.peek();
|
||||||
if (c.summarySourceCol.peek()) {
|
controller = destTable.getValue(cursorPos.rowId, filterColId);
|
||||||
const filterColId = c.summarySource.peek().colId.peek();
|
query.operations![filterColId] = 'in';
|
||||||
const destValue = destTable.getValue(cursorPos.rowId, filterColId);
|
query.filters[filterColId] = isList(controller) ? controller.slice(1) : [controller];
|
||||||
filter[filterColId] = destValue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
const result = srcTable.filterRecords(filter); // Should just have one record, or 0.
|
|
||||||
srcRowId = result[0] && result[0].id;
|
|
||||||
} else {
|
|
||||||
srcRowId = srcTable.findRow(colId, controller);
|
|
||||||
}
|
}
|
||||||
|
srcRowId = srcTable.getRowIds().find(getFilterFunc(this.docData, query));
|
||||||
}
|
}
|
||||||
if (!srcRowId || typeof srcRowId !== 'number') { throw new Error('cannot trace rowId'); }
|
if (!srcRowId || typeof srcRowId !== 'number') { throw new Error('cannot trace rowId'); }
|
||||||
await this.recursiveMoveToCursorPos({
|
await this.recursiveMoveToCursorPos({
|
||||||
|
@ -88,7 +88,7 @@ interface BaseQuery {
|
|||||||
export interface ClientQuery extends BaseQuery {
|
export interface ClientQuery extends BaseQuery {
|
||||||
operations?: {
|
operations?: {
|
||||||
[colId: string]: QueryOperation;
|
[colId: string]: QueryOperation;
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user