🔀 Merge branch 'RicardoE105-feature/extended-zendesk'

This commit is contained in:
Jan Oberhauser 2020-04-09 00:33:16 +02:00
commit 6f87895e00
7 changed files with 235 additions and 37 deletions

View file

@ -1,4 +1,6 @@
import { INodeProperties } from 'n8n-workflow'; import {
INodeProperties,
} from 'n8n-workflow';
export const conditionFields = [ export const conditionFields = [
{ {

View file

@ -1,11 +1,17 @@
import { OptionsWithUri } from 'request'; import {
OptionsWithUri,
} from 'request';
import { import {
IExecuteFunctions, IExecuteFunctions,
IExecuteSingleFunctions, IExecuteSingleFunctions,
IHookFunctions, IHookFunctions,
ILoadOptionsFunctions, ILoadOptionsFunctions,
} from 'n8n-core'; } from 'n8n-core';
import { IDataObject } from 'n8n-workflow';
import {
IDataObject,
} from 'n8n-workflow';
export async function zendeskApiRequest(this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, method: string, resource: string, body: any = {}, qs: IDataObject = {}, uri?: string, option: IDataObject = {}): Promise<any> { // tslint:disable-line:no-any export async function zendeskApiRequest(this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, method: string, resource: string, body: any = {}, qs: IDataObject = {}, uri?: string, option: IDataObject = {}): Promise<any> { // tslint:disable-line:no-any
const credentials = this.getCredentials('zendeskApi'); const credentials = this.getCredentials('zendeskApi');
@ -28,7 +34,15 @@ export async function zendeskApiRequest(this: IHookFunctions | IExecuteFunctions
try { try {
return await this.helpers.request!(options); return await this.helpers.request!(options);
} catch (err) { } catch (err) {
throw new Error(err); let errorMessage = err.message;
if (err.response && err.response.body && err.response.body.error) {
errorMessage = err.response.body.error;
if (typeof err.response.body.error !== 'string') {
errorMessage = JSON.stringify(errorMessage);
}
}
throw new Error(`Zendesk error response [${err.statusCode}]: ${errorMessage}`);
} }
} }

View file

@ -1,4 +1,6 @@
import { INodeProperties } from 'n8n-workflow'; import {
INodeProperties,
} from 'n8n-workflow';
export const ticketOperations = [ export const ticketOperations = [
{ {
@ -70,6 +72,23 @@ export const ticketFields = [
required: true, required: true,
description: 'The first comment on the ticket', description: 'The first comment on the ticket',
}, },
{
displayName: 'JSON Parameters',
name: 'jsonParameters',
type: 'boolean',
default: false,
description: '',
displayOptions: {
show: {
resource: [
'ticket'
],
operation: [
'create',
],
},
},
},
{ {
displayName: 'Additional Fields', displayName: 'Additional Fields',
name: 'additionalFields', name: 'additionalFields',
@ -184,6 +203,30 @@ export const ticketFields = [
} }
], ],
}, },
{
displayName: ' Custom Fields',
name: 'customFieldsJson',
type: 'json',
typeOptions: {
alwaysOpenEditWindow: true,
},
default: '',
displayOptions: {
show: {
resource: [
'ticket',
],
operation: [
'create',
],
jsonParameters: [
true,
],
},
},
required: true,
description: `Array of customs fields <a href="https://developer.zendesk.com/rest_api/docs/support/tickets#setting-custom-field-values" target="_blank">Details</a>`,
},
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
/* ticket:update */ /* ticket:update */
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
@ -205,6 +248,23 @@ export const ticketFields = [
}, },
description: 'Ticket ID', description: 'Ticket ID',
}, },
{
displayName: 'JSON Parameters',
name: 'jsonParameters',
type: 'boolean',
default: false,
description: '',
displayOptions: {
show: {
resource: [
'ticket'
],
operation: [
'update',
],
},
},
},
{ {
displayName: 'Update Fields', displayName: 'Update Fields',
name: 'updateFields', name: 'updateFields',
@ -319,6 +379,30 @@ export const ticketFields = [
} }
], ],
}, },
{
displayName: ' Custom Fields',
name: 'customFieldsJson',
type: 'json',
typeOptions: {
alwaysOpenEditWindow: true,
},
default: '',
displayOptions: {
show: {
resource: [
'ticket',
],
operation: [
'update',
],
jsonParameters: [
true,
],
},
},
required: true,
description: `Array of customs fields <a href='https://developer.zendesk.com/rest_api/docs/support/tickets#setting-custom-field-values'>Details</a>`,
},
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
/* ticket:get */ /* ticket:get */
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */

View file

@ -0,0 +1,57 @@
import {
INodeProperties,
} from 'n8n-workflow';
export const ticketFieldOperations = [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
displayOptions: {
show: {
resource: [
'ticketField',
],
},
},
options: [
{
name: 'Get',
value: 'get',
description: 'Get a ticket field',
},
{
name: 'Get All',
value: 'getAll',
description: 'Get all system and custom ticket fields',
},
],
default: 'get',
description: 'The operation to perform.',
},
] as INodeProperties[];
export const ticketFieldFields = [
/* -------------------------------------------------------------------------- */
/* ticketField:get */
/* -------------------------------------------------------------------------- */
{
displayName: 'Ticket Field ID',
name: 'ticketFieldId',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
resource: [
'ticketField',
],
operation: [
'get',
],
},
},
description: 'ticketField ID',
},
] as INodeProperties[];

View file

@ -1,3 +1,11 @@
import {
IDataObject,
} from 'n8n-workflow';
export interface IComment {
body?: string;
}
export interface ITicket { export interface ITicket {
subject?: string; subject?: string;
comment?: IComment; comment?: IComment;
@ -7,8 +15,5 @@ export interface ITicket {
tags?: string[]; tags?: string[];
status?: string; status?: string;
recipient?: string; recipient?: string;
} custom_fields?: IDataObject[];
export interface IComment {
body?: string;
} }

View file

@ -1,6 +1,7 @@
import { import {
IExecuteFunctions, IExecuteFunctions,
} from 'n8n-core'; } from 'n8n-core';
import { import {
IDataObject, IDataObject,
INodeTypeDescription, INodeTypeDescription,
@ -9,14 +10,22 @@ import {
ILoadOptionsFunctions, ILoadOptionsFunctions,
INodePropertyOptions, INodePropertyOptions,
} from 'n8n-workflow'; } from 'n8n-workflow';
import { import {
zendeskApiRequest, zendeskApiRequest,
zendeskApiRequestAllItems, zendeskApiRequestAllItems,
} from './GenericFunctions'; } from './GenericFunctions';
import { import {
ticketFields, ticketFields,
ticketOperations ticketOperations
} from './TicketDescription'; } from './TicketDescription';
import {
ticketFieldFields,
ticketFieldOperations
} from './TicketFieldDescription';
import { import {
ITicket, ITicket,
IComment, IComment,
@ -54,12 +63,21 @@ export class Zendesk implements INodeType {
value: 'ticket', value: 'ticket',
description: 'Tickets are the means through which your end users (customers) communicate with agents in Zendesk Support.', description: 'Tickets are the means through which your end users (customers) communicate with agents in Zendesk Support.',
}, },
{
name: 'Ticket Field',
value: 'ticketField',
description: 'Manage system and custom ticket fields',
},
], ],
default: 'ticket', default: 'ticket',
description: 'Resource to consume.', description: 'Resource to consume.',
}, },
// TICKET
...ticketOperations, ...ticketOperations,
...ticketFields, ...ticketFields,
// TICKET FIELDS
...ticketFieldOperations,
...ticketFieldFields,
], ],
}; };
@ -112,6 +130,7 @@ export class Zendesk implements INodeType {
//https://developer.zendesk.com/rest_api/docs/support/tickets //https://developer.zendesk.com/rest_api/docs/support/tickets
if (operation === 'create') { if (operation === 'create') {
const description = this.getNodeParameter('description', i) as string; const description = this.getNodeParameter('description', i) as string;
const jsonParameters = this.getNodeParameter('jsonParameters', i) as boolean;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const comment: IComment = { const comment: IComment = {
body: description, body: description,
@ -140,16 +159,22 @@ export class Zendesk implements INodeType {
if (additionalFields.tags) { if (additionalFields.tags) {
body.tags = additionalFields.tags as string[]; body.tags = additionalFields.tags as string[];
} }
if (jsonParameters) {
const customFieldsJson = this.getNodeParameter('customFieldsJson', i) as string;
try { try {
JSON.parse(customFieldsJson);
} catch(err) {
throw new Error('Custom fields must be a valid JSON');
}
body.custom_fields = JSON.parse(customFieldsJson);
}
responseData = await zendeskApiRequest.call(this, 'POST', '/tickets', { ticket: body }); responseData = await zendeskApiRequest.call(this, 'POST', '/tickets', { ticket: body });
responseData = responseData.ticket; responseData = responseData.ticket;
} catch (err) {
throw new Error(`Zendesk Error: ${err}`);
}
} }
//https://developer.zendesk.com/rest_api/docs/support/tickets#update-ticket //https://developer.zendesk.com/rest_api/docs/support/tickets#update-ticket
if (operation === 'update') { if (operation === 'update') {
const ticketId = this.getNodeParameter('id', i) as string; const ticketId = this.getNodeParameter('id', i) as string;
const jsonParameters = this.getNodeParameter('jsonParameters', i) as boolean;
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject; const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
const body: ITicket = {}; const body: ITicket = {};
if (updateFields.type) { if (updateFields.type) {
@ -173,22 +198,23 @@ export class Zendesk implements INodeType {
if (updateFields.tags) { if (updateFields.tags) {
body.tags = updateFields.tags as string[]; body.tags = updateFields.tags as string[];
} }
if (jsonParameters) {
const customFieldsJson = this.getNodeParameter('customFieldsJson', i) as string;
try { try {
JSON.parse(customFieldsJson);
} catch(err) {
throw new Error('Custom fields must be a valid JSON');
}
body.custom_fields = JSON.parse(customFieldsJson);
}
responseData = await zendeskApiRequest.call(this, 'PUT', `/tickets/${ticketId}`, { ticket: body }); responseData = await zendeskApiRequest.call(this, 'PUT', `/tickets/${ticketId}`, { ticket: body });
responseData = responseData.ticket; responseData = responseData.ticket;
} catch (err) {
throw new Error(`Zendesk Error: ${err}`);
}
} }
//https://developer.zendesk.com/rest_api/docs/support/tickets#show-ticket //https://developer.zendesk.com/rest_api/docs/support/tickets#show-ticket
if (operation === 'get') { if (operation === 'get') {
const ticketId = this.getNodeParameter('id', i) as string; const ticketId = this.getNodeParameter('id', i) as string;
try {
responseData = await zendeskApiRequest.call(this, 'GET', `/tickets/${ticketId}`, {}); responseData = await zendeskApiRequest.call(this, 'GET', `/tickets/${ticketId}`, {});
responseData = responseData.ticket; responseData = responseData.ticket;
} catch (err) {
throw new Error(`Zendesk Error: ${err}`);
}
} }
//https://developer.zendesk.com/rest_api/docs/support/search#list-search-results //https://developer.zendesk.com/rest_api/docs/support/search#list-search-results
if (operation === 'getAll') { if (operation === 'getAll') {
@ -204,7 +230,6 @@ export class Zendesk implements INodeType {
if (options.sortOrder) { if (options.sortOrder) {
qs.sort_order = options.sortOrder; qs.sort_order = options.sortOrder;
} }
try {
if (returnAll) { if (returnAll) {
responseData = await zendeskApiRequestAllItems.call(this, 'results', 'GET', `/search`, {}, qs); responseData = await zendeskApiRequestAllItems.call(this, 'results', 'GET', `/search`, {}, qs);
} else { } else {
@ -213,9 +238,6 @@ export class Zendesk implements INodeType {
responseData = await zendeskApiRequest.call(this, 'GET', `/search`, {}, qs); responseData = await zendeskApiRequest.call(this, 'GET', `/search`, {}, qs);
responseData = responseData.results; responseData = responseData.results;
} }
} catch (err) {
throw new Error(`Zendesk Error: ${err}`);
}
} }
//https://developer.zendesk.com/rest_api/docs/support/tickets#delete-ticket //https://developer.zendesk.com/rest_api/docs/support/tickets#delete-ticket
if (operation === 'delete') { if (operation === 'delete') {
@ -227,6 +249,20 @@ export class Zendesk implements INodeType {
} }
} }
} }
//https://developer.zendesk.com/rest_api/docs/support/ticket_fields
if (resource === 'ticketField') {
//https://developer.zendesk.com/rest_api/docs/support/tickets#show-ticket
if (operation === 'get') {
const ticketFieldId = this.getNodeParameter('ticketFieldId', i) as string;
responseData = await zendeskApiRequest.call(this, 'GET', `/ticket_fields/${ticketFieldId}`, {});
responseData = responseData.ticket_field;
}
//https://developer.zendesk.com/rest_api/docs/support/ticket_fields#list-ticket-fields
if (operation === 'getAll') {
responseData = await zendeskApiRequest.call(this, 'GET', '/ticket_fields', {}, qs);
responseData = responseData.ticket_fields;
}
}
if (Array.isArray(responseData)) { if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]); returnData.push.apply(returnData, responseData as IDataObject[]);
} else { } else {

View file

@ -21,7 +21,7 @@ import {
zendeskApiRequestAllItems, zendeskApiRequestAllItems,
} from './GenericFunctions'; } from './GenericFunctions';
import { import {
conditionFields conditionFields,
} from './ConditionDescription'; } from './ConditionDescription';
export class ZendeskTrigger implements INodeType { export class ZendeskTrigger implements INodeType {