🔀 Merge branch 'feature/extended-zendesk' of https://github.com/RicardoE105/n8n into RicardoE105-feature/extended-zendesk

This commit is contained in:
Jan Oberhauser 2020-04-09 00:18:35 +02:00
commit f5d52a50cb
7 changed files with 228 additions and 37 deletions

View file

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

View file

@ -1,11 +1,17 @@
import { OptionsWithUri } from 'request';
import {
OptionsWithUri,
} from 'request';
import {
IExecuteFunctions,
IExecuteSingleFunctions,
IHookFunctions,
ILoadOptionsFunctions,
} 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
const credentials = this.getCredentials('zendeskApi');
@ -28,7 +34,8 @@ export async function zendeskApiRequest(this: IHookFunctions | IExecuteFunctions
try {
return await this.helpers.request!(options);
} catch (err) {
throw new Error(err);
const errorMessage = err.response.body.description || err.response.body;
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 = [
{
@ -70,6 +72,23 @@ export const ticketFields = [
required: true,
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',
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'>Details</a>`,
},
/* -------------------------------------------------------------------------- */
/* ticket:update */
/* -------------------------------------------------------------------------- */
@ -205,6 +248,23 @@ export const ticketFields = [
},
description: 'Ticket ID',
},
{
displayName: 'JSON Parameters',
name: 'jsonParameters',
type: 'boolean',
default: false,
description: '',
displayOptions: {
show: {
resource: [
'ticket'
],
operation: [
'update',
],
},
},
},
{
displayName: 'Update Fields',
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 */
/* -------------------------------------------------------------------------- */

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 {
subject?: string;
comment?: IComment;
@ -7,8 +15,5 @@ export interface ITicket {
tags?: string[];
status?: string;
recipient?: string;
}
export interface IComment {
body?: string;
custom_fields?: IDataObject[];
}

View file

@ -1,6 +1,7 @@
import {
IExecuteFunctions,
} from 'n8n-core';
import {
IDataObject,
INodeTypeDescription,
@ -9,14 +10,22 @@ import {
ILoadOptionsFunctions,
INodePropertyOptions,
} from 'n8n-workflow';
import {
zendeskApiRequest,
zendeskApiRequestAllItems,
} from './GenericFunctions';
import {
ticketFields,
ticketOperations
} from './TicketDescription';
import {
ticketFieldFields,
ticketFieldOperations
} from './TicketFieldDescription';
import {
ITicket,
IComment,
@ -54,12 +63,21 @@ export class Zendesk implements INodeType {
value: 'ticket',
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',
description: 'Resource to consume.',
},
// TICKET
...ticketOperations,
...ticketFields,
// TICKET FIELDS
...ticketFieldOperations,
...ticketFieldFields,
],
};
@ -112,6 +130,7 @@ export class Zendesk implements INodeType {
//https://developer.zendesk.com/rest_api/docs/support/tickets
if (operation === 'create') {
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 comment: IComment = {
body: description,
@ -140,16 +159,22 @@ export class Zendesk implements INodeType {
if (additionalFields.tags) {
body.tags = additionalFields.tags as string[];
}
try {
responseData = await zendeskApiRequest.call(this, 'POST', '/tickets', { ticket: body });
responseData = responseData.ticket;
} catch (err) {
throw new Error(`Zendesk Error: ${err}`);
if (jsonParameters) {
const customFieldsJson = this.getNodeParameter('customFieldsJson', i) as string;
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 = responseData.ticket;
}
//https://developer.zendesk.com/rest_api/docs/support/tickets#update-ticket
if (operation === 'update') {
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 body: ITicket = {};
if (updateFields.type) {
@ -173,22 +198,23 @@ export class Zendesk implements INodeType {
if (updateFields.tags) {
body.tags = updateFields.tags as string[];
}
try {
responseData = await zendeskApiRequest.call(this, 'PUT', `/tickets/${ticketId}`, { ticket: body });
responseData = responseData.ticket;
} catch (err) {
throw new Error(`Zendesk Error: ${err}`);
if (jsonParameters) {
const customFieldsJson = this.getNodeParameter('customFieldsJson', i) as string;
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 = responseData.ticket;
}
//https://developer.zendesk.com/rest_api/docs/support/tickets#show-ticket
if (operation === 'get') {
const ticketId = this.getNodeParameter('id', i) as string;
try {
responseData = await zendeskApiRequest.call(this, 'GET', `/tickets/${ticketId}`, {});
responseData = responseData.ticket;
} catch (err) {
throw new Error(`Zendesk Error: ${err}`);
}
responseData = await zendeskApiRequest.call(this, 'GET', `/tickets/${ticketId}`, {});
responseData = responseData.ticket;
}
//https://developer.zendesk.com/rest_api/docs/support/search#list-search-results
if (operation === 'getAll') {
@ -204,17 +230,13 @@ export class Zendesk implements INodeType {
if (options.sortOrder) {
qs.sort_order = options.sortOrder;
}
try {
if (returnAll) {
responseData = await zendeskApiRequestAllItems.call(this, 'results', 'GET', `/search`, {}, qs);
} else {
const limit = this.getNodeParameter('limit', i) as number;
qs.per_page = limit;
responseData = await zendeskApiRequest.call(this, 'GET', `/search`, {}, qs);
responseData = responseData.results;
}
} catch (err) {
throw new Error(`Zendesk Error: ${err}`);
if (returnAll) {
responseData = await zendeskApiRequestAllItems.call(this, 'results', 'GET', `/search`, {}, qs);
} else {
const limit = this.getNodeParameter('limit', i) as number;
qs.per_page = limit;
responseData = await zendeskApiRequest.call(this, 'GET', `/search`, {}, qs);
responseData = responseData.results;
}
}
//https://developer.zendesk.com/rest_api/docs/support/tickets#delete-ticket
@ -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)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
} else {

View file

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