(core) Forms Improvements

Summary:
 - Forms now have a reset button.
 - Choice and Reference fields in forms now have an improved select menu.
 - Formula and attachments column types are no longer mappable or visible in forms.
 - Fields in a form widget are now removed if their column is deleted.
 - The preview button in a published form widget has been replaced with a view button. It now opens the published form in a new tab.
 - A new share menu for published form widgets, with options to copy a link or embed code.
 - Forms can now have multiple sections.
 - Form widgets now indicate when publishing is unavailable (e.g. in forks or unsaved documents).
 - General improvements to form styling.

Test Plan: Browser tests.

Reviewers: jarek

Reviewed By: jarek

Subscribers: paulfitz

Differential Revision: https://phab.getgrist.com/D4203
This commit is contained in:
George Gevoian
2024-03-20 10:51:59 -04:00
parent aff9c7075c
commit 418681915e
40 changed files with 1643 additions and 617 deletions

View File

@@ -1,4 +1,4 @@
import {FormLayoutNode} from 'app/client/components/FormRenderer';
import {FormLayoutNode, patchLayoutSpec} from 'app/client/components/FormRenderer';
import {TypedFormData, typedFormDataToJson} from 'app/client/lib/formUtils';
import {makeT} from 'app/client/lib/localization';
import {getHomeUrl} from 'app/client/models/AppModel';
@@ -25,7 +25,13 @@ export class FormModelImpl extends Disposable implements FormModel {
public readonly formLayout = Computed.create(this, this.form, (_use, form) => {
if (!form) { return null; }
return safeJsonParse(form.formLayoutSpec, null) as FormLayoutNode;
const layout = safeJsonParse(form.formLayoutSpec, null) as FormLayoutNode | null;
if (!layout) { throw new Error('invalid formLayoutSpec'); }
const patchedLayout = patchLayoutSpec(layout, new Set(Object.keys(form.formFieldsById).map(Number)));
if (!patchedLayout) { throw new Error('invalid formLayoutSpec'); }
return patchedLayout;
});
public readonly submitting = Observable.create<boolean>(this, false);
public readonly submitted = Observable.create<boolean>(this, false);

View File

@@ -68,6 +68,7 @@ export interface ColumnRec extends IRowModel<"_grist_Tables_column"> {
disableEditData: ko.Computed<boolean>; // True to disable editing of the data in this column.
isHiddenCol: ko.Computed<boolean>;
isFormCol: ko.Computed<boolean>;
// Returns the rowModel for the referenced table, or null, if is not a reference column.
refTable: ko.Computed<TableRec|null>;
@@ -144,6 +145,11 @@ export function createColumnRec(this: ColumnRec, docModel: DocModel): void {
this.disableEditData = ko.pureComputed(() => Boolean(this.summarySourceCol()));
this.isHiddenCol = ko.pureComputed(() => gristTypes.isHiddenCol(this.colId()));
this.isFormCol = ko.pureComputed(() => (
!this.isHiddenCol() &&
this.pureType() !== 'Attachments' &&
!this.isRealFormula()
));
// Returns the rowModel for the referenced table, or null, if this is not a reference column.
this.refTable = ko.pureComputed(() => {