mirror of
https://github.com/gristlabs/grist-core.git
synced 2026-03-02 04:09:24 +00:00
(core) Forms feature
Summary: A new widget type Forms. For now hidden behind GRIST_EXPERIMENTAL_PLUGINS(). This diff contains all the core moving parts as a serves as a base to extend this functionality further. Test Plan: New test added Reviewers: georgegevoian Reviewed By: georgegevoian Subscribers: paulfitz Differential Revision: https://phab.getgrist.com/D4130
This commit is contained in:
@@ -54,6 +54,16 @@ MetaRowModel.prototype._assignColumn = function(colName) {
|
||||
MetaRowModel.Floater = function(tableModel, rowIdObs) {
|
||||
this._table = tableModel;
|
||||
this.rowIdObs = rowIdObs;
|
||||
|
||||
// Some tsc error prevents me from adding this at the module level.
|
||||
// This method is part of the interface of MetaRowModel.
|
||||
// TODO: Fix the tsc error and move this to the module level.
|
||||
if (!this.constructor.prototype.getRowId) {
|
||||
this.constructor.prototype.getRowId = function() {
|
||||
return this.rowIdObs();
|
||||
}
|
||||
}
|
||||
|
||||
// Note that ._index isn't supported because it doesn't make sense for a floating row model.
|
||||
|
||||
this._underlyingRowModel = this.autoDispose(ko.computed(function() {
|
||||
|
||||
@@ -17,7 +17,9 @@ export interface ViewFieldRec extends IRowModel<"_grist_Views_section_field">, R
|
||||
|
||||
widthPx: ko.Computed<string>;
|
||||
column: ko.Computed<ColumnRec>;
|
||||
origLabel: ko.Computed<string>;
|
||||
origCol: ko.Computed<ColumnRec>;
|
||||
pureType: ko.Computed<string>;
|
||||
colId: ko.Computed<string>;
|
||||
label: ko.Computed<string>;
|
||||
description: modelUtil.KoSaveableObservable<string>;
|
||||
@@ -101,6 +103,9 @@ export interface ViewFieldRec extends IRowModel<"_grist_Views_section_field">, R
|
||||
// `formatter` formats actual cell values, e.g. a whole list from the display column.
|
||||
formatter: ko.Computed<BaseFormatter>;
|
||||
|
||||
/** Label in FormView. By default FormView uses label, use this to override it. */
|
||||
question: modelUtil.KoSaveableObservable<string|undefined>;
|
||||
|
||||
createValueParser(): (value: string) => any;
|
||||
|
||||
// Helper which adds/removes/updates field's displayCol to match the formula.
|
||||
@@ -111,11 +116,13 @@ export function createViewFieldRec(this: ViewFieldRec, docModel: DocModel): void
|
||||
this.viewSection = refRecord(docModel.viewSections, this.parentId);
|
||||
this.widthDef = modelUtil.fieldWithDefault(this.width, () => this.viewSection().defaultWidth());
|
||||
|
||||
this.widthPx = ko.pureComputed(() => this.widthDef() + 'px');
|
||||
this.column = refRecord(docModel.columns, this.colRef);
|
||||
this.origCol = ko.pureComputed(() => this.column().origCol());
|
||||
this.colId = ko.pureComputed(() => this.column().colId());
|
||||
this.label = ko.pureComputed(() => this.column().label());
|
||||
this.widthPx = this.autoDispose(ko.pureComputed(() => this.widthDef() + 'px'));
|
||||
this.column = this.autoDispose(refRecord(docModel.columns, this.colRef));
|
||||
this.origCol = this.autoDispose(ko.pureComputed(() => this.column().origCol()));
|
||||
this.pureType = this.autoDispose(ko.pureComputed(() => this.column().pureType()));
|
||||
this.colId = this.autoDispose(ko.pureComputed(() => this.column().colId()));
|
||||
this.label = this.autoDispose(ko.pureComputed(() => this.column().label()));
|
||||
this.origLabel = this.autoDispose(ko.pureComputed(() => this.origCol().label()));
|
||||
this.description = modelUtil.savingComputed({
|
||||
read: () => this.column().description(),
|
||||
write: (setter, val) => setter(this.column().description, val)
|
||||
@@ -249,6 +256,7 @@ export function createViewFieldRec(this: ViewFieldRec, docModel: DocModel): void
|
||||
this.headerFontUnderline = this.widgetOptionsJson.prop('headerFontUnderline');
|
||||
this.headerFontItalic = this.widgetOptionsJson.prop('headerFontItalic');
|
||||
this.headerFontStrikethrough = this.widgetOptionsJson.prop('headerFontStrikethrough');
|
||||
this.question = this.widgetOptionsJson.prop('question');
|
||||
|
||||
this.documentSettings = ko.pureComputed(() => docModel.docInfoRow.documentSettingsJson());
|
||||
this.style = ko.pureComputed({
|
||||
|
||||
@@ -37,6 +37,7 @@ import defaults = require('lodash/defaults');
|
||||
export interface InsertColOptions {
|
||||
colInfo?: ColInfo;
|
||||
index?: number;
|
||||
nestInActiveBundle?: boolean;
|
||||
}
|
||||
|
||||
export interface ColInfo {
|
||||
@@ -54,6 +55,10 @@ export interface NewColInfo {
|
||||
colRef: number;
|
||||
}
|
||||
|
||||
export interface NewFieldInfo extends NewColInfo {
|
||||
fieldRef: number;
|
||||
}
|
||||
|
||||
// Represents a section of user views, now also known as a "page widget" (e.g. a view may contain
|
||||
// a grid section and a chart section).
|
||||
export interface ViewSectionRec extends IRowModel<"_grist_Views_section">, RuleOwner {
|
||||
@@ -103,7 +108,7 @@ export interface ViewSectionRec extends IRowModel<"_grist_Views_section">, RuleO
|
||||
|
||||
borderWidthPx: ko.Computed<string>;
|
||||
|
||||
layoutSpecObj: modelUtil.ObjObservable<any>;
|
||||
layoutSpecObj: modelUtil.SaveableObjObservable<any>;
|
||||
|
||||
_savedFilters: ko.Computed<KoArray<FilterRec>>;
|
||||
|
||||
@@ -268,9 +273,11 @@ export interface ViewSectionRec extends IRowModel<"_grist_Views_section">, RuleO
|
||||
// Saves custom definition (bundles change)
|
||||
saveCustomDef(): Promise<void>;
|
||||
|
||||
insertColumn(colId?: string|null, options?: InsertColOptions): Promise<NewColInfo>;
|
||||
insertColumn(colId?: string|null, options?: InsertColOptions): Promise<NewFieldInfo>;
|
||||
|
||||
showColumn(colRef: number, index?: number): Promise<void>
|
||||
showColumn(col: number|string, index?: number): Promise<number>
|
||||
|
||||
removeField(colRef: number): Promise<void>;
|
||||
}
|
||||
|
||||
export type WidgetMappedColumn = number|number[]|null;
|
||||
@@ -834,7 +841,7 @@ export function createViewSectionRec(this: ViewSectionRec, docModel: DocModel):
|
||||
...colInfo,
|
||||
'_position': parentPos,
|
||||
}];
|
||||
let newColInfo: NewColInfo;
|
||||
let newColInfo: NewFieldInfo;
|
||||
await docModel.docData.bundleActions('Insert column', async () => {
|
||||
newColInfo = await docModel.dataTables[this.tableId.peek()].sendTableAction(action);
|
||||
if (!this.isRaw.peek() && !this.isRecordCard.peek()) {
|
||||
@@ -843,19 +850,28 @@ export function createViewSectionRec(this: ViewSectionRec, docModel: DocModel):
|
||||
parentId: this.id.peek(),
|
||||
parentPos,
|
||||
};
|
||||
await docModel.viewFields.sendTableAction(['AddRecord', null, fieldInfo]);
|
||||
const fieldRef = await docModel.viewFields.sendTableAction(['AddRecord', null, fieldInfo]);
|
||||
newColInfo.fieldRef = fieldRef;
|
||||
}
|
||||
});
|
||||
}, {nestInActiveBundle: options.nestInActiveBundle});
|
||||
return newColInfo!;
|
||||
};
|
||||
|
||||
this.showColumn = async (colRef: number, index = this.viewFields().peekLength) => {
|
||||
this.showColumn = async (col: string|number, index = this.viewFields().peekLength) => {
|
||||
const parentPos = fieldInsertPositions(this.viewFields(), index, 1)[0];
|
||||
const colRef = typeof col === 'string'
|
||||
? this.table().columns().all().find(c => c.colId() === col)?.getRowId()
|
||||
: col;
|
||||
const colInfo = {
|
||||
colRef,
|
||||
parentId: this.id.peek(),
|
||||
parentPos,
|
||||
};
|
||||
await docModel.viewFields.sendTableAction(['AddRecord', null, colInfo]);
|
||||
return await docModel.viewFields.sendTableAction(['AddRecord', null, colInfo]);
|
||||
};
|
||||
|
||||
this.removeField = async (fieldRef: number) => {
|
||||
const action = ['RemoveRecord', fieldRef];
|
||||
await docModel.viewFields.sendTableAction(action);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -33,3 +33,7 @@ export function PERMITTED_CUSTOM_WIDGETS(): Observable<string[]> {
|
||||
}
|
||||
return G.window.PERMITTED_CUSTOM_WIDGETS;
|
||||
}
|
||||
|
||||
export function GRIST_FORMS_FEATURE() {
|
||||
return Boolean(getGristConfig().experimentalPlugins);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user