mirror of
https://github.com/n8n-io/n8n.git
synced 2025-02-02 07:01:30 -08:00
feat(Telegram Node): New operation sendAndWait (#12771)
This commit is contained in:
parent
5b760e7f7f
commit
2c58d47f8e
|
@ -13,6 +13,7 @@ import { labelFields, labelOperations } from './LabelDescription';
|
||||||
import { getGmailAliases, getLabels, getThreadMessages } from './loadOptions';
|
import { getGmailAliases, getLabels, getThreadMessages } from './loadOptions';
|
||||||
import { messageFields, messageOperations } from './MessageDescription';
|
import { messageFields, messageOperations } from './MessageDescription';
|
||||||
import { threadFields, threadOperations } from './ThreadDescription';
|
import { threadFields, threadOperations } from './ThreadDescription';
|
||||||
|
import { sendAndWaitWebhooks } from '../../../../utils/sendAndWait/descriptions';
|
||||||
import type { IEmail } from '../../../../utils/sendAndWait/interfaces';
|
import type { IEmail } from '../../../../utils/sendAndWait/interfaces';
|
||||||
import {
|
import {
|
||||||
configureWaitTillDate,
|
configureWaitTillDate,
|
||||||
|
@ -68,26 +69,7 @@ const versionDescription: INodeTypeDescription = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
webhooks: [
|
webhooks: sendAndWaitWebhooks,
|
||||||
{
|
|
||||||
name: 'default',
|
|
||||||
httpMethod: 'GET',
|
|
||||||
responseMode: 'onReceived',
|
|
||||||
responseData: '',
|
|
||||||
path: '={{ $nodeId }}',
|
|
||||||
restartWebhook: true,
|
|
||||||
isFullPath: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'default',
|
|
||||||
httpMethod: 'POST',
|
|
||||||
responseMode: 'onReceived',
|
|
||||||
responseData: '',
|
|
||||||
path: '={{ $nodeId }}',
|
|
||||||
restartWebhook: true,
|
|
||||||
isFullPath: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
properties: [
|
properties: [
|
||||||
{
|
{
|
||||||
displayName: 'Authentication',
|
displayName: 'Authentication',
|
||||||
|
|
|
@ -9,6 +9,7 @@ import * as folder from './folder';
|
||||||
import * as folderMessage from './folderMessage';
|
import * as folderMessage from './folderMessage';
|
||||||
import * as message from './message';
|
import * as message from './message';
|
||||||
import * as messageAttachment from './messageAttachment';
|
import * as messageAttachment from './messageAttachment';
|
||||||
|
import { sendAndWaitWebhooks } from '../../../../../utils/sendAndWait/descriptions';
|
||||||
|
|
||||||
export const description: INodeTypeDescription = {
|
export const description: INodeTypeDescription = {
|
||||||
displayName: 'Microsoft Outlook',
|
displayName: 'Microsoft Outlook',
|
||||||
|
@ -30,26 +31,7 @@ export const description: INodeTypeDescription = {
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
webhooks: [
|
webhooks: sendAndWaitWebhooks,
|
||||||
{
|
|
||||||
name: 'default',
|
|
||||||
httpMethod: 'GET',
|
|
||||||
responseMode: 'onReceived',
|
|
||||||
responseData: '',
|
|
||||||
path: '={{ $nodeId }}',
|
|
||||||
restartWebhook: true,
|
|
||||||
isFullPath: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'default',
|
|
||||||
httpMethod: 'POST',
|
|
||||||
responseMode: 'onReceived',
|
|
||||||
responseData: '',
|
|
||||||
path: '={{ $nodeId }}',
|
|
||||||
restartWebhook: true,
|
|
||||||
isFullPath: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
properties: [
|
properties: [
|
||||||
{
|
{
|
||||||
displayName: 'Resource',
|
displayName: 'Resource',
|
||||||
|
|
|
@ -41,6 +41,7 @@ import { reactionFields, reactionOperations } from './ReactionDescription';
|
||||||
import { starFields, starOperations } from './StarDescription';
|
import { starFields, starOperations } from './StarDescription';
|
||||||
import { userFields, userOperations } from './UserDescription';
|
import { userFields, userOperations } from './UserDescription';
|
||||||
import { userGroupFields, userGroupOperations } from './UserGroupDescription';
|
import { userGroupFields, userGroupOperations } from './UserGroupDescription';
|
||||||
|
import { sendAndWaitWebhooks } from '../../../utils/sendAndWait/descriptions';
|
||||||
import {
|
import {
|
||||||
configureWaitTillDate,
|
configureWaitTillDate,
|
||||||
getSendAndWaitProperties,
|
getSendAndWaitProperties,
|
||||||
|
@ -80,26 +81,7 @@ export class SlackV2 implements INodeType {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
webhooks: [
|
webhooks: sendAndWaitWebhooks,
|
||||||
{
|
|
||||||
name: 'default',
|
|
||||||
httpMethod: 'GET',
|
|
||||||
responseMode: 'onReceived',
|
|
||||||
responseData: '',
|
|
||||||
path: '={{ $nodeId }}',
|
|
||||||
restartWebhook: true,
|
|
||||||
isFullPath: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'default',
|
|
||||||
httpMethod: 'POST',
|
|
||||||
responseMode: 'onReceived',
|
|
||||||
responseData: '',
|
|
||||||
path: '={{ $nodeId }}',
|
|
||||||
restartWebhook: true,
|
|
||||||
isFullPath: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
properties: [
|
properties: [
|
||||||
{
|
{
|
||||||
displayName: 'Authentication',
|
displayName: 'Authentication',
|
||||||
|
|
|
@ -10,6 +10,8 @@ import type {
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
import { NodeApiError } from 'n8n-workflow';
|
import { NodeApiError } from 'n8n-workflow';
|
||||||
|
|
||||||
|
import { getSendAndWaitConfig } from '../../utils/sendAndWait/utils';
|
||||||
|
|
||||||
// Interface in n8n
|
// Interface in n8n
|
||||||
export interface IMarkupKeyboard {
|
export interface IMarkupKeyboard {
|
||||||
rows?: IMarkupKeyboardRow[];
|
rows?: IMarkupKeyboardRow[];
|
||||||
|
@ -252,3 +254,36 @@ export function getSecretToken(this: IHookFunctions | IWebhookFunctions) {
|
||||||
const secret_token = `${this.getWorkflow().id}_${this.getNode().id}`;
|
const secret_token = `${this.getWorkflow().id}_${this.getNode().id}`;
|
||||||
return secret_token.replace(/[^a-zA-Z0-9\_\-]+/g, '');
|
return secret_token.replace(/[^a-zA-Z0-9\_\-]+/g, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function createSendAndWaitMessageBody(context: IExecuteFunctions) {
|
||||||
|
const chat_id = context.getNodeParameter('chatId', 0) as string;
|
||||||
|
|
||||||
|
const config = getSendAndWaitConfig(context);
|
||||||
|
let text = config.message;
|
||||||
|
|
||||||
|
const instanceId = context.getInstanceId();
|
||||||
|
const attributionText = 'This message was sent automatically with ';
|
||||||
|
const link = `https://n8n.io/?utm_source=n8n-internal&utm_medium=powered_by&utm_campaign=${encodeURIComponent(
|
||||||
|
'n8n-nodes-base.telegram',
|
||||||
|
)}${instanceId ? '_' + instanceId : ''}`;
|
||||||
|
text = `${text}\n\n_${attributionText}_[n8n](${link})`;
|
||||||
|
|
||||||
|
const body = {
|
||||||
|
chat_id,
|
||||||
|
text,
|
||||||
|
disable_web_page_preview: true,
|
||||||
|
parse_mode: 'Markdown',
|
||||||
|
reply_markup: {
|
||||||
|
inline_keyboard: [
|
||||||
|
config.options.map((option) => {
|
||||||
|
return {
|
||||||
|
text: option.label,
|
||||||
|
url: `${config.url}?approved=${option.value}`,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
|
@ -6,11 +6,27 @@ import type {
|
||||||
INodeTypeDescription,
|
INodeTypeDescription,
|
||||||
IHttpRequestMethods,
|
IHttpRequestMethods,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
import { BINARY_ENCODING, NodeConnectionType, NodeOperationError } from 'n8n-workflow';
|
import {
|
||||||
|
BINARY_ENCODING,
|
||||||
|
SEND_AND_WAIT_OPERATION,
|
||||||
|
NodeConnectionType,
|
||||||
|
NodeOperationError,
|
||||||
|
} from 'n8n-workflow';
|
||||||
import type { Readable } from 'stream';
|
import type { Readable } from 'stream';
|
||||||
|
|
||||||
import { addAdditionalFields, apiRequest, getPropertyName } from './GenericFunctions';
|
import {
|
||||||
|
addAdditionalFields,
|
||||||
|
apiRequest,
|
||||||
|
createSendAndWaitMessageBody,
|
||||||
|
getPropertyName,
|
||||||
|
} from './GenericFunctions';
|
||||||
import { appendAttributionOption } from '../../utils/descriptions';
|
import { appendAttributionOption } from '../../utils/descriptions';
|
||||||
|
import { sendAndWaitWebhooks } from '../../utils/sendAndWait/descriptions';
|
||||||
|
import {
|
||||||
|
configureWaitTillDate,
|
||||||
|
getSendAndWaitProperties,
|
||||||
|
sendAndWaitWebhook,
|
||||||
|
} from '../../utils/sendAndWait/utils';
|
||||||
|
|
||||||
export class Telegram implements INodeType {
|
export class Telegram implements INodeType {
|
||||||
description: INodeTypeDescription = {
|
description: INodeTypeDescription = {
|
||||||
|
@ -33,6 +49,7 @@ export class Telegram implements INodeType {
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
webhooks: sendAndWaitWebhooks,
|
||||||
properties: [
|
properties: [
|
||||||
{
|
{
|
||||||
displayName: 'Resource',
|
displayName: 'Resource',
|
||||||
|
@ -263,6 +280,12 @@ export class Telegram implements INodeType {
|
||||||
description: 'Send a text message',
|
description: 'Send a text message',
|
||||||
action: 'Send a text message',
|
action: 'Send a text message',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'Send and Wait for Response',
|
||||||
|
value: SEND_AND_WAIT_OPERATION,
|
||||||
|
description: 'Send a message and wait for response',
|
||||||
|
action: 'Send message and wait for response',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'Send Photo',
|
name: 'Send Photo',
|
||||||
value: 'sendPhoto',
|
value: 'sendPhoto',
|
||||||
|
@ -1735,9 +1758,31 @@ export class Telegram implements INodeType {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
...getSendAndWaitProperties(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
displayName: 'Chat ID',
|
||||||
|
name: 'chatId',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
required: true,
|
||||||
|
description:
|
||||||
|
'Unique identifier for the target chat or username of the target channel (in the format @channelusername). To find your chat ID ask @get_id_bot.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'message',
|
||||||
|
undefined,
|
||||||
|
{
|
||||||
|
noButtonStyle: true,
|
||||||
|
defaultApproveLabel: '✅ Approve',
|
||||||
|
defaultDisapproveLabel: '❌ Decline',
|
||||||
|
},
|
||||||
|
).filter((p) => p.name !== 'subject'),
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
webhook = sendAndWaitWebhook;
|
||||||
|
|
||||||
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
||||||
const items = this.getInputData();
|
const items = this.getInputData();
|
||||||
const returnData: INodeExecutionData[] = [];
|
const returnData: INodeExecutionData[] = [];
|
||||||
|
@ -1757,6 +1802,17 @@ export class Telegram implements INodeType {
|
||||||
const nodeVersion = this.getNode().typeVersion;
|
const nodeVersion = this.getNode().typeVersion;
|
||||||
const instanceId = this.getInstanceId();
|
const instanceId = this.getInstanceId();
|
||||||
|
|
||||||
|
if (resource === 'message' && operation === SEND_AND_WAIT_OPERATION) {
|
||||||
|
body = createSendAndWaitMessageBody(this);
|
||||||
|
|
||||||
|
await apiRequest.call(this, 'POST', 'sendMessage', body);
|
||||||
|
|
||||||
|
const waitTill = configureWaitTillDate(this);
|
||||||
|
|
||||||
|
await this.putExecutionToWait(waitTill);
|
||||||
|
return [this.getInputData()];
|
||||||
|
}
|
||||||
|
|
||||||
for (let i = 0; i < items.length; i++) {
|
for (let i = 0; i < items.length; i++) {
|
||||||
try {
|
try {
|
||||||
// Reset all values
|
// Reset all values
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
import type { MockProxy } from 'jest-mock-extended';
|
||||||
|
import { mock } from 'jest-mock-extended';
|
||||||
|
import { type INode, SEND_AND_WAIT_OPERATION, type IExecuteFunctions } from 'n8n-workflow';
|
||||||
|
|
||||||
|
import * as genericFunctions from '../../GenericFunctions';
|
||||||
|
import { Telegram } from '../../Telegram.node';
|
||||||
|
|
||||||
|
jest.mock('../../GenericFunctions', () => {
|
||||||
|
const originalModule = jest.requireActual('../../GenericFunctions');
|
||||||
|
return {
|
||||||
|
...originalModule,
|
||||||
|
apiRequest: jest.fn(),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Test Telegram, message => sendAndWait', () => {
|
||||||
|
let telegram: Telegram;
|
||||||
|
let mockExecuteFunctions: MockProxy<IExecuteFunctions>;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
telegram = new Telegram();
|
||||||
|
mockExecuteFunctions = mock<IExecuteFunctions>();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
jest.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should send message and put execution to wait', async () => {
|
||||||
|
const items = [{ json: { data: 'test' } }];
|
||||||
|
//node
|
||||||
|
mockExecuteFunctions.getInputData.mockReturnValue(items);
|
||||||
|
mockExecuteFunctions.getNodeParameter.mockReturnValueOnce(SEND_AND_WAIT_OPERATION);
|
||||||
|
mockExecuteFunctions.getNodeParameter.mockReturnValueOnce('message');
|
||||||
|
mockExecuteFunctions.getNodeParameter.mockReturnValueOnce(false);
|
||||||
|
mockExecuteFunctions.getNode.mockReturnValue(mock<INode>());
|
||||||
|
mockExecuteFunctions.getInstanceId.mockReturnValue('instanceId');
|
||||||
|
|
||||||
|
//createSendAndWaitMessageBody
|
||||||
|
mockExecuteFunctions.getNodeParameter.mockReturnValueOnce('chatID');
|
||||||
|
|
||||||
|
//getSendAndWaitConfig
|
||||||
|
mockExecuteFunctions.getNodeParameter.mockReturnValueOnce('my message');
|
||||||
|
mockExecuteFunctions.getNodeParameter.mockReturnValueOnce('my subject');
|
||||||
|
mockExecuteFunctions.evaluateExpression.mockReturnValueOnce('http://localhost/waiting-webhook');
|
||||||
|
mockExecuteFunctions.evaluateExpression.mockReturnValueOnce('nodeID');
|
||||||
|
mockExecuteFunctions.getNodeParameter.mockReturnValueOnce({});
|
||||||
|
mockExecuteFunctions.getNodeParameter.mockReturnValueOnce('approval');
|
||||||
|
|
||||||
|
// configureWaitTillDate
|
||||||
|
mockExecuteFunctions.getNodeParameter.mockReturnValueOnce({}); //options.limitWaitTime.values
|
||||||
|
|
||||||
|
const result = await telegram.execute.call(mockExecuteFunctions);
|
||||||
|
|
||||||
|
expect(result).toEqual([items]);
|
||||||
|
expect(genericFunctions.apiRequest).toHaveBeenCalledTimes(1);
|
||||||
|
expect(mockExecuteFunctions.putExecutionToWait).toHaveBeenCalledTimes(1);
|
||||||
|
|
||||||
|
expect(genericFunctions.apiRequest).toHaveBeenCalledWith('POST', 'sendMessage', {
|
||||||
|
chat_id: 'chatID',
|
||||||
|
disable_web_page_preview: true,
|
||||||
|
parse_mode: 'Markdown',
|
||||||
|
reply_markup: {
|
||||||
|
inline_keyboard: [
|
||||||
|
[{ text: 'Approve', url: 'http://localhost/waiting-webhook/nodeID?approved=true' }],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
text: 'my message\n\n_This message was sent automatically with _[n8n](https://n8n.io/?utm_source=n8n-internal&utm_medium=powered_by&utm_campaign=n8n-nodes-base.telegram_instanceId)',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
22
packages/nodes-base/utils/sendAndWait/descriptions.ts
Normal file
22
packages/nodes-base/utils/sendAndWait/descriptions.ts
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
import type { IWebhookDescription } from 'n8n-workflow';
|
||||||
|
|
||||||
|
export const sendAndWaitWebhooks: IWebhookDescription[] = [
|
||||||
|
{
|
||||||
|
name: 'default',
|
||||||
|
httpMethod: 'GET',
|
||||||
|
responseMode: 'onReceived',
|
||||||
|
responseData: '',
|
||||||
|
path: '={{ $nodeId }}',
|
||||||
|
restartWebhook: true,
|
||||||
|
isFullPath: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'default',
|
||||||
|
httpMethod: 'POST',
|
||||||
|
responseMode: 'onReceived',
|
||||||
|
responseData: '',
|
||||||
|
path: '={{ $nodeId }}',
|
||||||
|
restartWebhook: true,
|
||||||
|
isFullPath: true,
|
||||||
|
},
|
||||||
|
];
|
|
@ -137,6 +137,11 @@ export function getSendAndWaitProperties(
|
||||||
targetProperties: INodeProperties[],
|
targetProperties: INodeProperties[],
|
||||||
resource: string = 'message',
|
resource: string = 'message',
|
||||||
additionalProperties: INodeProperties[] = [],
|
additionalProperties: INodeProperties[] = [],
|
||||||
|
options?: {
|
||||||
|
noButtonStyle?: boolean;
|
||||||
|
defaultApproveLabel?: string;
|
||||||
|
defaultDisapproveLabel?: string;
|
||||||
|
},
|
||||||
) {
|
) {
|
||||||
const buttonStyle: INodeProperties = {
|
const buttonStyle: INodeProperties = {
|
||||||
displayName: 'Button Style',
|
displayName: 'Button Style',
|
||||||
|
@ -154,6 +159,77 @@ export function getSendAndWaitProperties(
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
const approvalOptionsValues = [
|
||||||
|
{
|
||||||
|
displayName: 'Type of Approval',
|
||||||
|
name: 'approvalType',
|
||||||
|
type: 'options',
|
||||||
|
placeholder: 'Add option',
|
||||||
|
default: 'single',
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: 'Approve Only',
|
||||||
|
value: 'single',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Approve and Disapprove',
|
||||||
|
value: 'double',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Approve Button Label',
|
||||||
|
name: 'approveLabel',
|
||||||
|
type: 'string',
|
||||||
|
default: options?.defaultApproveLabel || 'Approve',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
approvalType: ['single', 'double'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
...[
|
||||||
|
options?.noButtonStyle
|
||||||
|
? ({} as INodeProperties)
|
||||||
|
: {
|
||||||
|
...buttonStyle,
|
||||||
|
displayName: 'Approve Button Style',
|
||||||
|
name: 'buttonApprovalStyle',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
approvalType: ['single', 'double'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
{
|
||||||
|
displayName: 'Disapprove Button Label',
|
||||||
|
name: 'disapproveLabel',
|
||||||
|
type: 'string',
|
||||||
|
default: options?.defaultDisapproveLabel || 'Decline',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
approvalType: ['double'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
...[
|
||||||
|
options?.noButtonStyle
|
||||||
|
? ({} as INodeProperties)
|
||||||
|
: {
|
||||||
|
...buttonStyle,
|
||||||
|
displayName: 'Disapprove Button Style',
|
||||||
|
name: 'buttonDisapprovalStyle',
|
||||||
|
default: 'secondary',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
approvalType: ['double'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
].filter((p) => Object.keys(p).length) as INodeProperties[];
|
||||||
|
|
||||||
const sendAndWait: INodeProperties[] = [
|
const sendAndWait: INodeProperties[] = [
|
||||||
...targetProperties,
|
...targetProperties,
|
||||||
{
|
{
|
||||||
|
@ -216,68 +292,7 @@ export function getSendAndWaitProperties(
|
||||||
{
|
{
|
||||||
displayName: 'Values',
|
displayName: 'Values',
|
||||||
name: 'values',
|
name: 'values',
|
||||||
values: [
|
values: approvalOptionsValues,
|
||||||
{
|
|
||||||
displayName: 'Type of Approval',
|
|
||||||
name: 'approvalType',
|
|
||||||
type: 'options',
|
|
||||||
placeholder: 'Add option',
|
|
||||||
default: 'single',
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
name: 'Approve Only',
|
|
||||||
value: 'single',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Approve and Disapprove',
|
|
||||||
value: 'double',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
displayName: 'Approve Button Label',
|
|
||||||
name: 'approveLabel',
|
|
||||||
type: 'string',
|
|
||||||
default: 'Approve',
|
|
||||||
displayOptions: {
|
|
||||||
show: {
|
|
||||||
approvalType: ['single', 'double'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
...buttonStyle,
|
|
||||||
displayName: 'Approve Button Style',
|
|
||||||
name: 'buttonApprovalStyle',
|
|
||||||
displayOptions: {
|
|
||||||
show: {
|
|
||||||
approvalType: ['single', 'double'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
displayName: 'Disapprove Button Label',
|
|
||||||
name: 'disapproveLabel',
|
|
||||||
type: 'string',
|
|
||||||
default: 'Decline',
|
|
||||||
displayOptions: {
|
|
||||||
show: {
|
|
||||||
approvalType: ['double'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
...buttonStyle,
|
|
||||||
displayName: 'Disapprove Button Style',
|
|
||||||
name: 'buttonDisapprovalStyle',
|
|
||||||
default: 'secondary',
|
|
||||||
displayOptions: {
|
|
||||||
show: {
|
|
||||||
approvalType: ['double'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
displayOptions: {
|
displayOptions: {
|
||||||
|
|
Loading…
Reference in a new issue