mirror of
https://github.com/gristlabs/grist-core.git
synced 2026-03-02 04:09:24 +00:00
Webhook trigger update by column (#832)
Add functionality to filter webhooks based on a column or columns.
This commit is contained in:
@@ -37,7 +37,7 @@ const WEBHOOK_COLUMNS = [
|
||||
id: 'vt_webhook_fc1',
|
||||
colId: 'tableId',
|
||||
type: 'Choice',
|
||||
label: 'Table',
|
||||
label: t('Table'),
|
||||
// widgetOptions are configured later, since the choices depend
|
||||
// on the user tables in the document.
|
||||
},
|
||||
@@ -45,13 +45,13 @@ const WEBHOOK_COLUMNS = [
|
||||
id: 'vt_webhook_fc2',
|
||||
colId: 'url',
|
||||
type: 'Text',
|
||||
label: 'URL',
|
||||
label: t('URL'),
|
||||
},
|
||||
{
|
||||
id: 'vt_webhook_fc3',
|
||||
colId: 'eventTypes',
|
||||
type: 'ChoiceList',
|
||||
label: 'Event Types',
|
||||
label: t('Event Types'),
|
||||
widgetOptions: JSON.stringify({
|
||||
widget: 'TextBox',
|
||||
alignment: 'left',
|
||||
@@ -59,11 +59,17 @@ const WEBHOOK_COLUMNS = [
|
||||
choiceOptions: {},
|
||||
}),
|
||||
},
|
||||
{
|
||||
id: 'vt_webhook_fc10',
|
||||
colId: 'watchedColIdsText',
|
||||
type: 'Text',
|
||||
label: t('Filter for changes in these columns (semicolon-separated ids)'),
|
||||
},
|
||||
{
|
||||
id: 'vt_webhook_fc4',
|
||||
colId: 'enabled',
|
||||
type: 'Bool',
|
||||
label: 'Enabled',
|
||||
label: t('Enabled'),
|
||||
widgetOptions: JSON.stringify({
|
||||
widget: 'Switch',
|
||||
}),
|
||||
@@ -72,31 +78,31 @@ const WEBHOOK_COLUMNS = [
|
||||
id: 'vt_webhook_fc5',
|
||||
colId: 'isReadyColumn',
|
||||
type: 'Text',
|
||||
label: 'Ready Column',
|
||||
label: t('Ready Column'),
|
||||
},
|
||||
{
|
||||
id: 'vt_webhook_fc6',
|
||||
colId: 'webhookId',
|
||||
type: 'Text',
|
||||
label: 'Webhook Id',
|
||||
label: t('Webhook Id'),
|
||||
},
|
||||
{
|
||||
id: 'vt_webhook_fc7',
|
||||
colId: 'name',
|
||||
type: 'Text',
|
||||
label: 'Name',
|
||||
label: t('Name'),
|
||||
},
|
||||
{
|
||||
id: 'vt_webhook_fc8',
|
||||
colId: 'memo',
|
||||
type: 'Text',
|
||||
label: 'Memo',
|
||||
label: t('Memo'),
|
||||
},
|
||||
{
|
||||
id: 'vt_webhook_fc9',
|
||||
colId: 'status',
|
||||
type: 'Text',
|
||||
label: 'Status',
|
||||
label: t('Status'),
|
||||
},
|
||||
] as const;
|
||||
|
||||
@@ -107,8 +113,8 @@ const WEBHOOK_VIEW_FIELDS: Array<(typeof WEBHOOK_COLUMNS)[number]['colId']> = [
|
||||
'name', 'memo',
|
||||
'eventTypes', 'url',
|
||||
'tableId', 'isReadyColumn',
|
||||
'webhookId', 'enabled',
|
||||
'status'
|
||||
'watchedColIdsText', 'webhookId',
|
||||
'enabled', 'status'
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -127,9 +133,9 @@ class WebhookExternalTable implements IExternalTable {
|
||||
public name = 'GristHidden_WebhookTable';
|
||||
public initialActions = _prepareWebhookInitialActions(this.name);
|
||||
public saveableFields = [
|
||||
'tableId', 'url', 'eventTypes', 'enabled', 'name', 'memo', 'isReadyColumn',
|
||||
'tableId', 'watchedColIdsText', 'url', 'eventTypes', 'enabled', 'name', 'memo', 'isReadyColumn',
|
||||
];
|
||||
public webhooks: ObservableArray<WebhookSummary> = observableArray<WebhookSummary>([]);
|
||||
public webhooks: ObservableArray<UIWebhookSummary> = observableArray<UIWebhookSummary>([]);
|
||||
|
||||
public constructor(private _docApi: DocAPI) {
|
||||
}
|
||||
@@ -151,7 +157,7 @@ class WebhookExternalTable implements IExternalTable {
|
||||
}
|
||||
const colIds = new Set(getColIdsFromDocAction(d) || []);
|
||||
if (colIds.has('webhookId') || colIds.has('status')) {
|
||||
throw new Error(`Sorry, not all fields can be edited.`);
|
||||
throw new Error(t(`Sorry, not all fields can be edited.`));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -162,7 +168,7 @@ class WebhookExternalTable implements IExternalTable {
|
||||
continue;
|
||||
}
|
||||
await this._removeWebhook(rec);
|
||||
reportMessage(`Removed webhook.`);
|
||||
reportMessage(t(`Removed webhook.`));
|
||||
}
|
||||
const updates = new Set(delta.updateRows);
|
||||
const t2 = editor;
|
||||
@@ -227,6 +233,7 @@ class WebhookExternalTable implements IExternalTable {
|
||||
for (const webhook of webhooks) {
|
||||
const values = _mapWebhookValues(webhook);
|
||||
const rowId = rowMap.get(webhook.id);
|
||||
|
||||
if (rowId) {
|
||||
toRemove.delete(rowId);
|
||||
actions.push(
|
||||
@@ -269,7 +276,12 @@ class WebhookExternalTable implements IExternalTable {
|
||||
private _initalizeWebhookList(webhooks: WebhookSummary[]){
|
||||
|
||||
this.webhooks.removeAll();
|
||||
this.webhooks.push(...webhooks);
|
||||
this.webhooks.push(
|
||||
...webhooks.map(webhook => {
|
||||
const uiWebhook: UIWebhookSummary = {...webhook};
|
||||
uiWebhook.fields.watchedColIdsText = webhook.fields.watchedColIds ? webhook.fields.watchedColIds.join(";") : "";
|
||||
return uiWebhook;
|
||||
}));
|
||||
}
|
||||
|
||||
private _getErrorString(e: ApiError): string {
|
||||
@@ -308,6 +320,9 @@ class WebhookExternalTable implements IExternalTable {
|
||||
if (fields.eventTypes) {
|
||||
fields.eventTypes = without(fields.eventTypes, 'L');
|
||||
}
|
||||
fields.watchedColIds = fields.watchedColIdsText
|
||||
? fields.watchedColIdsText.split(";").filter((colId: string) => colId.trim() !== "")
|
||||
: [];
|
||||
return fields;
|
||||
}
|
||||
}
|
||||
@@ -355,12 +370,12 @@ export class WebhookPage extends DisposableWithEvents {
|
||||
|
||||
public async reset() {
|
||||
await this.docApi.flushWebhooks();
|
||||
reportSuccess('Cleared webhook queue.');
|
||||
reportSuccess(t('Cleared webhook queue.'));
|
||||
}
|
||||
|
||||
public async resetSelected(id: string) {
|
||||
await this.docApi.flushWebhook(id);
|
||||
reportSuccess(`Cleared webhook ${id} queue.`);
|
||||
reportSuccess(t(`Cleared webhook ${id} queue.`));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -440,16 +455,21 @@ function _prepareWebhookInitialActions(tableId: string): DocAction[] {
|
||||
/**
|
||||
* Map a webhook summary to a webhook table raw record. The main
|
||||
* difference is that `eventTypes` is tweaked to be in a cell format,
|
||||
* and `status` is converted to a string.
|
||||
* `status` is converted to a string,
|
||||
* and `watchedColIdsText` is converted to list in a cell format.
|
||||
*/
|
||||
function _mapWebhookValues(webhookSummary: WebhookSummary): Partial<WebhookSchemaType> {
|
||||
function _mapWebhookValues(webhookSummary: UIWebhookSummary): Partial<WebhookSchemaType> {
|
||||
const fields = webhookSummary.fields;
|
||||
const {eventTypes} = fields;
|
||||
const {eventTypes, watchedColIdsText} = fields;
|
||||
const watchedColIds = watchedColIdsText
|
||||
? watchedColIdsText.split(";").filter(colId => colId.trim() !== "")
|
||||
: [];
|
||||
return {
|
||||
...fields,
|
||||
webhookId: webhookSummary.id,
|
||||
status: JSON.stringify(webhookSummary.usage),
|
||||
eventTypes: [GristObjCode.List, ...eventTypes],
|
||||
watchedColIds: [GristObjCode.List, ...watchedColIds],
|
||||
};
|
||||
}
|
||||
|
||||
@@ -457,6 +477,11 @@ type WebhookSchemaType = {
|
||||
[prop in keyof WebhookSummary['fields']]: WebhookSummary['fields'][prop]
|
||||
} & {
|
||||
eventTypes: [GristObjCode, ...unknown[]];
|
||||
watchedColIds: [GristObjCode, ...unknown[]];
|
||||
status: string;
|
||||
webhookId: string;
|
||||
}
|
||||
|
||||
type UIWebhookSummary = WebhookSummary & {
|
||||
fields: {watchedColIdsText?: string;}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user