(core) Cursor in custom widgets

Summary:
Adding a new method `setCursorPos` in the widget API, and a new configuration option for the ready message `allowSelectBy` that exposes custom widgets in the `Select by` dropdown.
With this, a custom widget can control the position of the linked widgets and is able to change the column in the creator panel.

Test Plan: Added new test. Existing tests should pass.

Reviewers: JakubSerafin

Reviewed By: JakubSerafin

Subscribers: JakubSerafin

Differential Revision: https://phab.getgrist.com/D3993
This commit is contained in:
Jarosław Sadziński
2023-08-28 11:16:17 +02:00
parent c02acff361
commit b6a431dd58
33 changed files with 155 additions and 84 deletions

View File

@@ -19,6 +19,7 @@ export const InteractionOptionsRequest = t.iface([], {
"requiredAccess": t.opt("string"),
"hasCustomOptions": t.opt("boolean"),
"columns": t.opt("ColumnsToMap"),
"allowSelectBy": t.opt("boolean"),
});
export const InteractionOptions = t.iface([], {

View File

@@ -50,6 +50,10 @@ export interface InteractionOptionsRequest {
* and those requested by Custom Widget.
*/
columns?: ColumnsToMap,
/**
* Show widget as linking source.
*/
allowSelectBy?: boolean,
}
/**

View File

@@ -4,6 +4,15 @@
import * as t from "ts-interface-checker";
// tslint:disable:object-literal-key-quotes
export const UIRowId = t.union("number", t.lit('new'));
export const CursorPos = t.iface([], {
"rowId": t.opt("UIRowId"),
"rowIndex": t.opt("number"),
"fieldIndex": t.opt("number"),
"sectionId": t.opt("number"),
});
export const ComponentKind = t.union(t.lit("safeBrowser"), t.lit("safePython"), t.lit("unsafeNode"));
export const GristAPI = t.iface([], {
@@ -25,7 +34,8 @@ export const GristView = t.iface([], {
"fetchSelectedTable": t.func("any"),
"fetchSelectedRecord": t.func("any", t.param("rowId", "number")),
"allowSelectBy": t.func("void"),
"setSelectedRows": t.func("void", t.param("rowIds", t.array("number"))),
"setSelectedRows": t.func("void", t.param("rowIds", t.union(t.array("number"), "null"))),
"setCursorPos": t.func("void", t.param("pos", "CursorPos")),
});
export const AccessTokenOptions = t.iface([], {
@@ -39,6 +49,8 @@ export const AccessTokenResult = t.iface([], {
});
const exportedTypeSuite: t.ITypeSuite = {
UIRowId,
CursorPos,
ComponentKind,
GristAPI,
GristDocAPI,

View File

@@ -37,6 +37,36 @@
import {RenderOptions, RenderTarget} from './RenderOptions';
// This is the row ID used in the client, but it's helpful to have available in some common code
// as well, which is why it's declared here. Note that for data actions and stored data,
// 'new' is not used.
/**
* Represents the id of a row in a table. The value of the `id` column. Might be a number or 'new' value for a new row.
*/
export type UIRowId = number | 'new';
/**
* Represents the position of an active cursor on a page.
*/
export interface CursorPos {
/**
* The rowId (value of the `id` column) of the current cursor position, or 'new' if the cursor is on a new row.
*/
rowId?: UIRowId;
/**
* The index of the current row in the current view.
*/
rowIndex?: number;
/**
* The index of the selected field in the current view.
*/
fieldIndex?: number;
/**
* The id of a section that this cursor is in. Ignored when setting a cursor position for a particular view.
*/
sectionId?: number;
}
export type ComponentKind = "safeBrowser" | "safePython" | "unsafeNode";
export const RPC_GRISTAPI_INTERFACE = '_grist_api';
@@ -123,14 +153,20 @@ export interface GristView {
// because ts-interface-builder does not properly support index-signature.
/**
* Allow custom widget to be listed as a possible source for linking with SELECT BY.
* Deprecated now. It was used for filtering selected table by `setSelectedRows` method.
* Now the preferred way it to use ready message.
*/
allowSelectBy(): Promise<void>;
/**
* Set the list of selected rows to be used against any linked widget. Requires `allowSelectBy()`.
* Set the list of selected rows to be used against any linked widget.
*/
setSelectedRows(rowIds: number[]): Promise<void>;
setSelectedRows(rowIds: number[]|null): Promise<void>;
/**
* Sets the cursor position to a specific row and field. `sectionId` is ignored. Used for widget linking.
*/
setCursorPos(pos: CursorPos): Promise<void>
}
/**

View File

@@ -75,6 +75,10 @@ export const allowSelectBy = viewApi.allowSelectBy;
export const setSelectedRows = viewApi.setSelectedRows;
export const setCursorPos = viewApi.setCursorPos;
/**
* Fetches data backing the widget as for [[GristView.fetchSelectedTable]],
* but decoding data by default, replacing e.g. ['D', timestamp] with