gristlabs_grist-core/app/plugin/GristAPI.ts
Paul Fitzpatrick ac5452c89f (core) add grist.onRecord and grist.onRecords event handlers
Summary:
This simplifies writing custom widgets that access selected
data.  To access the record at which the cursor is set, and
get any future changes to it as the cursor moves or data
changes, it suffices now to do:

```
grist.ready();
grist.onRecord(record => /* render */);
```

Similarly to access the set of selected records, and get any
changes, it suffices now to do:

```
grist.ready();
grist.onRecords(records => /* render */);
```

The `records` argument will be a list of objects, each of which
is a single record.  This is distinct from the column-based
representation favored in Grist up ontil now.  That remains
how methods like `fetchTable` or `fetchSelectedTable` represent
their results.  In the future, methods named like `fetchRecords`
or `fetchSelectedRecords` could be added that return lists.

Test Plan: extended tests

Reviewers: dsagal

Reviewed By: dsagal

Differential Revision: https://phab.getgrist.com/D2583
2020-08-13 14:34:23 -04:00

103 lines
4.0 KiB
TypeScript

/**
* This file defines the interface for the grist api exposed to SafeBrowser plugins. Grist supports
* various ways to require it to cover various scenarios. If writing the main safeBrowser module
* (the one referenced by the components.safeBrowser key of the manifest) use
* `self.importScript('grist');`, if writing a view include the script in the html `<script src="grist"></script>`
*
*
* Example usage (let's assume that Grist let's plugin contributes to a Foo API defined as follow ):
*
* interface Foo {
* foo(name: string): Promise<string>;
* }
*
* > main.ts:
* class MyFoo {
* public foo(name: string): Promise<string> {
* return new Promise<string>( async resolve => {
* grist.rpc.onMessage( e => {
* resolve(e.data + name);
* });
* grist.ready();
* await grist.api.render('view1.html', 'fullscreen');
* });
* }
* }
* grist.rpc.registerImpl<Foo>('grist', new MyFoo()); // can add 3rd arg with type information
*
* > view1.html includes:
* grist.api.render('static/view2.html', 'fullscreen').then( view => {
* grist.rpc.onMessage(e => grist.rpc.postMessageForward("main.ts", e.data));
* });
*
* > view2.html includes:
* grist.rpc.postMessage('view1.html', 'foo ');
*
*/
import {RenderOptions, RenderTarget} from './RenderOptions';
export type ComponentKind = "safeBrowser" | "safePython" | "unsafeNode";
export const RPC_GRISTAPI_INTERFACE = '_grist_api';
export interface GristAPI {
/**
* Render the file at `path` into the `target` location in Grist. `path` must be relative to the
* root of the plugin's directory and point to an html that is contained within the plugin's
* directory. `target` is a predifined location of the Grist UI, it could be `fullscreen` or
* identifier for an inline target. Grist provides inline target identifiers in certain call
* plugins. E.g. ImportSourceAPI.getImportSource is given a target identifier to allow rende UI
* inline in the import dialog. Returns the procId which can be used to dispose the view.
*/
render(path: string, target: RenderTarget, options?: RenderOptions): Promise<number>;
/**
* Dispose the process with id procId. If the process was embedded into the UI, removes the
* corresponding element from the view.
*/
dispose(procId: number): Promise<void>;
// Subscribes to actions for `tableId`. Actions of all subscribed tables are send as rpc's
// message.
// TODO: document format of messages that can be listened on `rpc.onMessage(...);`
subscribe(tableId: string): Promise<void>;
// Unsubscribe from actions for `tableId`.
unsubscribe(tableId: string): Promise<void>;
}
/**
* GristDocAPI interface is implemented by Grist, and allows getting information from and
* interacting with the Grist document to which a plugin is attached.
*/
export interface GristDocAPI {
// Returns the docName that identifies the document.
getDocName(): Promise<string>;
// Returns a sorted list of table IDs.
listTables(): Promise<string[]>;
// Returns a complete table of data in the format {colId: [values]}, including the 'id' column.
// Do not modify the returned arrays in-place, especially if used directly (not over RPC).
// TODO: return type is Promise{[colId: string]: CellValue[]}> but cannot be specified because
// ts-interface-builder does not properly support index-signature.
fetchTable(tableId: string): Promise<any>;
// Applies an array of user actions.
// todo: return type should be Promise<ApplyUAResult>, but this requires importing modules from
// `app/common` which is not currently supported by the build.
applyUserActions(actions: any[][]): Promise<any>;
}
export interface GristView {
// Like fetchTable, but gets data for the custom section specifically, if there is any.
// TODO: return type is Promise{[colId: string]: CellValue[]}> but cannot be specified because
// ts-interface-builder does not properly support index-signature.
fetchSelectedTable(): Promise<any>;
// Similar TODO to fetchSelectedTable for return type.
fetchSelectedRecord(rowId: number): Promise<any>;
}