mirror of
https://github.com/n8n-io/n8n.git
synced 2025-02-21 02:56:40 -08:00
✨ Add Kitemaker node (#1676)
* ⚡ Add Kitemaker node * ⚡ Require status ID for workItem:create * ✏️ Reword button text * ⚡ Add credentials file * ⚡ Implement pagination * ⚡ Improvements * ⚡ Remove not needed parameter Co-authored-by: ricardo <ricardoespinoza105@gmail.com> Co-authored-by: Jan Oberhauser <jan.oberhauser@gmail.com>
This commit is contained in:
parent
efd40ea7a6
commit
4cf8055224
18
packages/nodes-base/credentials/KitemakerApi.credentials.ts
Normal file
18
packages/nodes-base/credentials/KitemakerApi.credentials.ts
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
import {
|
||||||
|
ICredentialType,
|
||||||
|
NodePropertyTypes,
|
||||||
|
} from 'n8n-workflow';
|
||||||
|
|
||||||
|
export class KitemakerApi implements ICredentialType {
|
||||||
|
name = 'kitemakerApi';
|
||||||
|
displayName = 'Kitemaker API';
|
||||||
|
documentationUrl = 'kitemaker';
|
||||||
|
properties = [
|
||||||
|
{
|
||||||
|
displayName: 'Personal Access Token',
|
||||||
|
name: 'personalAccessToken',
|
||||||
|
type: 'string' as NodePropertyTypes,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
85
packages/nodes-base/nodes/Kitemaker/GenericFunctions.ts
Normal file
85
packages/nodes-base/nodes/Kitemaker/GenericFunctions.ts
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
import {
|
||||||
|
IExecuteFunctions,
|
||||||
|
ILoadOptionsFunctions,
|
||||||
|
} from 'n8n-core';
|
||||||
|
|
||||||
|
import {
|
||||||
|
IDataObject,
|
||||||
|
IHookFunctions,
|
||||||
|
NodeApiError,
|
||||||
|
} from 'n8n-workflow';
|
||||||
|
|
||||||
|
export async function kitemakerRequest(
|
||||||
|
this: IExecuteFunctions | ILoadOptionsFunctions | IHookFunctions,
|
||||||
|
body: IDataObject = {},
|
||||||
|
) {
|
||||||
|
const { personalAccessToken } = this.getCredentials('kitemakerApi') as { personalAccessToken: string };
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${personalAccessToken}`,
|
||||||
|
},
|
||||||
|
method: 'POST',
|
||||||
|
body,
|
||||||
|
uri: 'https://toil.kitemaker.co/developers/graphql',
|
||||||
|
json: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
const responseData = await this.helpers.request!.call(this, options);
|
||||||
|
|
||||||
|
if (responseData.errors) {
|
||||||
|
throw new NodeApiError(this.getNode(), responseData);
|
||||||
|
}
|
||||||
|
|
||||||
|
return responseData;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function kitemakerRequestAllItems(
|
||||||
|
this: IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions,
|
||||||
|
body: { query: string; variables: { [key: string]: string } },
|
||||||
|
) {
|
||||||
|
const resource = this.getNodeParameter('resource', 0) as 'space' | 'user' | 'workItem';
|
||||||
|
const [group, items] = getGroupAndItems(resource);
|
||||||
|
|
||||||
|
const returnAll = this.getNodeParameter('returnAll', 0, false) as boolean;
|
||||||
|
const limit = this.getNodeParameter('limit', 0, 0) as number;
|
||||||
|
|
||||||
|
const returnData: IDataObject[] = [];
|
||||||
|
let responseData;
|
||||||
|
|
||||||
|
do {
|
||||||
|
responseData = await kitemakerRequest.call(this, body);
|
||||||
|
body.variables.cursor = responseData.data[group].cursor;
|
||||||
|
returnData.push(...responseData.data[group][items]);
|
||||||
|
|
||||||
|
if (!returnAll && returnData.length > limit) {
|
||||||
|
return returnData.slice(0, limit);
|
||||||
|
}
|
||||||
|
|
||||||
|
} while (responseData.data[group].hasMore);
|
||||||
|
|
||||||
|
return returnData;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getGroupAndItems(resource: 'space' | 'user' | 'workItem') {
|
||||||
|
const map: { [key: string]: { [key: string]: string } } = {
|
||||||
|
space: { group: 'organization', items: 'spaces' },
|
||||||
|
user: { group: 'organization', items: 'users' },
|
||||||
|
workItem: { group: 'workItems', items: 'workItems' },
|
||||||
|
};
|
||||||
|
|
||||||
|
return [
|
||||||
|
map[resource]['group'],
|
||||||
|
map[resource]['items'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createLoadOptions(
|
||||||
|
resources: Array<{ name?: string; username?: string; title?: string; id: string }>,
|
||||||
|
): Array<{ name: string; value: string }> {
|
||||||
|
return resources.map(option => {
|
||||||
|
if (option.username) return ({ name: option.username, value: option.id });
|
||||||
|
if (option.title) return ({ name: option.title, value: option.id });
|
||||||
|
return ({ name: option.name ?? 'Unnamed', value: option.id });
|
||||||
|
});
|
||||||
|
}
|
321
packages/nodes-base/nodes/Kitemaker/Kitemaker.node.ts
Normal file
321
packages/nodes-base/nodes/Kitemaker/Kitemaker.node.ts
Normal file
|
@ -0,0 +1,321 @@
|
||||||
|
import {
|
||||||
|
IExecuteFunctions
|
||||||
|
} from 'n8n-core';
|
||||||
|
|
||||||
|
import {
|
||||||
|
IDataObject,
|
||||||
|
ILoadOptionsFunctions,
|
||||||
|
INodeExecutionData,
|
||||||
|
INodeType,
|
||||||
|
INodeTypeDescription
|
||||||
|
} from 'n8n-workflow';
|
||||||
|
|
||||||
|
import {
|
||||||
|
organizationOperations,
|
||||||
|
spaceFields,
|
||||||
|
spaceOperations,
|
||||||
|
userFields,
|
||||||
|
userOperations,
|
||||||
|
workItemFields,
|
||||||
|
workItemOperations,
|
||||||
|
} from './descriptions';
|
||||||
|
|
||||||
|
import {
|
||||||
|
createLoadOptions,
|
||||||
|
kitemakerRequest,
|
||||||
|
kitemakerRequestAllItems,
|
||||||
|
} from './GenericFunctions';
|
||||||
|
|
||||||
|
import {
|
||||||
|
getAllSpaces,
|
||||||
|
getAllUsers,
|
||||||
|
getAllWorkItems,
|
||||||
|
getLabels,
|
||||||
|
getOrganization,
|
||||||
|
getSpaces,
|
||||||
|
getStatuses,
|
||||||
|
getUsers,
|
||||||
|
getWorkItem,
|
||||||
|
getWorkItems,
|
||||||
|
} from './queries';
|
||||||
|
|
||||||
|
import {
|
||||||
|
createWorkItem,
|
||||||
|
editWorkItem,
|
||||||
|
} from './mutations';
|
||||||
|
|
||||||
|
export class Kitemaker implements INodeType {
|
||||||
|
description: INodeTypeDescription = {
|
||||||
|
displayName: 'Kitemaker',
|
||||||
|
name: 'kitemaker',
|
||||||
|
icon: 'file:kitemaker.svg',
|
||||||
|
group: ['input'],
|
||||||
|
version: 1,
|
||||||
|
subtitle: '={{$parameter["resource"] + ": " + $parameter["operation"]}}',
|
||||||
|
description: 'Consume the Kitemaker GraphQL API',
|
||||||
|
defaults: {
|
||||||
|
name: 'Kitemaker',
|
||||||
|
color: '#662482',
|
||||||
|
},
|
||||||
|
inputs: ['main'],
|
||||||
|
outputs: ['main'],
|
||||||
|
credentials: [
|
||||||
|
{
|
||||||
|
name: 'kitemakerApi',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
properties: [
|
||||||
|
{
|
||||||
|
displayName: 'Resource',
|
||||||
|
name: 'resource',
|
||||||
|
type: 'options',
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: 'Organization',
|
||||||
|
value: 'organization',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Space',
|
||||||
|
value: 'space',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'User',
|
||||||
|
value: 'user',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Work Item',
|
||||||
|
value: 'workItem',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
default: 'workItem',
|
||||||
|
required: true,
|
||||||
|
description: 'Resource to operate on.',
|
||||||
|
},
|
||||||
|
...organizationOperations,
|
||||||
|
...spaceOperations,
|
||||||
|
...spaceFields,
|
||||||
|
...userOperations,
|
||||||
|
...userFields,
|
||||||
|
...workItemOperations,
|
||||||
|
...workItemFields,
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
methods = {
|
||||||
|
loadOptions: {
|
||||||
|
async getLabels(this: ILoadOptionsFunctions) {
|
||||||
|
const responseData = await kitemakerRequest.call(this, { query: getLabels });
|
||||||
|
const { data: { organization: { spaces } } } = responseData;
|
||||||
|
|
||||||
|
return createLoadOptions(spaces[0].labels);
|
||||||
|
},
|
||||||
|
|
||||||
|
async getSpaces(this: ILoadOptionsFunctions) {
|
||||||
|
const responseData = await kitemakerRequest.call(this, { query: getSpaces });
|
||||||
|
const { data: { organization: { spaces } } } = responseData;
|
||||||
|
|
||||||
|
return createLoadOptions(spaces);
|
||||||
|
},
|
||||||
|
|
||||||
|
async getStatuses(this: ILoadOptionsFunctions) {
|
||||||
|
const responseData = await kitemakerRequest.call(this, { query: getStatuses });
|
||||||
|
const { data: { organization: { spaces } } } = responseData;
|
||||||
|
|
||||||
|
return createLoadOptions(spaces[0].statuses);
|
||||||
|
},
|
||||||
|
|
||||||
|
async getUsers(this: ILoadOptionsFunctions) {
|
||||||
|
const responseData = await kitemakerRequest.call(this, { query: getUsers });
|
||||||
|
const { data: { organization: { users } } } = responseData;
|
||||||
|
|
||||||
|
return createLoadOptions(users);
|
||||||
|
},
|
||||||
|
|
||||||
|
async getWorkItems(this: ILoadOptionsFunctions) {
|
||||||
|
const spaceId = this.getNodeParameter('spaceId', 0) as string;
|
||||||
|
|
||||||
|
const responseData = await kitemakerRequest.call(this, {
|
||||||
|
query: getWorkItems,
|
||||||
|
variables: { spaceId },
|
||||||
|
});
|
||||||
|
|
||||||
|
const { data: { workItems: { workItems } } } = responseData;
|
||||||
|
|
||||||
|
return createLoadOptions(workItems);
|
||||||
|
},
|
||||||
|
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
||||||
|
const items = this.getInputData();
|
||||||
|
|
||||||
|
const resource = this.getNodeParameter('resource', 0);
|
||||||
|
const operation = this.getNodeParameter('operation', 0);
|
||||||
|
|
||||||
|
let responseData;
|
||||||
|
const returnData: IDataObject[] = [];
|
||||||
|
|
||||||
|
// https://github.com/kitemakerhq/docs/blob/main/kitemaker.graphql
|
||||||
|
|
||||||
|
for (let i = 0; i < items.length; i++) {
|
||||||
|
|
||||||
|
if (resource === 'organization') {
|
||||||
|
|
||||||
|
// *********************************************************************
|
||||||
|
// organization
|
||||||
|
// *********************************************************************
|
||||||
|
|
||||||
|
if (operation === 'get') {
|
||||||
|
|
||||||
|
// ----------------------------------
|
||||||
|
// organization: get
|
||||||
|
// ----------------------------------
|
||||||
|
|
||||||
|
responseData = await kitemakerRequest.call(this, {
|
||||||
|
query: getOrganization,
|
||||||
|
});
|
||||||
|
|
||||||
|
returnData.push(responseData.data.organization);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (resource === 'space') {
|
||||||
|
|
||||||
|
// *********************************************************************
|
||||||
|
// space
|
||||||
|
// *********************************************************************
|
||||||
|
|
||||||
|
if (operation === 'getAll') {
|
||||||
|
|
||||||
|
// ----------------------------------
|
||||||
|
// space: getAll
|
||||||
|
// ----------------------------------
|
||||||
|
|
||||||
|
const allItems = await kitemakerRequestAllItems.call(this, {
|
||||||
|
query: getAllSpaces,
|
||||||
|
variables: {},
|
||||||
|
});
|
||||||
|
|
||||||
|
returnData.push(...allItems);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (resource === 'user') {
|
||||||
|
|
||||||
|
// *********************************************************************
|
||||||
|
// user
|
||||||
|
// *********************************************************************
|
||||||
|
|
||||||
|
if (operation === 'getAll') {
|
||||||
|
|
||||||
|
// ----------------------------------
|
||||||
|
// user: getAll
|
||||||
|
// ----------------------------------
|
||||||
|
|
||||||
|
const allItems = await kitemakerRequestAllItems.call(this, {
|
||||||
|
query: getAllUsers,
|
||||||
|
variables: {},
|
||||||
|
});
|
||||||
|
|
||||||
|
returnData.push(...allItems);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (resource === 'workItem') {
|
||||||
|
|
||||||
|
// *********************************************************************
|
||||||
|
// workItem
|
||||||
|
// *********************************************************************
|
||||||
|
|
||||||
|
if (operation === 'create') {
|
||||||
|
|
||||||
|
// ----------------------------------
|
||||||
|
// workItem: create
|
||||||
|
// ----------------------------------
|
||||||
|
|
||||||
|
const input = {
|
||||||
|
title: this.getNodeParameter('title', i) as string,
|
||||||
|
statusId: this.getNodeParameter('statusId', i) as string[],
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!input.statusId.length) {
|
||||||
|
throw new Error('Please enter a status to set for the work item to create.');
|
||||||
|
}
|
||||||
|
|
||||||
|
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
|
||||||
|
|
||||||
|
if (Object.keys(additionalFields).length) {
|
||||||
|
Object.assign(input, additionalFields);
|
||||||
|
}
|
||||||
|
|
||||||
|
responseData = await kitemakerRequest.call(this, {
|
||||||
|
query: createWorkItem,
|
||||||
|
variables: { input },
|
||||||
|
});
|
||||||
|
|
||||||
|
returnData.push(responseData.data.createWorkItem.workItem);
|
||||||
|
|
||||||
|
} else if (operation === 'get') {
|
||||||
|
|
||||||
|
// ----------------------------------
|
||||||
|
// workItem: get
|
||||||
|
// ----------------------------------
|
||||||
|
|
||||||
|
const workItemId = this.getNodeParameter('workItemId', i) as string;
|
||||||
|
|
||||||
|
responseData = await kitemakerRequest.call(this, {
|
||||||
|
query: getWorkItem,
|
||||||
|
variables: { workItemId },
|
||||||
|
});
|
||||||
|
|
||||||
|
returnData.push(responseData.data.workItem);
|
||||||
|
|
||||||
|
} else if (operation === 'getAll') {
|
||||||
|
|
||||||
|
// ----------------------------------
|
||||||
|
// workItem: getAll
|
||||||
|
// ----------------------------------
|
||||||
|
|
||||||
|
const allItems = await kitemakerRequestAllItems.call(this, {
|
||||||
|
query: getAllWorkItems,
|
||||||
|
variables: {
|
||||||
|
spaceId: this.getNodeParameter('spaceId', i) as string,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
returnData.push(...allItems);
|
||||||
|
|
||||||
|
} else if (operation === 'update') {
|
||||||
|
|
||||||
|
// ----------------------------------
|
||||||
|
// workItem: update
|
||||||
|
// ----------------------------------
|
||||||
|
|
||||||
|
const input = {
|
||||||
|
id: this.getNodeParameter('workItemId', i),
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
|
||||||
|
|
||||||
|
if (!Object.keys(updateFields).length) {
|
||||||
|
throw new Error('Please enter at least one field to update for the work item.');
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.assign(input, updateFields);
|
||||||
|
|
||||||
|
responseData = await kitemakerRequest.call(this, {
|
||||||
|
query: editWorkItem,
|
||||||
|
variables: { input },
|
||||||
|
});
|
||||||
|
|
||||||
|
returnData.push(responseData.data.editWorkItem.workItem);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [this.helpers.returnJsonArray(returnData)];
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
import {
|
||||||
|
INodeProperties,
|
||||||
|
} from 'n8n-workflow';
|
||||||
|
|
||||||
|
export const organizationOperations = [
|
||||||
|
{
|
||||||
|
displayName: 'Operation',
|
||||||
|
name: 'operation',
|
||||||
|
type: 'options',
|
||||||
|
default: 'get',
|
||||||
|
description: 'Operation to perform.',
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: 'Get',
|
||||||
|
value: 'get',
|
||||||
|
description: 'Retrieve data on the logged-in user\'s organization.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
resource: [
|
||||||
|
'organization',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
] as INodeProperties[];
|
|
@ -0,0 +1,71 @@
|
||||||
|
import {
|
||||||
|
INodeProperties,
|
||||||
|
} from 'n8n-workflow';
|
||||||
|
|
||||||
|
export const spaceOperations = [
|
||||||
|
{
|
||||||
|
displayName: 'Operation',
|
||||||
|
name: 'operation',
|
||||||
|
type: 'options',
|
||||||
|
default: 'getAll',
|
||||||
|
description: 'Operation to perform.',
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: 'Get All',
|
||||||
|
value: 'getAll',
|
||||||
|
description: 'Retrieve data on all the spaces in the<br>logged-in user\'s organization.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
resource: [
|
||||||
|
'space',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
] as INodeProperties[];
|
||||||
|
|
||||||
|
export const spaceFields = [
|
||||||
|
{
|
||||||
|
displayName: 'Return All',
|
||||||
|
name: 'returnAll',
|
||||||
|
type: 'boolean',
|
||||||
|
default: false,
|
||||||
|
description: 'Return all results.',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
resource: [
|
||||||
|
'space',
|
||||||
|
],
|
||||||
|
operation: [
|
||||||
|
'getAll',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Limit',
|
||||||
|
name: 'limit',
|
||||||
|
type: 'number',
|
||||||
|
default: 5,
|
||||||
|
description: 'The number of results to return.',
|
||||||
|
typeOptions: {
|
||||||
|
minValue: 1,
|
||||||
|
maxValue: 1000,
|
||||||
|
},
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
resource: [
|
||||||
|
'space',
|
||||||
|
],
|
||||||
|
operation: [
|
||||||
|
'getAll',
|
||||||
|
],
|
||||||
|
returnAll: [
|
||||||
|
false,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
] as INodeProperties[];
|
|
@ -0,0 +1,71 @@
|
||||||
|
import {
|
||||||
|
INodeProperties,
|
||||||
|
} from 'n8n-workflow';
|
||||||
|
|
||||||
|
export const userOperations = [
|
||||||
|
{
|
||||||
|
displayName: 'Operation',
|
||||||
|
name: 'operation',
|
||||||
|
type: 'options',
|
||||||
|
default: 'getAll',
|
||||||
|
description: 'Operation to perform.',
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: 'Get All',
|
||||||
|
value: 'getAll',
|
||||||
|
description: 'Retrieve data on all the users in the<br>logged-in user\'s organization.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
resource: [
|
||||||
|
'user',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
] as INodeProperties[];
|
||||||
|
|
||||||
|
export const userFields = [
|
||||||
|
{
|
||||||
|
displayName: 'Return All',
|
||||||
|
name: 'returnAll',
|
||||||
|
type: 'boolean',
|
||||||
|
default: false,
|
||||||
|
description: 'Return all results.',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
resource: [
|
||||||
|
'user',
|
||||||
|
],
|
||||||
|
operation: [
|
||||||
|
'getAll',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Limit',
|
||||||
|
name: 'limit',
|
||||||
|
type: 'number',
|
||||||
|
default: 5,
|
||||||
|
description: 'The number of results to return.',
|
||||||
|
typeOptions: {
|
||||||
|
minValue: 1,
|
||||||
|
maxValue: 1000,
|
||||||
|
},
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
resource: [
|
||||||
|
'user',
|
||||||
|
],
|
||||||
|
operation: [
|
||||||
|
'getAll',
|
||||||
|
],
|
||||||
|
returnAll: [
|
||||||
|
false,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
] as INodeProperties[];
|
|
@ -0,0 +1,372 @@
|
||||||
|
import {
|
||||||
|
INodeProperties,
|
||||||
|
} from 'n8n-workflow';
|
||||||
|
|
||||||
|
export const workItemOperations = [
|
||||||
|
{
|
||||||
|
displayName: 'Operation',
|
||||||
|
name: 'operation',
|
||||||
|
type: 'options',
|
||||||
|
default: 'get',
|
||||||
|
description: 'Operation to perform.',
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: 'Create',
|
||||||
|
value: 'create',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Get',
|
||||||
|
value: 'get',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Get All',
|
||||||
|
value: 'getAll',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Update',
|
||||||
|
value: 'update',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
resource: [
|
||||||
|
'workItem',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
] as INodeProperties[];
|
||||||
|
|
||||||
|
export const workItemFields = [
|
||||||
|
// ----------------------------------
|
||||||
|
// workItem: create
|
||||||
|
// ----------------------------------
|
||||||
|
{
|
||||||
|
displayName: 'Title',
|
||||||
|
name: 'title',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
required: true,
|
||||||
|
description: 'Title of the work item to create.',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
resource: [
|
||||||
|
'workItem',
|
||||||
|
],
|
||||||
|
operation: [
|
||||||
|
'create',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Status ID',
|
||||||
|
name: 'statusId',
|
||||||
|
type: 'options',
|
||||||
|
typeOptions: {
|
||||||
|
loadOptionsMethod: 'getStatuses',
|
||||||
|
},
|
||||||
|
default: [],
|
||||||
|
required: true,
|
||||||
|
description: 'ID of the status to set on the item to create.',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
resource: [
|
||||||
|
'workItem',
|
||||||
|
],
|
||||||
|
operation: [
|
||||||
|
'create',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Additional Fields',
|
||||||
|
name: 'additionalFields',
|
||||||
|
type: 'collection',
|
||||||
|
placeholder: 'Add Field',
|
||||||
|
default: {},
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
resource: [
|
||||||
|
'workItem',
|
||||||
|
],
|
||||||
|
operation: [
|
||||||
|
'create',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
displayName: 'Description',
|
||||||
|
name: 'description',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
typeOptions: {
|
||||||
|
alwaysOpenEditWindow: true,
|
||||||
|
},
|
||||||
|
description: 'Description of the item to create. Markdown supported.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Effort',
|
||||||
|
name: 'effort',
|
||||||
|
type: 'options',
|
||||||
|
default: 'SMALL',
|
||||||
|
description: 'Effort to set for the item to create.',
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: 'Small',
|
||||||
|
value: 'SMALL',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Medium',
|
||||||
|
value: 'MEDIUM',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Large',
|
||||||
|
value: 'LARGE',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Impact',
|
||||||
|
name: 'impact',
|
||||||
|
type: 'options',
|
||||||
|
default: 'SMALL',
|
||||||
|
description: 'Impact to set for the item to create.',
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: 'Small',
|
||||||
|
value: 'SMALL',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Medium',
|
||||||
|
value: 'MEDIUM',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Large',
|
||||||
|
value: 'LARGE',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Label IDs',
|
||||||
|
name: 'labelIds',
|
||||||
|
type: 'multiOptions',
|
||||||
|
typeOptions: {
|
||||||
|
loadOptionsMethod: 'getLabels',
|
||||||
|
},
|
||||||
|
default: [],
|
||||||
|
description: 'ID of the label to set on the item to create.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Member IDs',
|
||||||
|
name: 'memberIds',
|
||||||
|
type: 'multiOptions',
|
||||||
|
typeOptions: {
|
||||||
|
loadOptionsMethod: 'getUsers',
|
||||||
|
},
|
||||||
|
default: [],
|
||||||
|
description: 'ID of the user to assign to the item to create.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
// ----------------------------------
|
||||||
|
// workItem: get
|
||||||
|
// ----------------------------------
|
||||||
|
{
|
||||||
|
displayName: 'Work Item ID',
|
||||||
|
name: 'workItemId',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
required: true,
|
||||||
|
description: 'ID of the work item to retrieve.',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
resource: [
|
||||||
|
'workItem',
|
||||||
|
],
|
||||||
|
operation: [
|
||||||
|
'get',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// ----------------------------------
|
||||||
|
// workItem: getAll
|
||||||
|
// ----------------------------------
|
||||||
|
{
|
||||||
|
displayName: 'Space ID',
|
||||||
|
name: 'spaceId',
|
||||||
|
type: 'options',
|
||||||
|
typeOptions: {
|
||||||
|
loadOptionsMethod: 'getSpaces',
|
||||||
|
},
|
||||||
|
default: [],
|
||||||
|
required: true,
|
||||||
|
description: 'ID of the space to retrieve the work items from.',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
resource: [
|
||||||
|
'workItem',
|
||||||
|
],
|
||||||
|
operation: [
|
||||||
|
'getAll',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Return All',
|
||||||
|
name: 'returnAll',
|
||||||
|
type: 'boolean',
|
||||||
|
default: false,
|
||||||
|
description: 'Return all results.',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
resource: [
|
||||||
|
'workItem',
|
||||||
|
],
|
||||||
|
operation: [
|
||||||
|
'getAll',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Limit',
|
||||||
|
name: 'limit',
|
||||||
|
type: 'number',
|
||||||
|
default: 5,
|
||||||
|
description: 'The number of results to return.',
|
||||||
|
typeOptions: {
|
||||||
|
minValue: 1,
|
||||||
|
maxValue: 1000,
|
||||||
|
},
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
resource: [
|
||||||
|
'workItem',
|
||||||
|
],
|
||||||
|
operation: [
|
||||||
|
'getAll',
|
||||||
|
],
|
||||||
|
returnAll: [
|
||||||
|
false,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// ----------------------------------
|
||||||
|
// workItem: update
|
||||||
|
// ----------------------------------
|
||||||
|
{
|
||||||
|
displayName: 'Work Item ID',
|
||||||
|
name: 'workItemId',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
required: true,
|
||||||
|
description: 'ID of the work item to update.',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
resource: [
|
||||||
|
'workItem',
|
||||||
|
],
|
||||||
|
operation: [
|
||||||
|
'update',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Update Fields',
|
||||||
|
name: 'updateFields',
|
||||||
|
type: 'collection',
|
||||||
|
placeholder: 'Add Field',
|
||||||
|
default: {},
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
resource: [
|
||||||
|
'workItem',
|
||||||
|
],
|
||||||
|
operation: [
|
||||||
|
'update',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
displayName: 'Description',
|
||||||
|
name: 'description',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
typeOptions: {
|
||||||
|
alwaysOpenEditWindow: true,
|
||||||
|
},
|
||||||
|
description: 'Description of the item to update. Markdown supported.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Effort',
|
||||||
|
name: 'effort',
|
||||||
|
type: 'options',
|
||||||
|
default: 'SMALL',
|
||||||
|
description: 'Effort to set for the item to update.',
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: 'Small',
|
||||||
|
value: 'SMALL',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Medium',
|
||||||
|
value: 'MEDIUM',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Large',
|
||||||
|
value: 'LARGE',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Impact',
|
||||||
|
name: 'impact',
|
||||||
|
type: 'options',
|
||||||
|
default: 'SMALL',
|
||||||
|
description: 'Impact to set for the item to update.',
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: 'Small',
|
||||||
|
value: 'SMALL',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Medium',
|
||||||
|
value: 'MEDIUM',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Large',
|
||||||
|
value: 'LARGE',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Status ID',
|
||||||
|
name: 'statusId',
|
||||||
|
type: 'options',
|
||||||
|
typeOptions: {
|
||||||
|
loadOptionsMethod: 'getStatuses',
|
||||||
|
},
|
||||||
|
default: [],
|
||||||
|
description: 'ID of the status to set on the item to update.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Title',
|
||||||
|
name: 'title',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
description: 'Title to set for the work item to update.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
] as INodeProperties[];
|
|
@ -0,0 +1,4 @@
|
||||||
|
export * from './OrganizationDescription';
|
||||||
|
export * from './SpaceDescription';
|
||||||
|
export * from './UserDescription';
|
||||||
|
export * from './WorkItemDescription';
|
18
packages/nodes-base/nodes/Kitemaker/kitemaker.svg
Normal file
18
packages/nodes-base/nodes/Kitemaker/kitemaker.svg
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
<?xml version="1.0" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||||
|
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||||
|
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="170.000000pt" height="170.000000pt" viewBox="-30 -25 220.000000 220.000000"
|
||||||
|
preserveAspectRatio="xMidYMid meet">
|
||||||
|
|
||||||
|
<g transform="translate(0.000000,170.000000) scale(0.100000,-0.100000)"
|
||||||
|
fill="#000000" stroke="none">
|
||||||
|
<path fill="#662482" d="M1065 1445 c-302 -140 -560 -254 -572 -254 -17 -1 -61 50 -200 229
|
||||||
|
-178 229 -206 256 -242 233 -14 -9 -16 -89 -19 -793 -1 -570 1 -786 9 -796 35
|
||||||
|
-43 33 -46 852 774 558 558 787 794 787 809 0 26 -25 53 -48 52 -9 0 -264
|
||||||
|
-115 -567 -254z"/>
|
||||||
|
<path fill="#e61b73" d="M694 448 c-133 -134 -244 -251 -247 -260 -3 -9 2 -26 11 -38 16 -18
|
||||||
|
67 -26 599 -85 320 -35 589 -62 597 -59 19 7 29 38 21 62 -3 9 -159 152 -346
|
||||||
|
317 -241 212 -348 301 -367 303 -23 2 -59 -30 -268 -240z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 922 B |
69
packages/nodes-base/nodes/Kitemaker/mutations.ts
Normal file
69
packages/nodes-base/nodes/Kitemaker/mutations.ts
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
// ----------------------------------
|
||||||
|
// mutations
|
||||||
|
// ----------------------------------
|
||||||
|
|
||||||
|
export const createWorkItem = `
|
||||||
|
mutation($input: CreateWorkItemInput!) {
|
||||||
|
createWorkItem(input: $input) {
|
||||||
|
workItem {
|
||||||
|
id
|
||||||
|
number
|
||||||
|
title
|
||||||
|
description
|
||||||
|
status {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
members {
|
||||||
|
id
|
||||||
|
username
|
||||||
|
}
|
||||||
|
watchers {
|
||||||
|
id
|
||||||
|
username
|
||||||
|
}
|
||||||
|
labels {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
effort
|
||||||
|
impact
|
||||||
|
updatedAt
|
||||||
|
createdAt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const editWorkItem = `
|
||||||
|
mutation ($input: EditWorkItemInput!) {
|
||||||
|
editWorkItem(input: $input) {
|
||||||
|
workItem {
|
||||||
|
id
|
||||||
|
number
|
||||||
|
title
|
||||||
|
description
|
||||||
|
status {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
members {
|
||||||
|
id
|
||||||
|
username
|
||||||
|
}
|
||||||
|
watchers {
|
||||||
|
id
|
||||||
|
username
|
||||||
|
}
|
||||||
|
labels {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
effort
|
||||||
|
impact
|
||||||
|
updatedAt
|
||||||
|
createdAt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
199
packages/nodes-base/nodes/Kitemaker/queries.ts
Normal file
199
packages/nodes-base/nodes/Kitemaker/queries.ts
Normal file
|
@ -0,0 +1,199 @@
|
||||||
|
// ----------------------------------
|
||||||
|
// queries
|
||||||
|
// ----------------------------------
|
||||||
|
|
||||||
|
export const getAllSpaces = `
|
||||||
|
query {
|
||||||
|
organization {
|
||||||
|
spaces {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
labels {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
color
|
||||||
|
}
|
||||||
|
statuses {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
type
|
||||||
|
default
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const getAllUsers = `
|
||||||
|
query {
|
||||||
|
organization {
|
||||||
|
users {
|
||||||
|
id
|
||||||
|
username
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const getLabels = `
|
||||||
|
query {
|
||||||
|
organization {
|
||||||
|
spaces {
|
||||||
|
labels {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
color
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const getOrganization = `
|
||||||
|
query {
|
||||||
|
organization {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const getSpaces = `
|
||||||
|
query {
|
||||||
|
organization {
|
||||||
|
spaces {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
labels {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
color
|
||||||
|
}
|
||||||
|
statuses {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
type
|
||||||
|
default
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const getStatuses = `
|
||||||
|
query {
|
||||||
|
organization {
|
||||||
|
spaces {
|
||||||
|
statuses {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
type
|
||||||
|
default
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const getUsers = `
|
||||||
|
query {
|
||||||
|
organization {
|
||||||
|
users {
|
||||||
|
id
|
||||||
|
username
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const getWorkItems = `
|
||||||
|
query($spaceId: ID!) {
|
||||||
|
workItems(spaceId: $spaceId) {
|
||||||
|
workItems {
|
||||||
|
id
|
||||||
|
title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const getWorkItem = `
|
||||||
|
query($workItemId: ID!) {
|
||||||
|
workItem(id: $workItemId) {
|
||||||
|
id
|
||||||
|
number
|
||||||
|
title
|
||||||
|
description
|
||||||
|
status {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
sort
|
||||||
|
members {
|
||||||
|
id
|
||||||
|
username
|
||||||
|
}
|
||||||
|
watchers {
|
||||||
|
id
|
||||||
|
username
|
||||||
|
}
|
||||||
|
labels {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
comments {
|
||||||
|
id
|
||||||
|
actor {
|
||||||
|
__typename
|
||||||
|
}
|
||||||
|
body
|
||||||
|
threadId
|
||||||
|
updatedAt
|
||||||
|
createdAt
|
||||||
|
}
|
||||||
|
effort
|
||||||
|
impact
|
||||||
|
updatedAt
|
||||||
|
createdAt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const getAllWorkItems = `
|
||||||
|
query($spaceId: ID!, $cursor: String) {
|
||||||
|
workItems(spaceId: $spaceId, cursor: $cursor) {
|
||||||
|
hasMore,
|
||||||
|
cursor,
|
||||||
|
workItems {
|
||||||
|
id
|
||||||
|
title
|
||||||
|
description
|
||||||
|
labels {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
comments {
|
||||||
|
id
|
||||||
|
body
|
||||||
|
actor {
|
||||||
|
... on User {
|
||||||
|
id
|
||||||
|
username
|
||||||
|
}
|
||||||
|
... on IntegrationUser {
|
||||||
|
id
|
||||||
|
externalName
|
||||||
|
}
|
||||||
|
... on Integration {
|
||||||
|
id
|
||||||
|
type
|
||||||
|
}
|
||||||
|
... on Application {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
|
@ -133,6 +133,7 @@
|
||||||
"dist/credentials/JotFormApi.credentials.js",
|
"dist/credentials/JotFormApi.credentials.js",
|
||||||
"dist/credentials/Kafka.credentials.js",
|
"dist/credentials/Kafka.credentials.js",
|
||||||
"dist/credentials/KeapOAuth2Api.credentials.js",
|
"dist/credentials/KeapOAuth2Api.credentials.js",
|
||||||
|
"dist/credentials/KitemakerApi.credentials.js",
|
||||||
"dist/credentials/LemlistApi.credentials.js",
|
"dist/credentials/LemlistApi.credentials.js",
|
||||||
"dist/credentials/LineNotifyOAuth2Api.credentials.js",
|
"dist/credentials/LineNotifyOAuth2Api.credentials.js",
|
||||||
"dist/credentials/LingvaNexApi.credentials.js",
|
"dist/credentials/LingvaNexApi.credentials.js",
|
||||||
|
@ -406,6 +407,7 @@
|
||||||
"dist/nodes/Kafka/KafkaTrigger.node.js",
|
"dist/nodes/Kafka/KafkaTrigger.node.js",
|
||||||
"dist/nodes/Keap/Keap.node.js",
|
"dist/nodes/Keap/Keap.node.js",
|
||||||
"dist/nodes/Keap/KeapTrigger.node.js",
|
"dist/nodes/Keap/KeapTrigger.node.js",
|
||||||
|
"dist/nodes/Kitemaker/Kitemaker.node.js",
|
||||||
"dist/nodes/Lemlist/Lemlist.node.js",
|
"dist/nodes/Lemlist/Lemlist.node.js",
|
||||||
"dist/nodes/Lemlist/LemlistTrigger.node.js",
|
"dist/nodes/Lemlist/LemlistTrigger.node.js",
|
||||||
"dist/nodes/Line/Line.node.js",
|
"dist/nodes/Line/Line.node.js",
|
||||||
|
|
Loading…
Reference in a new issue