mirror of
https://github.com/gristlabs/grist-core.git
synced 2024-10-27 20:44:07 +00:00
418681915e
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
122 lines
3.8 KiB
TypeScript
122 lines
3.8 KiB
TypeScript
import {BaseAPI, IOptions} from 'app/common/BaseAPI';
|
|
import {CellValue, ColValues} from 'app/common/DocActions';
|
|
import {addCurrentOrgToPath} from 'app/common/urlUtils';
|
|
|
|
/**
|
|
* Form and associated field metadata from a Grist view section.
|
|
*
|
|
* Includes the layout of the form, metadata such as the form title, and
|
|
* a map of data for each field in the form. All of this is used to build a
|
|
* submittable version of the form (see `FormRenderer.ts`, which handles the
|
|
* actual building of forms).
|
|
*/
|
|
export interface Form {
|
|
formFieldsById: Record<number, FormField>;
|
|
formLayoutSpec: string;
|
|
formTitle: string;
|
|
formTableId: string;
|
|
}
|
|
|
|
/**
|
|
* Metadata for a field in a form.
|
|
*
|
|
* Form fields are directly related to Grist fields; the former is based on data
|
|
* from the latter, with additional metadata specific to forms, like whether a
|
|
* form field is required. All of this is used to build a field in a submittable
|
|
* version of the form (see `FormRenderer.ts`, which handles the actual building
|
|
* of forms).
|
|
*/
|
|
export interface FormField {
|
|
/** The field label. Defaults to the Grist column label or id. */
|
|
question: string;
|
|
/** The field description. */
|
|
description: string;
|
|
/** The Grist column id of the field. */
|
|
colId: string;
|
|
/** The Grist column type of the field (e.g. "Text"). */
|
|
type: string;
|
|
/** Additional field options. */
|
|
options: FormFieldOptions;
|
|
/** Populated with data from a referenced table. Only set if `type` is a Reference type. */
|
|
refValues: [number, CellValue][] | null;
|
|
}
|
|
|
|
interface FormFieldOptions {
|
|
/** True if the field is required to submit the form. */
|
|
formRequired?: boolean;
|
|
/** Populated with a list of options. Only set if the field `type` is a Choice/Reference Liste. */
|
|
choices?: string[];
|
|
}
|
|
|
|
export interface FormAPI {
|
|
getForm(options: GetFormOptions): Promise<Form>;
|
|
createRecord(options: CreateRecordOptions): Promise<void>;
|
|
}
|
|
|
|
interface GetFormCommonOptions {
|
|
vsId: number;
|
|
}
|
|
|
|
interface GetFormWithDocIdOptions extends GetFormCommonOptions {
|
|
docId: string;
|
|
}
|
|
|
|
interface GetFormWithShareKeyOptions extends GetFormCommonOptions {
|
|
shareKey: string;
|
|
}
|
|
|
|
type GetFormOptions = GetFormWithDocIdOptions | GetFormWithShareKeyOptions;
|
|
|
|
interface CreateRecordCommonOptions {
|
|
tableId: string;
|
|
colValues: ColValues;
|
|
}
|
|
|
|
interface CreateRecordWithDocIdOptions extends CreateRecordCommonOptions {
|
|
docId: string;
|
|
}
|
|
|
|
interface CreateRecordWithShareKeyOptions extends CreateRecordCommonOptions {
|
|
shareKey: string;
|
|
}
|
|
|
|
type CreateRecordOptions = CreateRecordWithDocIdOptions | CreateRecordWithShareKeyOptions;
|
|
|
|
export class FormAPIImpl extends BaseAPI implements FormAPI {
|
|
constructor(private _homeUrl: string, options: IOptions = {}) {
|
|
super(options);
|
|
}
|
|
|
|
public async getForm(options: GetFormOptions): Promise<Form> {
|
|
if ('docId' in options) {
|
|
const {docId, vsId} = options;
|
|
return this.requestJson(`${this._url}/api/docs/${docId}/forms/${vsId}`, {method: 'GET'});
|
|
} else {
|
|
const {shareKey, vsId} = options;
|
|
return this.requestJson(`${this._url}/api/s/${shareKey}/forms/${vsId}`, {method: 'GET'});
|
|
}
|
|
}
|
|
|
|
public async createRecord(options: CreateRecordOptions): Promise<void> {
|
|
if ('docId' in options) {
|
|
const {docId, tableId, colValues} = options;
|
|
return this.requestJson(`${this._url}/api/docs/${docId}/tables/${tableId}/records`, {
|
|
method: 'POST',
|
|
body: JSON.stringify({records: [{fields: colValues}]}),
|
|
});
|
|
} else {
|
|
const {shareKey, tableId, colValues} = options;
|
|
const url = new URL(`${this._url}/api/s/${shareKey}/tables/${tableId}/records`);
|
|
url.searchParams.set('utm_source', 'grist-forms');
|
|
return this.requestJson(url.href, {
|
|
method: 'POST',
|
|
body: JSON.stringify({records: [{fields: colValues}]}),
|
|
});
|
|
}
|
|
}
|
|
|
|
private get _url(): string {
|
|
return addCurrentOrgToPath(this._homeUrl);
|
|
}
|
|
}
|