(core) Improving custom widget API. Changing destroy function signature.

Summary:
Destroy function in TableOperations was throwing error when invoked with a single
record id instead of an array. Now it returns a void type.

Also changing mapColumns function signature as it doesn't require options for a default
behavior.

Test Plan: Updated tests.

Reviewers: alexmojaki

Reviewed By: alexmojaki

Differential Revision: https://phab.getgrist.com/D3404
This commit is contained in:
Jarosław Sadziński 2022-05-05 13:42:50 +02:00
parent 1e42871cc9
commit db57815d2b
4 changed files with 14 additions and 17 deletions

View File

@ -18,8 +18,7 @@ export interface TableOperations {
/** /**
* Delete a record or records. * Delete a record or records.
*/ */
destroy(recordId: Types.RecordId): Promise<Types.RecordId>; destroy(recordIds: Types.RecordId|Types.RecordId[]): Promise<void>;
destroy(recordIds: Types.RecordId[]): Promise<Types.RecordId[]>;
/** /**
* Add or update a record or records. * Add or update a record or records.

View File

@ -67,15 +67,12 @@ export class TableOperationsImpl implements TableOperations {
}); });
} }
public destroy(recordId: Types.RecordId): Promise<Types.RecordId>; public async destroy(recordIdOrRecordIds: Types.RecordId|Types.RecordId[]): Promise<void> {
public destroy(recordIds: Types.RecordId[]): Promise<Types.RecordId[]>; await withRecords(recordIdOrRecordIds, async (recordIds) => {
public async destroy(recordIdOrRecordIds: Types.RecordId|Types.RecordId[]): Promise<Types.RecordId|Types.RecordId[]> {
return withRecords(recordIdOrRecordIds, async (recordIds) => {
const tableId = await this._platform.getTableId(); const tableId = await this._platform.getTableId();
const actions = [['BulkRemoveRecord', tableId, recordIds]]; const actions = [['BulkRemoveRecord', tableId, recordIds]];
const sandboxRes = await this._applyUserActions( await this._applyUserActions(tableId, [], actions);
tableId, [], actions); return [];
return sandboxRes.retValues[0];
}); });
} }

View File

@ -216,13 +216,13 @@ async function getMappingsIfChanged(data: any): Promise<WidgetColumnMap|null> {
* Returns null if not all required columns were mapped or not widget doesn't support * Returns null if not all required columns were mapped or not widget doesn't support
* custom column mapping. * custom column mapping.
*/ */
export function mapColumnNames(data: any, options: { export function mapColumnNames(data: any, options?: {
columns?: ColumnsToMap columns?: ColumnsToMap
mappings?: WidgetColumnMap|null, mappings?: WidgetColumnMap|null,
reverse?: boolean, reverse?: boolean,
}) { }) {
options = {columns: _columnsToMap, mappings: _mappingsCache, reverse: false, ...options}; options = {columns: _columnsToMap, mappings: _mappingsCache, reverse: false, ...options};
// If not column configuration was requested or // If no column configuration was requested or
// table has no rows, return original data. // table has no rows, return original data.
if (!options.columns) { if (!options.columns) {
return data; return data;
@ -246,8 +246,8 @@ export function mapColumnNames(data: any, options: {
function isOptional(col: string) { function isOptional(col: string) {
return Boolean( return Boolean(
// Columns passed as strings are required. // Columns passed as strings are required.
!options.columns?.includes(col) !options!.columns?.includes(col)
&& options.columns?.find(c => typeof c === 'object' && c?.name === col && c.optional) && options!.columns?.find(c => typeof c === 'object' && c?.name === col && c.optional)
); );
} }
// For each widget column in mapping. // For each widget column in mapping.
@ -292,7 +292,7 @@ export function mapColumnNames(data: any, options: {
* original table in a widget with column mappings. As for mapColumnNames(), * original table in a widget with column mappings. As for mapColumnNames(),
* we don't attempt to do these transformations automatically. * we don't attempt to do these transformations automatically.
*/ */
export function mapColumnNamesBack(data: any, options: { export function mapColumnNamesBack(data: any, options?: {
columns?: ColumnsToMap columns?: ColumnsToMap
mappings?: WidgetColumnMap|null, mappings?: WidgetColumnMap|null,
}) { }) {
@ -320,10 +320,10 @@ export function onRecord(callback: (data: RowRecord | null, mappings: WidgetColu
* For custom widgets, add a handler that will be called whenever the * For custom widgets, add a handler that will be called whenever the
* new (blank) row is selected. * new (blank) row is selected.
*/ */
export function onNewRecord(callback: () => unknown) { export function onNewRecord(callback: (mappings: WidgetColumnMap | null) => unknown) {
on('message', async function(msg) { on('message', async function(msg) {
if (msg.tableId && msg.rowId === 'new') { if (msg.tableId && msg.rowId === 'new') {
callback(); callback(await getMappingsIfChanged(msg));
} }
}); });
} }

View File

@ -298,7 +298,8 @@ export class DocWorkerApi {
this._app.post('/api/docs/:docId/tables/:tableId/data/delete', canEdit, withDoc(async (activeDoc, req, res) => { this._app.post('/api/docs/:docId/tables/:tableId/data/delete', canEdit, withDoc(async (activeDoc, req, res) => {
const rowIds = req.body; const rowIds = req.body;
const op = getTableOperations(req, activeDoc); const op = getTableOperations(req, activeDoc);
res.json(await op.destroy(rowIds)); await op.destroy(rowIds);
res.json(null);
})); }));
// Download full document // Download full document