mirror of
https://github.com/gristlabs/grist-core.git
synced 2024-10-27 20:44:07 +00:00
(core) Refactor more value parsing code into common
Summary: Following discussion in https://phab.getgrist.com/D3164: - Change createParser to accept docData and one or two metadata row IDs and let it extract the metadata, so it's more easily usable in the server. - Change ViewFieldRec.valueParser observable to a function createValueParser. Test Plan: Existing tests. Reviewers: dsagal Reviewed By: dsagal Differential Revision: https://phab.getgrist.com/D3172
This commit is contained in:
parent
4164d89b84
commit
6b448567c9
@ -372,7 +372,7 @@ BaseView.prototype._parsePasteForView = function(data, fields) {
|
|||||||
});
|
});
|
||||||
const updateColIds = updateCols.map(c => c && c.colId());
|
const updateColIds = updateCols.map(c => c && c.colId());
|
||||||
const updateColTypes = updateCols.map(c => c && c.type());
|
const updateColTypes = updateCols.map(c => c && c.type());
|
||||||
const parsers = fields.map(field => field && field.valueParser() || (x => x));
|
const parsers = fields.map(field => field && field.createValueParser() || (x => x));
|
||||||
const docIdHash = tableUtil.getDocIdHash();
|
const docIdHash = tableUtil.getDocIdHash();
|
||||||
|
|
||||||
const richData = data.map((col, idx) => {
|
const richData = data.map((col, idx) => {
|
||||||
|
@ -17,9 +17,6 @@ export class ReferenceUtils {
|
|||||||
public readonly isRefList: boolean;
|
public readonly isRefList: boolean;
|
||||||
|
|
||||||
constructor(public readonly field: ViewFieldRec, docData: DocData) {
|
constructor(public readonly field: ViewFieldRec, docData: DocData) {
|
||||||
// Note that this constructor is called inside ViewFieldRec.valueParser, a ko.pureComputed,
|
|
||||||
// and there are several observables here which get used and become dependencies.
|
|
||||||
|
|
||||||
const colType = field.column().type();
|
const colType = field.column().type();
|
||||||
const refTableId = getReferencedTableId(colType);
|
const refTableId = getReferencedTableId(colType);
|
||||||
if (!refTableId) {
|
if (!refTableId) {
|
||||||
|
@ -2,7 +2,6 @@ import {ColumnRec, DocModel, IRowModel, refRecord, ViewSectionRec} from 'app/cli
|
|||||||
import * as modelUtil from 'app/client/models/modelUtil';
|
import * as modelUtil from 'app/client/models/modelUtil';
|
||||||
import * as UserType from 'app/client/widgets/UserType';
|
import * as UserType from 'app/client/widgets/UserType';
|
||||||
import {DocumentSettings} from 'app/common/DocumentSettings';
|
import {DocumentSettings} from 'app/common/DocumentSettings';
|
||||||
import {getReferencedTableId, isFullReferencingType} from 'app/common/gristTypes';
|
|
||||||
import {BaseFormatter, createFormatter} from 'app/common/ValueFormatter';
|
import {BaseFormatter, createFormatter} from 'app/common/ValueFormatter';
|
||||||
import {createParser} from 'app/common/ValueParser';
|
import {createParser} from 'app/common/ValueParser';
|
||||||
import * as ko from 'knockout';
|
import * as ko from 'knockout';
|
||||||
@ -70,7 +69,7 @@ export interface ViewFieldRec extends IRowModel<"_grist_Views_section_field"> {
|
|||||||
|
|
||||||
documentSettings: ko.PureComputed<DocumentSettings>;
|
documentSettings: ko.PureComputed<DocumentSettings>;
|
||||||
|
|
||||||
valueParser: ko.Computed<(value: string) => any>;
|
createValueParser(): (value: string) => any;
|
||||||
|
|
||||||
// Helper which adds/removes/updates field's displayCol to match the formula.
|
// Helper which adds/removes/updates field's displayCol to match the formula.
|
||||||
saveDisplayFormula(formula: string): Promise<void>|undefined;
|
saveDisplayFormula(formula: string): Promise<void>|undefined;
|
||||||
@ -174,20 +173,10 @@ export function createViewFieldRec(this: ViewFieldRec, docModel: DocModel): void
|
|||||||
createFormatter(this.column().type(), this.widgetOptionsJson(), this.documentSettings());
|
createFormatter(this.column().type(), this.widgetOptionsJson(), this.documentSettings());
|
||||||
};
|
};
|
||||||
|
|
||||||
this.valueParser = ko.pureComputed(() => {
|
this.createValueParser = function() {
|
||||||
const docSettings = this.documentSettings();
|
const fieldRef = this.useColOptions.peek() ? undefined : this.id.peek();
|
||||||
const type = this.column().type();
|
return createParser(docModel.docData, this.colRef.peek(), fieldRef);
|
||||||
|
};
|
||||||
const widgetOpts = this.widgetOptionsJson();
|
|
||||||
if (isFullReferencingType(type)) {
|
|
||||||
const vcol = this.visibleColModel();
|
|
||||||
widgetOpts.visibleColId = vcol.colId() || 'id';
|
|
||||||
widgetOpts.visibleColType = vcol.type();
|
|
||||||
widgetOpts.visibleColWidgetOpts = vcol.widgetOptionsJson();
|
|
||||||
widgetOpts.tableData = docModel.docData.getTable(getReferencedTableId(type)!);
|
|
||||||
}
|
|
||||||
return createParser(type, widgetOpts, docSettings);
|
|
||||||
});
|
|
||||||
|
|
||||||
// The widgetOptions to read and write: either the column's or the field's own.
|
// The widgetOptions to read and write: either the column's or the field's own.
|
||||||
this._widgetOptionsStr = modelUtil.savingComputed({
|
this._widgetOptionsStr = modelUtil.savingComputed({
|
||||||
|
@ -76,7 +76,7 @@ export class NTextEditor extends NewBaseEditor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public getCellValue(): CellValue {
|
public getCellValue(): CellValue {
|
||||||
const valueParser = this.options.field.valueParser.peek();
|
const valueParser = this.options.field.createValueParser();
|
||||||
return valueParser(this.getTextValue());
|
return valueParser(this.getTextValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
import {csvDecodeRow} from 'app/common/csvFormat';
|
import {csvDecodeRow} from 'app/common/csvFormat';
|
||||||
|
import {DocData} from 'app/common/DocData';
|
||||||
import {DocumentSettings} from 'app/common/DocumentSettings';
|
import {DocumentSettings} from 'app/common/DocumentSettings';
|
||||||
|
import {getReferencedTableId, isFullReferencingType} from 'app/common/gristTypes';
|
||||||
import * as gristTypes from 'app/common/gristTypes';
|
import * as gristTypes from 'app/common/gristTypes';
|
||||||
import * as gutil from 'app/common/gutil';
|
import * as gutil from 'app/common/gutil';
|
||||||
import {safeJsonParse} from 'app/common/gutil';
|
import {safeJsonParse} from 'app/common/gutil';
|
||||||
import {getCurrency, NumberFormatOptions} from 'app/common/NumberFormat';
|
import {getCurrency, NumberFormatOptions} from 'app/common/NumberFormat';
|
||||||
import NumberParse from 'app/common/NumberParse';
|
import NumberParse from 'app/common/NumberParse';
|
||||||
import {parseDateStrict, parseDateTime} from 'app/common/parseDate';
|
import {parseDateStrict, parseDateTime} from 'app/common/parseDate';
|
||||||
import {TableData} from 'app/common/TableData';
|
import {MetaRowRecord, TableData} from 'app/common/TableData';
|
||||||
import {DateFormatOptions, DateTimeFormatOptions, formatDecoded, FormatOptions} from 'app/common/ValueFormatter';
|
import {DateFormatOptions, DateTimeFormatOptions, formatDecoded, FormatOptions} from 'app/common/ValueFormatter';
|
||||||
import flatMap = require('lodash/flatMap');
|
import flatMap = require('lodash/flatMap');
|
||||||
|
|
||||||
@ -99,7 +101,7 @@ class ChoiceListParser extends ValueParser {
|
|||||||
/**
|
/**
|
||||||
* This is different from other widget options which are simple JSON
|
* This is different from other widget options which are simple JSON
|
||||||
* stored on the field. These have to be specially derived
|
* stored on the field. These have to be specially derived
|
||||||
* for referencing columns. See ViewFieldRec.valueParser for an example.
|
* for referencing columns. See createParser.
|
||||||
*/
|
*/
|
||||||
interface ReferenceParsingOptions {
|
interface ReferenceParsingOptions {
|
||||||
visibleColId: string;
|
visibleColId: string;
|
||||||
@ -116,7 +118,7 @@ export class ReferenceParser extends ValueParser {
|
|||||||
|
|
||||||
protected _visibleColId = this.widgetOpts.visibleColId;
|
protected _visibleColId = this.widgetOpts.visibleColId;
|
||||||
protected _tableData = this.widgetOpts.tableData;
|
protected _tableData = this.widgetOpts.tableData;
|
||||||
protected _visibleColParser = createParser(
|
protected _visibleColParser = createParserRaw(
|
||||||
this.widgetOpts.visibleColType,
|
this.widgetOpts.visibleColType,
|
||||||
this.widgetOpts.visibleColWidgetOpts,
|
this.widgetOpts.visibleColWidgetOpts,
|
||||||
this.docSettings,
|
this.docSettings,
|
||||||
@ -218,7 +220,7 @@ export const valueParserClasses: { [type: string]: typeof ValueParser } = {
|
|||||||
* widgetOpts is usually the field/column's widgetOptions JSON
|
* widgetOpts is usually the field/column's widgetOptions JSON
|
||||||
* but referencing columns need more than that, see ReferenceParsingOptions above.
|
* but referencing columns need more than that, see ReferenceParsingOptions above.
|
||||||
*/
|
*/
|
||||||
export function createParser(
|
export function createParserRaw(
|
||||||
type: string, widgetOpts: FormatOptions, docSettings: DocumentSettings
|
type: string, widgetOpts: FormatOptions, docSettings: DocumentSettings
|
||||||
): (value: string) => any {
|
): (value: string) => any {
|
||||||
const cls = valueParserClasses[gristTypes.extractTypeFromColType(type)];
|
const cls = valueParserClasses[gristTypes.extractTypeFromColType(type)];
|
||||||
@ -228,3 +230,43 @@ export function createParser(
|
|||||||
}
|
}
|
||||||
return value => value;
|
return value => value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a function which can parse strings into values appropriate for
|
||||||
|
* a specific widget field or table column.
|
||||||
|
*
|
||||||
|
* Pass fieldRef (a row ID of _grist_Views_section_field) to use the settings of that view field
|
||||||
|
* instead of the table column.
|
||||||
|
*/
|
||||||
|
export function createParser(
|
||||||
|
docData: DocData,
|
||||||
|
colRef: number,
|
||||||
|
fieldRef?: number,
|
||||||
|
): (value: string) => any {
|
||||||
|
const columnsTable = docData.getMetaTable('_grist_Tables_column');
|
||||||
|
const fieldsTable = docData.getMetaTable('_grist_Views_section_field');
|
||||||
|
const docInfoTable = docData.getMetaTable('_grist_DocInfo');
|
||||||
|
|
||||||
|
const col = columnsTable.getRecord(colRef)!;
|
||||||
|
|
||||||
|
let fieldOrCol: MetaRowRecord<'_grist_Tables_column' | '_grist_Views_section_field'> = col;
|
||||||
|
if (fieldRef) {
|
||||||
|
fieldOrCol = fieldsTable.getRecord(fieldRef) || col;
|
||||||
|
}
|
||||||
|
|
||||||
|
const widgetOpts = safeJsonParse(fieldOrCol.widgetOptions, {});
|
||||||
|
|
||||||
|
const type = col.type;
|
||||||
|
if (isFullReferencingType(type)) {
|
||||||
|
const vcol = columnsTable.getRecord(fieldOrCol.visibleCol);
|
||||||
|
widgetOpts.visibleColId = vcol?.colId || 'id';
|
||||||
|
widgetOpts.visibleColType = vcol?.type;
|
||||||
|
widgetOpts.visibleColWidgetOpts = safeJsonParse(vcol?.widgetOptions || '', {});
|
||||||
|
widgetOpts.tableData = docData.getTable(getReferencedTableId(type)!);
|
||||||
|
}
|
||||||
|
|
||||||
|
const docInfo = docInfoTable.getRecord(1);
|
||||||
|
const docSettings = safeJsonParse(docInfo!.documentSettings, {}) as DocumentSettings;
|
||||||
|
|
||||||
|
return createParserRaw(type, widgetOpts, docSettings);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user