(core) Widget options api

Summary:
Adding configuration options for CustomWidgets.

Custom widgets can now store options (in JSON) in viewSection metadata.

Changes in grist-plugin-api:
- Adding onOptions handler, that will be invoked when the widget is ready and when the configuration is changed
- Adding WidgetAPI - new API to read and save a configuration for widget.

Changes in Grist:
- Rewriting CustomView code, and extracting code that is responsible for showing the iframe and registering Rpc.
- Adding Open Configuration button to Widget section in the Creator panel and in the section menu.
- Custom Widgets can implement "configure" method, to show configuration screen when requested.

Test Plan: Browser tests.

Reviewers: paulfitz, dsagal

Reviewed By: paulfitz

Differential Revision: https://phab.getgrist.com/D3185
This commit is contained in:
Jarosław Sadziński
2022-01-12 14:30:51 +01:00
parent 5a876976d5
commit 85ef873ce5
18 changed files with 1087 additions and 318 deletions

View File

@@ -1,7 +1,7 @@
import * as BaseView from 'app/client/components/BaseView';
import { ColumnRec, FilterRec, TableRec, ViewFieldRec, ViewRec } from 'app/client/models/DocModel';
import * as modelUtil from 'app/client/models/modelUtil';
import {ICustomWidget} from 'app/common/CustomWidget';
import {AccessLevel, ICustomWidget} from 'app/common/CustomWidget';
import * as ko from 'knockout';
import { CursorPos, } from 'app/client/components/Cursor';
import { KoArray, } from 'app/client/lib/koArray';
@@ -123,6 +123,11 @@ export interface ViewSectionRec extends IRowModel<"_grist_Views_section"> {
// Number for frozen columns to display.
// We won't freeze all the columns on a grid, it will leave at least 1 column unfrozen.
numFrozen: ko.Computed<number>;
activeCustomOptions: modelUtil.CustomComputed<any>;
// Temporary variable holding flag that describes if the widget supports custom options (set by api).
hasCustomOptions: ko.Observable<boolean>;
// Temporary variable holding widget desired access (changed either from manifest or via api).
desiredAccessLevel: ko.Observable<AccessLevel|null>;
// Save all filters of fields/columns in the section.
saveFilters(): Promise<void>;
@@ -150,6 +155,10 @@ export interface CustomViewSectionDef {
* Custom widget information.
*/
widgetDef: modelUtil.KoSaveableObservable<ICustomWidget|null>;
/**
* Custom widget options.
*/
widgetOptions: modelUtil.KoSaveableObservable<Record<string, any>|null>;
/**
* Access granted to url.
*/
@@ -206,13 +215,17 @@ export function createViewSectionRec(this: ViewSectionRec, docModel: DocModel):
mode: customDefObj.prop('mode'),
url: customDefObj.prop('url'),
widgetDef: customDefObj.prop('widgetDef'),
widgetOptions: customDefObj.prop('widgetOptions'),
access: customDefObj.prop('access'),
pluginId: customDefObj.prop('pluginId'),
sectionId: customDefObj.prop('sectionId')
};
this.saveCustomDef = () => {
return customDefObj.save();
this.activeCustomOptions = modelUtil.customValue(this.customDef.widgetOptions);
this.saveCustomDef = async () => {
await customDefObj.save();
this.activeCustomOptions.revert();
};
this.themeDef = modelUtil.fieldWithDefault(this.theme, 'form');
@@ -447,4 +460,7 @@ export function createViewSectionRec(this: ViewSectionRec, docModel: DocModel):
)
)
);
this.hasCustomOptions = ko.observable(false);
this.desiredAccessLevel = ko.observable(null);
}