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 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 richData = data.map((col, idx) => {
|
||||
|
@ -17,9 +17,6 @@ export class ReferenceUtils {
|
||||
public readonly isRefList: boolean;
|
||||
|
||||
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 refTableId = getReferencedTableId(colType);
|
||||
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 UserType from 'app/client/widgets/UserType';
|
||||
import {DocumentSettings} from 'app/common/DocumentSettings';
|
||||
import {getReferencedTableId, isFullReferencingType} from 'app/common/gristTypes';
|
||||
import {BaseFormatter, createFormatter} from 'app/common/ValueFormatter';
|
||||
import {createParser} from 'app/common/ValueParser';
|
||||
import * as ko from 'knockout';
|
||||
@ -70,7 +69,7 @@ export interface ViewFieldRec extends IRowModel<"_grist_Views_section_field"> {
|
||||
|
||||
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.
|
||||
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());
|
||||
};
|
||||
|
||||
this.valueParser = ko.pureComputed(() => {
|
||||
const docSettings = this.documentSettings();
|
||||
const type = this.column().type();
|
||||
|
||||
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);
|
||||
});
|
||||
this.createValueParser = function() {
|
||||
const fieldRef = this.useColOptions.peek() ? undefined : this.id.peek();
|
||||
return createParser(docModel.docData, this.colRef.peek(), fieldRef);
|
||||
};
|
||||
|
||||
// The widgetOptions to read and write: either the column's or the field's own.
|
||||
this._widgetOptionsStr = modelUtil.savingComputed({
|
||||
|
@ -76,7 +76,7 @@ export class NTextEditor extends NewBaseEditor {
|
||||
}
|
||||
|
||||
public getCellValue(): CellValue {
|
||||
const valueParser = this.options.field.valueParser.peek();
|
||||
const valueParser = this.options.field.createValueParser();
|
||||
return valueParser(this.getTextValue());
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,14 @@
|
||||
import {csvDecodeRow} from 'app/common/csvFormat';
|
||||
import {DocData} from 'app/common/DocData';
|
||||
import {DocumentSettings} from 'app/common/DocumentSettings';
|
||||
import {getReferencedTableId, isFullReferencingType} from 'app/common/gristTypes';
|
||||
import * as gristTypes from 'app/common/gristTypes';
|
||||
import * as gutil from 'app/common/gutil';
|
||||
import {safeJsonParse} from 'app/common/gutil';
|
||||
import {getCurrency, NumberFormatOptions} from 'app/common/NumberFormat';
|
||||
import NumberParse from 'app/common/NumberParse';
|
||||
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 flatMap = require('lodash/flatMap');
|
||||
|
||||
@ -99,7 +101,7 @@ class ChoiceListParser extends ValueParser {
|
||||
/**
|
||||
* This is different from other widget options which are simple JSON
|
||||
* 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 {
|
||||
visibleColId: string;
|
||||
@ -116,7 +118,7 @@ export class ReferenceParser extends ValueParser {
|
||||
|
||||
protected _visibleColId = this.widgetOpts.visibleColId;
|
||||
protected _tableData = this.widgetOpts.tableData;
|
||||
protected _visibleColParser = createParser(
|
||||
protected _visibleColParser = createParserRaw(
|
||||
this.widgetOpts.visibleColType,
|
||||
this.widgetOpts.visibleColWidgetOpts,
|
||||
this.docSettings,
|
||||
@ -218,7 +220,7 @@ export const valueParserClasses: { [type: string]: typeof ValueParser } = {
|
||||
* widgetOpts is usually the field/column's widgetOptions JSON
|
||||
* but referencing columns need more than that, see ReferenceParsingOptions above.
|
||||
*/
|
||||
export function createParser(
|
||||
export function createParserRaw(
|
||||
type: string, widgetOpts: FormatOptions, docSettings: DocumentSettings
|
||||
): (value: string) => any {
|
||||
const cls = valueParserClasses[gristTypes.extractTypeFromColType(type)];
|
||||
@ -228,3 +230,43 @@ export function createParser(
|
||||
}
|
||||
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