first commit
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled

This commit is contained in:
2026-03-17 16:22:57 +03:30
commit 3d5eaf9445
15349 changed files with 2847338 additions and 0 deletions
@@ -0,0 +1,241 @@
import type { INodeProperties } from 'n8n-workflow';
export const attachmentOperations: INodeProperties[] = [
// ----------------------------------
// attachment
// ----------------------------------
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['attachment'],
},
},
options: [
{
name: 'Create',
value: 'create',
description: 'Create a new attachment for a card',
action: 'Create an attachment',
},
{
name: 'Delete',
value: 'delete',
description: 'Delete an attachment',
action: 'Delete an attachment',
},
{
name: 'Get',
value: 'get',
description: 'Get the data of an attachment',
action: 'Get an attachment',
},
{
name: 'Get Many',
value: 'getAll',
description: 'Returns many attachments for the card',
action: 'Get many attachments',
},
],
default: 'getAll',
},
];
export const attachmentFields: INodeProperties[] = [
{
displayName: 'Card ID',
name: 'cardId',
type: 'resourceLocator',
default: { mode: 'list', value: '' },
required: true,
modes: [
{
displayName: 'From List',
name: 'list',
type: 'list',
placeholder: 'Select a Card...',
typeOptions: {
searchListMethod: 'searchCards',
searchFilterRequired: true,
searchable: true,
},
},
{
displayName: 'By URL',
name: 'url',
type: 'string',
placeholder: 'https://trello.com/c/e123456/card-name',
validation: [
{
type: 'regex',
properties: {
regex: 'http(s)?://trello.com/c/([a-zA-Z0-9]{2,})/.*',
errorMessage: 'Not a valid Trello Card URL',
},
},
],
extractValue: {
type: 'regex',
regex: 'https://trello.com/c/([a-zA-Z0-9]{2,})',
},
},
{
displayName: 'ID',
name: 'id',
type: 'string',
validation: [
{
type: 'regex',
properties: {
regex: '[a-zA-Z0-9]{2,}',
errorMessage: 'Not a valid Trello Card ID',
},
},
],
placeholder: 'wiIaGwqE',
url: '=https://trello.com/c/{{$value}}',
},
],
displayOptions: {
show: {
operation: ['delete', 'create', 'get', 'getAll'],
resource: ['attachment'],
},
},
description: 'The ID of the card',
},
// ----------------------------------
// attachment:create
// ----------------------------------
{
displayName: 'Source URL',
name: 'url',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: ['create'],
resource: ['attachment'],
},
},
description: 'The URL of the attachment to add',
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
displayOptions: {
show: {
operation: ['create'],
resource: ['attachment'],
},
},
default: {},
options: [
{
displayName: 'MIME Type',
name: 'mimeType',
type: 'string',
default: '',
placeholder: 'image/png',
description: 'The MIME type of the attachment to add',
},
{
displayName: 'Name',
name: 'name',
type: 'string',
default: '',
description: 'The name of the attachment to add',
},
],
},
// ----------------------------------
// attachment:delete
// ----------------------------------
{
displayName: 'Attachment ID',
name: 'id',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: ['delete'],
resource: ['attachment'],
},
},
description: 'The ID of the attachment to delete',
},
// ----------------------------------
// attachment:getAll
// ----------------------------------
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
displayOptions: {
show: {
operation: ['getAll'],
resource: ['attachment'],
},
},
default: {},
options: [
{
displayName: 'Fields',
name: 'fields',
type: 'string',
default: 'all',
description: 'Fields to return. Either "all" or a comma-separated list of fields.',
},
],
},
// ----------------------------------
// attachment:get
// ----------------------------------
{
displayName: 'Attachment ID',
name: 'id',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: ['get'],
resource: ['attachment'],
},
},
description: 'The ID of the attachment to get',
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
displayOptions: {
show: {
operation: ['get'],
resource: ['attachment'],
},
},
default: {},
options: [
{
displayName: 'Fields',
name: 'fields',
type: 'string',
default: 'all',
description: 'Fields to return. Either "all" or a comma-separated list of fields.',
},
],
},
];
@@ -0,0 +1,448 @@
import type { INodeProperties } from 'n8n-workflow';
export const boardOperations: INodeProperties[] = [
// ----------------------------------
// board
// ----------------------------------
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['board'],
},
},
options: [
{
name: 'Create',
value: 'create',
description: 'Create a new board',
action: 'Create a board',
},
{
name: 'Delete',
value: 'delete',
description: 'Delete a board',
action: 'Delete a board',
},
{
name: 'Get',
value: 'get',
description: 'Get the data of a board',
action: 'Get a board',
},
{
name: 'Update',
value: 'update',
description: 'Update a board',
action: 'Update a board',
},
],
default: 'create',
},
];
export const boardFields: INodeProperties[] = [
// ----------------------------------
// board:create
// ----------------------------------
{
displayName: 'Name',
name: 'name',
type: 'string',
default: '',
placeholder: 'My board',
required: true,
displayOptions: {
show: {
operation: ['create'],
resource: ['board'],
},
},
description: 'The name of the board',
},
{
displayName: 'Description',
name: 'description',
type: 'string',
default: '',
displayOptions: {
show: {
operation: ['create'],
resource: ['board'],
},
},
description: 'The description of the board',
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
displayOptions: {
show: {
operation: ['create'],
resource: ['board'],
},
},
default: {},
options: [
{
displayName: 'Aging',
name: 'prefs_cardAging',
type: 'options',
options: [
{
name: 'Pirate',
value: 'pirate',
},
{
name: 'Regular',
value: 'regular',
},
],
default: 'regular',
description:
'Determines the type of card aging that should take place on the board if card aging is enabled',
},
{
displayName: 'Background',
name: 'prefs_background',
type: 'string',
default: 'blue',
description:
'The ID of a custom background or one of: blue, orange, green, red, purple, pink, lime, sky, grey',
},
{
displayName: 'Comments',
name: 'prefs_comments',
type: 'options',
options: [
{
name: 'Disabled',
value: 'disabled',
},
{
name: 'Members',
value: 'members',
},
{
name: 'Observers',
value: 'observers',
},
{
name: 'Organization',
value: 'org',
},
{
name: 'Public',
value: 'public',
},
],
default: 'members',
description: 'Who can comment on cards on this board',
},
{
displayName: 'Covers',
name: 'prefs_cardCovers',
type: 'boolean',
default: true,
description: 'Whether card covers are enabled',
},
{
displayName: 'Invitations',
name: 'prefs_invitations',
type: 'options',
options: [
{
name: 'Admins',
value: 'admins',
},
{
name: 'Members',
value: 'members',
},
],
default: 'members',
description: 'Determines what types of members can invite users to join',
},
{
displayName: 'Keep From Source',
name: 'keepFromSource',
type: 'string',
default: 'none',
description: 'To keep cards from the original board pass in the value cards',
},
{
displayName: 'Labels',
name: 'defaultLabels',
type: 'boolean',
default: true,
description: 'Whether to use the default set of labels',
},
{
displayName: 'Lists',
name: 'defaultLists',
type: 'boolean',
default: true,
description:
'Whether to add the default set of lists to a board(To Do, Doing, Done).It is ignored if idBoardSource is provided',
},
{
displayName: 'Organization ID',
name: 'idOrganization',
type: 'string',
default: '',
description: 'The ID or name of the team the board should belong to',
},
{
displayName: 'Permission Level',
name: 'prefs_permissionLevel',
type: 'options',
options: [
{
name: 'Organization',
value: 'org',
},
{
name: 'Private',
value: 'private',
},
{
name: 'Public',
value: 'public',
},
],
default: 'private',
description: 'The permissions level of the board',
},
{
displayName: 'Power Ups',
name: 'powerUps',
type: 'options',
options: [
{
name: 'All',
value: 'all',
},
{
name: 'Calendar',
value: 'calendar',
},
{
name: 'Card Aging',
value: 'cardAging',
},
{
name: 'Recap',
value: 'recap',
},
{
name: 'Voting',
value: 'voting',
},
],
default: 'all',
description: 'The Power-Ups that should be enabled on the new board',
},
{
displayName: 'Self Join',
name: 'prefs_selfJoin',
type: 'boolean',
default: true,
description:
'Whether users can join the boards themselves or whether they have to be invited',
},
{
displayName: 'Source IDs',
name: 'idBoardSource',
type: 'string',
default: '',
description: 'The ID of a board to copy into the new board',
},
{
displayName: 'Voting',
name: 'prefs_voting',
type: 'options',
options: [
{
name: 'Disabled',
value: 'disabled',
},
{
name: 'Members',
value: 'members',
},
{
name: 'Observers',
value: 'observers',
},
{
name: 'Organization',
value: 'org',
},
{
name: 'Public',
value: 'public',
},
],
default: 'disabled',
description: 'Who can vote on this board',
},
],
},
{
displayName: 'Board',
name: 'id',
type: 'resourceLocator',
default: { mode: 'list', value: '' },
required: true,
displayOptions: {
show: {
operation: ['get', 'delete', 'update'],
resource: ['board'],
},
},
description: 'The ID of the board',
modes: [
{
displayName: 'From List',
name: 'list',
type: 'list',
placeholder: 'Select a Board...',
initType: 'board',
typeOptions: {
searchListMethod: 'searchBoards',
searchFilterRequired: true,
searchable: true,
},
},
{
displayName: 'By URL',
name: 'url',
type: 'string',
placeholder: 'https://trello.com/b/e123456/board-name',
validation: [
{
type: 'regex',
properties: {
regex: 'http(s)?://trello.com/b/([a-zA-Z0-9]{2,})/.*',
errorMessage: 'Not a valid Trello Board URL',
},
},
],
extractValue: {
type: 'regex',
regex: 'https://trello.com/b/([a-zA-Z0-9]{2,})',
},
},
{
displayName: 'ID',
name: 'id',
type: 'string',
validation: [
{
type: 'regex',
properties: {
regex: '[a-zA-Z0-9]{2,}',
errorMessage: 'Not a valid Trello Board ID',
},
},
],
placeholder: 'KdEAAdde',
url: '=https://trello.com/b/{{$value}}',
},
],
},
// ----------------------------------
// board:get
// ----------------------------------
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
displayOptions: {
show: {
operation: ['get'],
resource: ['board'],
},
},
default: {},
options: [
{
displayName: 'Fields',
name: 'fields',
type: 'string',
default: 'all',
description:
'Fields to return. Either "all" or a comma-separated list: closed, dateLastActivity, dateLastView, desc, descData, idOrganization, invitations, invited, labelNames, memberships, name, pinned, powerUps, prefs, shortLink, shortUrl, starred, subscribed, URL.',
},
{
displayName: 'Plugin Data',
name: 'pluginData',
type: 'boolean',
default: false,
description: 'Whether to include pluginData on the card with the response',
},
],
},
// ----------------------------------
// board:update
// ----------------------------------
{
displayName: 'Update Fields',
name: 'updateFields',
type: 'collection',
placeholder: 'Add Field',
displayOptions: {
show: {
operation: ['update'],
resource: ['board'],
},
},
default: {},
options: [
{
displayName: 'Closed',
name: 'closed',
type: 'boolean',
default: false,
description: 'Whether the board is closed',
},
{
displayName: 'Description',
name: 'desc',
type: 'string',
default: '',
description: 'New description of the board',
},
{
displayName: 'Name',
name: 'name',
type: 'string',
default: '',
description: 'New name of the board',
},
{
displayName: 'Organization ID',
name: 'idOrganization',
type: 'string',
default: '',
description: 'The ID of the team the board should be moved to',
},
{
displayName: 'Subscribed',
name: 'subscribed',
type: 'boolean',
default: false,
description: 'Whether the acting user is subscribed to the board',
},
],
},
];
@@ -0,0 +1,292 @@
import type { INodeProperties } from 'n8n-workflow';
export const boardMemberOperations: INodeProperties[] = [
// ----------------------------------
// boardMember
// ----------------------------------
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['boardMember'],
},
},
options: [
{
name: 'Add',
value: 'add',
description: 'Add member to board using member ID',
action: 'Add a board member',
},
{
name: 'Get Many',
value: 'getAll',
description: 'Get many members of a board',
action: 'Get many board members',
},
{
name: 'Invite',
value: 'invite',
description: 'Invite a new member to a board via email',
action: 'Invite a board member',
},
{
name: 'Remove',
value: 'remove',
description: 'Remove member from board using member ID',
action: 'Remove a board member',
},
],
default: 'add',
},
];
export const boardMemberFields: INodeProperties[] = [
// ----------------------------------
// boardMember:getAll
// ----------------------------------
{
displayName: 'Board ID',
name: 'id',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: ['getAll'],
resource: ['boardMember'],
},
},
description: 'The ID of the board to get members from',
},
{
displayName: 'Return All',
name: 'returnAll',
type: 'boolean',
displayOptions: {
show: {
operation: ['getAll'],
resource: ['boardMember'],
},
},
default: false,
description: 'Whether to return all results or only up to a given limit',
},
{
displayName: 'Limit',
name: 'limit',
type: 'number',
typeOptions: {
minValue: 1,
},
description: 'Max number of results to return',
default: 20,
displayOptions: {
show: {
operation: ['getAll'],
resource: ['boardMember'],
returnAll: [false],
},
},
},
// ----------------------------------
// boardMember:add
// ----------------------------------
{
displayName: 'Board ID',
name: 'id',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: ['add'],
resource: ['boardMember'],
},
},
description: 'The ID of the board to add member to',
},
{
displayName: 'Member ID',
name: 'idMember',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: ['add'],
resource: ['boardMember'],
},
},
description: 'The ID of the member to add to the board',
},
{
displayName: 'Type',
name: 'type',
type: 'options',
required: true,
default: 'normal',
displayOptions: {
show: {
operation: ['add'],
resource: ['boardMember'],
},
},
options: [
{
name: 'Normal',
value: 'normal',
description: 'Invite as normal member',
},
{
name: 'Admin',
value: 'admin',
description: 'Invite as admin',
},
{
name: 'Observer',
value: 'observer',
description: 'Invite as observer (Trello premium feature)',
},
],
description: 'Determines the type of membership the user being added should have',
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
default: {},
displayOptions: {
show: {
operation: ['add'],
resource: ['boardMember'],
},
},
options: [
{
displayName: 'Allow Billable Guest',
name: 'allowBillableGuest',
type: 'boolean',
default: false,
description: 'Whether to allow organization admins to add multi-board guests onto a board',
},
],
},
// ----------------------------------
// boardMember:invite
// ----------------------------------
{
displayName: 'Board ID',
name: 'id',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: ['invite'],
resource: ['boardMember'],
},
},
description: 'The ID of the board to invite member to',
},
{
displayName: 'Email',
name: 'email',
type: 'string',
placeholder: 'name@email.com',
default: '',
required: true,
displayOptions: {
show: {
operation: ['invite'],
resource: ['boardMember'],
},
},
description: 'The ID of the board to update',
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
displayOptions: {
show: {
operation: ['invite'],
resource: ['boardMember'],
},
},
default: {},
options: [
{
displayName: 'Type',
name: 'type',
type: 'options',
default: 'normal',
options: [
{
name: 'Normal',
value: 'normal',
description: 'Invite as normal member',
},
{
name: 'Admin',
value: 'admin',
description: 'Invite as admin',
},
{
name: 'Observer',
value: 'observer',
description: 'Invite as observer (Trello premium feature)',
},
],
description: 'Determines the type of membership the user being added should have',
},
{
displayName: 'Full Name',
name: 'fullName',
type: 'string',
default: '',
description:
'The full name of the user to add as a member of the board. Must have a length of at least 1 and cannot begin nor end with a space.',
},
],
},
// ----------------------------------
// boardMember:remove
// ----------------------------------
{
displayName: 'Board ID',
name: 'id',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: ['remove'],
resource: ['boardMember'],
},
},
description: 'The ID of the board to remove member from',
},
{
displayName: 'Member ID',
name: 'idMember',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: ['remove'],
resource: ['boardMember'],
},
},
description: 'The ID of the member to remove from the board',
},
];
@@ -0,0 +1,169 @@
import type { INodeProperties } from 'n8n-workflow';
export const cardCommentOperations: INodeProperties[] = [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['cardComment'],
},
},
options: [
{
name: 'Create',
value: 'create',
description: 'Create a comment on a card',
action: 'Create a card comment',
},
{
name: 'Delete',
value: 'delete',
description: 'Delete a comment from a card',
action: 'Delete a card comment',
},
{
name: 'Update',
value: 'update',
description: 'Update a comment on a card',
action: 'Update a card comment',
},
],
default: 'create',
},
];
export const cardCommentFields: INodeProperties[] = [
{
displayName: 'Card',
name: 'cardId',
type: 'resourceLocator',
default: { mode: 'list', value: '' },
required: true,
modes: [
{
displayName: 'From List',
name: 'list',
type: 'list',
placeholder: 'Select a Card...',
typeOptions: {
searchListMethod: 'searchCards',
searchFilterRequired: true,
searchable: true,
},
},
{
displayName: 'By URL',
name: 'url',
type: 'string',
placeholder: 'https://trello.com/c/e123456/card-name',
validation: [
{
type: 'regex',
properties: {
regex: 'http(s)?://trello.com/c/([a-zA-Z0-9]{2,})/.*',
errorMessage: 'Not a valid Trello Card URL',
},
},
],
extractValue: {
type: 'regex',
regex: 'https://trello.com/c/([a-zA-Z0-9]{2,})',
},
},
{
displayName: 'ID',
name: 'id',
type: 'string',
validation: [
{
type: 'regex',
properties: {
regex: '[a-zA-Z0-9]{2,}',
errorMessage: 'Not a valid Trello Card ID',
},
},
],
placeholder: 'wiIaGwqE',
url: '=https://trello.com/c/{{$value}}',
},
],
displayOptions: {
show: {
operation: ['update', 'delete', 'create'],
resource: ['cardComment'],
},
},
description: 'The ID of the card',
},
// ----------------------------------
// cardComment:create
// ----------------------------------
{
displayName: 'Text',
name: 'text',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: ['create'],
resource: ['cardComment'],
},
},
description: 'Text of the comment',
},
// ----------------------------------
// cardComment:remove
// ----------------------------------
{
displayName: 'Comment ID',
name: 'commentId',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: ['delete'],
resource: ['cardComment'],
},
},
description: 'The ID of the comment to delete',
},
// ----------------------------------
// cardComment:update
// ----------------------------------
{
displayName: 'Comment ID',
name: 'commentId',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: ['update'],
resource: ['cardComment'],
},
},
description: 'The ID of the comment to delete',
},
{
displayName: 'Text',
name: 'text',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: ['update'],
resource: ['cardComment'],
},
},
description: 'Text of the comment',
},
];
@@ -0,0 +1,419 @@
import type { INodeProperties } from 'n8n-workflow';
export const cardOperations: INodeProperties[] = [
// ----------------------------------
// card
// ----------------------------------
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['card'],
},
},
options: [
{
name: 'Create',
value: 'create',
description: 'Create a new card',
action: 'Create a card',
},
{
name: 'Delete',
value: 'delete',
description: 'Delete a card',
action: 'Delete a card',
},
{
name: 'Get',
value: 'get',
description: 'Get the data of a card',
action: 'Get a card',
},
{
name: 'Update',
value: 'update',
description: 'Update a card',
action: 'Update a card',
},
],
default: 'create',
},
];
export const cardFields: INodeProperties[] = [
// ----------------------------------
// card:create
// ----------------------------------
{
displayName: 'List ID',
name: 'listId',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: ['create'],
resource: ['card'],
},
},
description: 'The ID of the list to create card in',
},
{
displayName: 'Name',
name: 'name',
type: 'string',
default: '',
placeholder: 'My card',
required: true,
displayOptions: {
show: {
operation: ['create'],
resource: ['card'],
},
},
description: 'The name of the card',
},
{
displayName: 'Description',
name: 'description',
type: 'string',
default: '',
displayOptions: {
show: {
operation: ['create'],
resource: ['card'],
},
},
description: 'The description of the card',
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
displayOptions: {
show: {
operation: ['create'],
resource: ['card'],
},
},
default: {},
options: [
{
displayName: 'Due Date',
name: 'due',
type: 'dateTime',
default: '',
description: 'A due date for the card',
},
{
displayName: 'Due Complete',
name: 'dueComplete',
type: 'boolean',
default: false,
description: 'Whether the card is completed',
},
{
displayName: 'Position',
name: 'pos',
type: 'string',
default: 'bottom',
description: 'The position of the new card. top, bottom, or a positive float.',
},
{
displayName: 'Member IDs',
name: 'idMembers',
type: 'string',
default: '',
description: 'Comma-separated list of member IDs to add to the card',
},
{
displayName: 'Label IDs',
name: 'idLabels',
type: 'string',
default: '',
description: 'Comma-separated list of label IDs to add to the card',
},
{
displayName: 'URL Source',
name: 'urlSource',
type: 'string',
default: '',
description: 'A source URL to attach to card',
},
{
displayName: 'Source ID',
name: 'idCardSource',
type: 'string',
default: '',
description: 'The ID of a card to copy into the new card',
},
{
displayName: 'Keep From Source',
name: 'keepFromSource',
type: 'string',
default: 'all',
description:
'If using idCardSource you can specify which properties to copy over. all or comma-separated list of: attachments, checklists, comments, due, labels, members, stickers.',
},
],
},
{
displayName: 'Card',
name: 'id',
type: 'resourceLocator',
default: { mode: 'list', value: '' },
required: true,
modes: [
{
displayName: 'From List',
name: 'list',
type: 'list',
placeholder: 'Select a Card...',
typeOptions: {
searchListMethod: 'searchCards',
searchFilterRequired: true,
searchable: true,
},
},
{
displayName: 'By URL',
name: 'url',
type: 'string',
placeholder: 'https://trello.com/c/e123456/card-name',
validation: [
{
type: 'regex',
properties: {
regex: 'http(s)?://trello.com/c/([a-zA-Z0-9]{2,})/.*',
errorMessage: 'Not a valid Trello Card URL',
},
},
],
extractValue: {
type: 'regex',
regex: 'https://trello.com/c/([a-zA-Z0-9]{2,})',
},
},
{
displayName: 'ID',
name: 'id',
type: 'string',
validation: [
{
type: 'regex',
properties: {
regex: '[a-zA-Z0-9]{2,}',
errorMessage: 'Not a valid Trello Card ID',
},
},
],
placeholder: 'wiIaGwqE',
url: '=https://trello.com/c/{{$value}}',
},
],
displayOptions: {
show: {
operation: ['get', 'delete', 'update'],
resource: ['card'],
},
},
description: 'The ID of the card',
},
// ----------------------------------
// card:get
// ----------------------------------
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
displayOptions: {
show: {
operation: ['get'],
resource: ['card'],
},
},
default: {},
options: [
{
displayName: 'Fields',
name: 'fields',
type: 'string',
default: 'all',
// eslint-disable-next-line n8n-nodes-base/node-param-description-miscased-url
description:
'Fields to return. Either "all" or a comma-separated list: badges, checkItemStates, closed, dateLastActivity, desc, descData, due, email, idBoard, idChecklists, idLabels, idList, idMembers, idShort, idAttachmentCover, manualCoverAttachment, labels, name, pos, shortUrl, url.',
},
{
displayName: 'Board',
name: 'board',
type: 'boolean',
default: false,
description: 'Whether to return the board object the card is on',
},
{
displayName: 'Board Fields',
name: 'board_fields',
type: 'string',
default: 'all',
// eslint-disable-next-line n8n-nodes-base/node-param-description-miscased-url
description:
'Fields to return. Either "all" or a comma-separated list: name, desc, descData, closed, idOrganization, pinned, url, prefs.',
},
{
displayName: 'Custom Field Items',
name: 'customFieldItems',
type: 'boolean',
default: false,
description: 'Whether to include the customFieldItems',
},
{
displayName: 'Members',
name: 'members',
type: 'boolean',
default: false,
description: 'Whether to return member objects for members on the card',
},
{
displayName: 'Member Fields',
name: 'member_fields',
type: 'string',
default: 'all',
description:
'Fields to return. Either "all" or a comma-separated list: avatarHash, fullName, initials, username.',
},
{
displayName: 'Plugin Data',
name: 'pluginData',
type: 'boolean',
default: false,
description: 'Whether to include pluginData on the card with the response',
},
{
displayName: 'Stickers',
name: 'stickers',
type: 'boolean',
default: false,
description: 'Whether to include sticker models with the response',
},
{
displayName: 'Sticker Fields',
name: 'sticker_fields',
type: 'string',
default: 'all',
description: 'Fields to return. Either "all" or a comma-separated list of sticker fields.',
},
],
},
// ----------------------------------
// card:update
// ----------------------------------
{
displayName: 'Update Fields',
name: 'updateFields',
type: 'collection',
placeholder: 'Add Field',
displayOptions: {
show: {
operation: ['update'],
resource: ['card'],
},
},
default: {},
options: [
{
displayName: 'Attachment Cover',
name: 'idAttachmentCover',
type: 'string',
default: '',
description:
'The ID of the image attachment the card should use as its cover, or null for none',
},
{
displayName: 'Board ID',
name: 'idBoard',
type: 'string',
default: '',
description: 'The ID of the board the card should be on',
},
{
displayName: 'Closed',
name: 'closed',
type: 'boolean',
default: false,
description: 'Whether the board is closed',
},
{
displayName: 'Description',
name: 'desc',
type: 'string',
default: '',
description: 'New description of the board',
},
{
displayName: 'Due Date',
name: 'due',
type: 'dateTime',
default: '',
description: 'A due date for the card',
},
{
displayName: 'Due Complete',
name: 'dueComplete',
type: 'boolean',
default: false,
description: 'Whether the card is completed',
},
{
displayName: 'Label IDs',
name: 'idLabels',
type: 'string',
default: '',
description: 'Comma-separated list of label IDs to set on card',
},
{
displayName: 'List ID',
name: 'idList',
type: 'string',
default: '',
description: 'The ID of the list the card should be in',
},
{
displayName: 'Member IDs',
name: 'idMembers',
type: 'string',
default: '',
description: 'Comma-separated list of member IDs to set on card',
},
{
displayName: 'Name',
name: 'name',
type: 'string',
default: '',
description: 'New name of the board',
},
{
displayName: 'Position',
name: 'pos',
type: 'string',
default: 'bottom',
description: 'The position of the card. top, bottom, or a positive float.',
},
{
displayName: 'Subscribed',
name: 'subscribed',
type: 'boolean',
default: false,
description: 'Whether the acting user is subscribed to the board',
},
],
},
];
@@ -0,0 +1,498 @@
import type { INodeProperties } from 'n8n-workflow';
export const checklistOperations: INodeProperties[] = [
// ----------------------------------
// checklist
// ----------------------------------
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['checklist'],
},
},
options: [
{
name: 'Create',
value: 'create',
description: 'Create a new checklist',
action: 'Create a checklist',
},
{
name: 'Create Checklist Item',
value: 'createCheckItem',
description: 'Create a checklist item',
action: 'Create checklist item',
},
{
name: 'Delete',
value: 'delete',
description: 'Delete a checklist',
action: 'Delete a checklist',
},
{
name: 'Delete Checklist Item',
value: 'deleteCheckItem',
description: 'Delete a checklist item',
action: 'Delete a checklist item',
},
{
name: 'Get',
value: 'get',
description: 'Get the data of a checklist',
action: 'Get a checklist',
},
{
name: 'Get Checklist Items',
value: 'getCheckItem',
description: 'Get a specific checklist on a card',
action: 'Get checklist items',
},
{
name: 'Get Completed Checklist Items',
value: 'completedCheckItems',
description: 'Get the completed checklist items on a card',
action: 'Get completed checklist items',
},
{
name: 'Get Many',
value: 'getAll',
description: 'Returns many checklists for the card',
action: 'Get many checklists',
},
{
name: 'Update Checklist Item',
value: 'updateCheckItem',
description: 'Update an item in a checklist on a card',
action: 'Update a checklist item',
},
],
default: 'getAll',
},
];
export const checklistFields: INodeProperties[] = [
{
displayName: 'Card',
name: 'cardId',
type: 'resourceLocator',
default: { mode: 'list', value: '' },
required: true,
modes: [
{
displayName: 'From List',
name: 'list',
type: 'list',
placeholder: 'Select a Card...',
typeOptions: {
searchListMethod: 'searchCards',
searchFilterRequired: true,
searchable: true,
},
},
{
displayName: 'By URL',
name: 'url',
type: 'string',
placeholder: 'https://trello.com/c/e123456/card-name',
validation: [
{
type: 'regex',
properties: {
regex: 'http(s)?://trello.com/c/([a-zA-Z0-9]{2,})/.*',
errorMessage: 'Not a valid Trello Card URL',
},
},
],
extractValue: {
type: 'regex',
regex: 'https://trello.com/c/([a-zA-Z0-9]{2,})',
},
},
{
displayName: 'ID',
name: 'id',
type: 'string',
validation: [
{
type: 'regex',
properties: {
regex: '[a-zA-Z0-9]{2,}',
errorMessage: 'Not a valid Trello Card ID',
},
},
],
placeholder: 'wiIaGwqE',
url: '=https://trello.com/c/{{$value}}',
},
],
displayOptions: {
show: {
operation: [
'delete',
'create',
'getAll',
'deleteCheckItem',
'getCheckItem',
'updateCheckItem',
'completeCheckItems',
],
resource: ['checklist'],
},
},
description: 'The ID of the card',
},
// ----------------------------------
// checklist:create
// ----------------------------------
{
displayName: 'Name',
name: 'name',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: ['create'],
resource: ['checklist'],
},
},
description: 'The URL of the checklist to add',
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
displayOptions: {
show: {
operation: ['create'],
resource: ['checklist'],
},
},
default: {},
options: [
{
displayName: 'ID Of Checklist Source',
name: 'idChecklistSource',
type: 'string',
default: '',
description: 'The ID of a source checklist to copy into the new one',
},
{
displayName: 'Position',
name: 'pos',
type: 'string',
default: '',
description:
'The position of the checklist on the card. One of: top, bottom, or a positive number.',
},
],
},
// ----------------------------------
// checklist:delete
// ----------------------------------
{
displayName: 'Checklist ID',
name: 'id',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: ['delete'],
resource: ['checklist'],
},
},
description: 'The ID of the checklist to delete',
},
// ----------------------------------
// checklist:getAll
// ----------------------------------
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
displayOptions: {
show: {
operation: ['getAll'],
resource: ['checklist'],
},
},
default: {},
options: [
{
displayName: 'Fields',
name: 'fields',
type: 'string',
default: 'all',
description: 'Fields to return. Either "all" or a comma-separated list of fields.',
},
],
},
// ----------------------------------
// checklist:get
// ----------------------------------
{
displayName: 'Checklist ID',
name: 'id',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: ['get'],
resource: ['checklist'],
},
},
description: 'The ID of the checklist to get',
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
displayOptions: {
show: {
operation: ['get'],
resource: ['checklist'],
},
},
default: {},
options: [
{
displayName: 'Fields',
name: 'fields',
type: 'string',
default: 'all',
description: 'Fields to return. Either "all" or a comma-separated list of fields.',
},
],
},
// ----------------------------------
// checklist:createCheckItem
// ----------------------------------
{
displayName: 'Checklist ID',
name: 'checklistId',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: ['createCheckItem'],
resource: ['checklist'],
},
},
description: 'The ID of the checklist to update',
},
{
displayName: 'Name',
name: 'name',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: ['createCheckItem'],
resource: ['checklist'],
},
},
description: 'The name of the new check item on the checklist',
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
displayOptions: {
show: {
operation: ['createCheckItem'],
resource: ['checklist'],
},
},
default: {},
options: [
{
displayName: 'Checked',
name: 'checked',
type: 'boolean',
default: false,
description: 'Whether the check item is already checked when created',
},
{
displayName: 'Position',
name: 'pos',
type: 'string',
default: '',
description:
'The position of the checklist on the card. One of: top, bottom, or a positive number.',
},
],
},
// ----------------------------------
// checklist:deleteCheckItem
// ----------------------------------
{
displayName: 'CheckItem ID',
name: 'checkItemId',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: ['deleteCheckItem'],
resource: ['checklist'],
},
},
description: 'The ID of the checklist item to delete',
},
// ----------------------------------
// checklist:getCheckItem
// ----------------------------------
{
displayName: 'CheckItem ID',
name: 'checkItemId',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: ['getCheckItem'],
resource: ['checklist'],
},
},
description: 'The ID of the checklist item to get',
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
displayOptions: {
show: {
operation: ['getCheckItem'],
resource: ['checklist'],
},
},
default: {},
options: [
{
displayName: 'Fields',
name: 'fields',
type: 'string',
default: 'all',
description: 'Fields to return. Either "all" or a comma-separated list of fields.',
},
],
},
// ----------------------------------
// checklist:updateCheckItem
// ----------------------------------
{
displayName: 'CheckItem ID',
name: 'checkItemId',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: ['updateCheckItem'],
resource: ['checklist'],
},
},
description: 'The ID of the checklist item to update',
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
displayOptions: {
show: {
operation: ['updateCheckItem'],
resource: ['checklist'],
},
},
default: {},
options: [
{
displayName: 'Name',
name: 'name',
type: 'string',
default: '',
description: 'The new name for the checklist item',
},
{
displayName: 'State',
name: 'state',
type: 'options',
options: [
{
name: 'Complete',
value: 'complete',
},
{
name: 'Incomplete',
value: 'incomplete',
},
],
default: 'complete',
},
{
displayName: 'Checklist ID',
name: 'checklistId',
type: 'string',
default: '',
description: 'The ID of the checklist this item is in',
},
{
displayName: 'Position',
name: 'pos',
type: 'string',
default: '',
description:
'The position of the checklist on the card. One of: top, bottom, or a positive number.',
},
],
},
// ----------------------------------
// checklist:completedCheckItems
// ----------------------------------
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
displayOptions: {
show: {
operation: ['completedCheckItems'],
resource: ['checklist'],
},
},
default: {},
options: [
{
displayName: 'Fields',
name: 'fields',
type: 'string',
default: 'all',
description:
'Fields to return. Either "all" or a comma-separated list of: "idCheckItem", "state".',
},
],
},
];
@@ -0,0 +1,62 @@
import type {
IDataObject,
IExecuteFunctions,
IHookFunctions,
IHttpRequestMethods,
ILoadOptionsFunctions,
IRequestOptions,
} from 'n8n-workflow';
/**
* Make an API request to Trello
*
*/
export async function apiRequest(
this: IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions,
method: IHttpRequestMethods,
endpoint: string,
body: object,
query?: IDataObject,
): Promise<any> {
query = query || {};
const options: IRequestOptions = {
method,
body,
qs: query,
uri: `https://api.trello.com/1/${endpoint}`,
json: true,
};
if (method === 'GET') {
delete options.body;
}
return await this.helpers.requestWithAuthentication.call(this, 'trelloApi', options);
}
export async function apiRequestAllItems(
this: IHookFunctions | IExecuteFunctions,
method: IHttpRequestMethods,
endpoint: string,
body: IDataObject,
query: IDataObject = {},
): Promise<any> {
query.limit = 30;
query.sort = '-id';
const returnData: IDataObject[] = [];
let responseData;
do {
responseData = await apiRequest.call(this, method, endpoint, body, query);
returnData.push.apply(returnData, responseData as IDataObject[]);
if (responseData.length !== 0) {
query.before = responseData[responseData.length - 1].id;
}
} while (query.limit <= responseData.length);
return returnData;
}
@@ -0,0 +1,483 @@
import type { INodeProperties } from 'n8n-workflow';
export const labelOperations: INodeProperties[] = [
// ----------------------------------
// label
// ----------------------------------
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['label'],
},
},
options: [
{
name: 'Add to Card',
value: 'addLabel',
description: 'Add a label to a card',
action: 'Add a label to a card',
},
{
name: 'Create',
value: 'create',
description: 'Create a new label',
action: 'Create a label',
},
{
name: 'Delete',
value: 'delete',
description: 'Delete a label',
action: 'Delete a label',
},
{
name: 'Get',
value: 'get',
description: 'Get the data of a label',
action: 'Get a label',
},
{
name: 'Get Many',
value: 'getAll',
description: 'Returns many labels for the board',
action: 'Get many labels',
},
{
name: 'Remove From Card',
value: 'removeLabel',
description: 'Remove a label from a card',
action: 'Remove a label from a card',
},
{
name: 'Update',
value: 'update',
description: 'Update a label',
action: 'Update a label',
},
],
default: 'getAll',
},
];
export const labelFields: INodeProperties[] = [
{
displayName: 'Board',
name: 'boardId',
type: 'resourceLocator',
default: { mode: 'list', value: '' },
required: true,
displayOptions: {
show: {
operation: ['create', 'getAll'],
resource: ['label'],
},
},
description: 'The ID of the board',
modes: [
{
displayName: 'From List',
name: 'list',
type: 'list',
placeholder: 'Select a Board...',
initType: 'board',
typeOptions: {
searchListMethod: 'searchBoards',
searchFilterRequired: true,
searchable: true,
},
},
{
displayName: 'By URL',
name: 'url',
type: 'string',
placeholder: 'https://trello.com/b/e123456/board-name',
validation: [
{
type: 'regex',
properties: {
regex: 'http(s)?://trello.com/b/([a-zA-Z0-9]{2,})/.*',
errorMessage: 'Not a valid Trello Board URL',
},
},
],
extractValue: {
type: 'regex',
regex: 'https://trello.com/b/([a-zA-Z0-9]{2,})',
},
},
{
displayName: 'ID',
name: 'id',
type: 'string',
validation: [
{
type: 'regex',
properties: {
regex: '[a-zA-Z0-9]{2,}',
errorMessage: 'Not a valid Trello Board ID',
},
},
],
placeholder: 'KdEAAdde',
url: '=https://trello.com/b/{{$value}}',
},
],
},
// ----------------------------------
// label:create
// ----------------------------------
{
displayName: 'Name',
name: 'name',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: ['create'],
resource: ['label'],
},
},
description: 'Name for the label',
},
{
displayName: 'Color',
name: 'color',
type: 'options',
required: true,
displayOptions: {
show: {
operation: ['create'],
resource: ['label'],
},
},
options: [
{
name: 'Black',
value: 'black',
},
{
name: 'Blue',
value: 'blue',
},
{
name: 'Green',
value: 'green',
},
{
name: 'Lime',
value: 'lime',
},
{
name: 'Null',
value: 'null',
},
{
name: 'Orange',
value: 'orange',
},
{
name: 'Pink',
value: 'pink',
},
{
name: 'Purple',
value: 'purple',
},
{
name: 'Red',
value: 'red',
},
{
name: 'Sky',
value: 'sky',
},
{
name: 'Yellow',
value: 'yellow',
},
],
default: 'null',
description: 'The color for the label',
},
// ----------------------------------
// label:delete
// ----------------------------------
{
displayName: 'Label ID',
name: 'id',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: ['delete'],
resource: ['label'],
},
},
description: 'The ID of the label to delete',
},
// ----------------------------------
// label:getAll
// ----------------------------------
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
displayOptions: {
show: {
operation: ['getAll'],
resource: ['label'],
},
},
default: {},
options: [
{
displayName: 'Fields',
name: 'fields',
type: 'string',
default: 'all',
description: 'Fields to return. Either "all" or a comma-separated list of fields.',
},
],
},
// ----------------------------------
// label:get
// ----------------------------------
{
displayName: 'Label ID',
name: 'id',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: ['get'],
resource: ['label'],
},
},
description: 'Get information about a label by ID',
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
displayOptions: {
show: {
operation: ['get'],
resource: ['label'],
},
},
default: {},
options: [
{
displayName: 'Fields',
name: 'fields',
type: 'string',
default: 'all',
description: 'Fields to return. Either "all" or a comma-separated list of fields.',
},
],
},
{
displayName: 'Card ID',
name: 'cardId',
type: 'resourceLocator',
default: { mode: 'list', value: '' },
required: true,
modes: [
{
displayName: 'From List',
name: 'list',
type: 'list',
placeholder: 'Choose...',
typeOptions: {
searchListMethod: 'searchCards',
searchFilterRequired: true,
searchable: true,
},
},
{
displayName: 'By URL',
name: 'url',
type: 'string',
placeholder: 'https://trello.com/c/e123456/card-name',
validation: [
{
type: 'regex',
properties: {
regex: 'http(s)?://trello.com/c/([a-zA-Z0-9]{2,})/.*',
errorMessage: 'Not a valid Trello Card URL',
},
},
],
extractValue: {
type: 'regex',
regex: 'https://trello.com/c/([a-zA-Z0-9]{2,})',
},
},
{
displayName: 'ID',
name: 'id',
type: 'string',
validation: [
{
type: 'regex',
properties: {
regex: '[a-zA-Z0-9]{2,}',
errorMessage: 'Not a valid Trello Card ID',
},
},
],
placeholder: 'wiIaGwqE',
url: '=https://trello.com/c/{{$value}}',
},
],
displayOptions: {
show: {
operation: ['addLabel', 'removeLabel'],
resource: ['label'],
},
},
description: 'The ID of the card',
},
// ----------------------------------
// label:addLabel
// ----------------------------------
{
displayName: 'Label ID',
name: 'id',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: ['addLabel'],
resource: ['label'],
},
},
description: 'The ID of the label to add',
},
// ----------------------------------
// label:removeLabel
// ----------------------------------
{
displayName: 'Label ID',
name: 'id',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: ['removeLabel'],
resource: ['label'],
},
},
description: 'The ID of the label to remove',
},
// ----------------------------------
// label:update
// ----------------------------------
{
displayName: 'Label ID',
name: 'id',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: ['update'],
resource: ['label'],
},
},
description: 'The ID of the label to update',
},
{
displayName: 'Update Fields',
name: 'updateFields',
type: 'collection',
placeholder: 'Add Field',
displayOptions: {
show: {
operation: ['update'],
resource: ['label'],
},
},
default: {},
options: [
{
displayName: 'Name',
name: 'name',
type: 'string',
default: '',
description: 'Name of the label',
},
{
displayName: 'Color',
name: 'color',
type: 'options',
options: [
{
name: 'Black',
value: 'black',
},
{
name: 'Blue',
value: 'blue',
},
{
name: 'Green',
value: 'green',
},
{
name: 'Lime',
value: 'lime',
},
{
name: 'Null',
value: 'null',
},
{
name: 'Orange',
value: 'orange',
},
{
name: 'Pink',
value: 'pink',
},
{
name: 'Purple',
value: 'purple',
},
{
name: 'Red',
value: 'red',
},
{
name: 'Sky',
value: 'sky',
},
{
name: 'Yellow',
value: 'yellow',
},
],
default: 'null',
description: 'The color for the label',
},
],
},
];
@@ -0,0 +1,399 @@
import type { INodeProperties } from 'n8n-workflow';
export const listOperations: INodeProperties[] = [
// ----------------------------------
// list
// ----------------------------------
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['list'],
},
},
options: [
{
name: 'Archive',
value: 'archive',
description: 'Archive/Unarchive a list',
action: 'Archive/unarchive a list',
},
{
name: 'Create',
value: 'create',
description: 'Create a new list',
action: 'Create a list',
},
{
name: 'Get',
value: 'get',
description: 'Get the data of a list',
action: 'Get a list',
},
{
name: 'Get Cards',
value: 'getCards',
description: 'Get all the cards in a list',
action: 'Get all cards in a list',
},
{
name: 'Get Many',
value: 'getAll',
description: 'Get many lists',
action: 'Get many lists',
},
{
name: 'Update',
value: 'update',
description: 'Update a list',
action: 'Update a list',
},
],
default: 'create',
},
];
export const listFields: INodeProperties[] = [
// ----------------------------------
// list:archive
// ----------------------------------
{
displayName: 'List ID',
name: 'id',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: ['archive'],
resource: ['list'],
},
},
description: 'The ID of the list to archive or unarchive',
},
{
displayName: 'Archive',
name: 'archive',
type: 'boolean',
default: false,
displayOptions: {
show: {
operation: ['archive'],
resource: ['list'],
},
},
description: 'Whether the list should be archived or unarchived',
},
// ----------------------------------
// list:create
// ----------------------------------
{
displayName: 'Board ID',
name: 'idBoard',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: ['create'],
resource: ['list'],
},
},
description: 'The ID of the board the list should be created in',
},
{
displayName: 'Name',
name: 'name',
type: 'string',
default: '',
placeholder: 'My list',
required: true,
displayOptions: {
show: {
operation: ['create'],
resource: ['list'],
},
},
description: 'The name of the list',
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
displayOptions: {
show: {
operation: ['create'],
resource: ['list'],
},
},
default: {},
options: [
{
displayName: 'List Source',
name: 'idListSource',
type: 'string',
default: '',
description: 'ID of the list to copy into the new list',
},
{
displayName: 'Position',
name: 'pos',
type: 'string',
default: 'bottom',
description: 'The position of the new list. top, bottom, or a positive float.',
},
],
},
// ----------------------------------
// list:getCards
// ----------------------------------
{
displayName: 'List ID',
name: 'id',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: ['getCards'],
resource: ['list'],
},
},
description: 'The ID of the list to get cards',
},
{
displayName: 'Return All',
name: 'returnAll',
type: 'boolean',
displayOptions: {
show: {
resource: ['list'],
operation: ['getCards'],
},
},
default: false,
description: 'Whether to return all results or only up to a given limit',
},
{
displayName: 'Limit',
name: 'limit',
type: 'number',
typeOptions: {
minValue: 1,
},
description: 'Max number of results to return',
default: 20,
displayOptions: {
show: {
resource: ['list'],
operation: ['getCards'],
returnAll: [false],
},
},
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
displayOptions: {
show: {
operation: ['getCards'],
resource: ['list'],
},
},
default: {},
options: [
{
displayName: 'Fields',
name: 'fields',
type: 'string',
default: 'all',
description: 'Fields to return. Either "all" or a comma-separated list of fields.',
},
],
},
// ----------------------------------
// list:get
// ----------------------------------
{
displayName: 'List ID',
name: 'id',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: ['get'],
resource: ['list'],
},
},
description: 'The ID of the list to get',
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
displayOptions: {
show: {
operation: ['get'],
resource: ['list'],
},
},
default: {},
options: [
{
displayName: 'Fields',
name: 'fields',
type: 'string',
default: 'all',
description: 'Fields to return. Either "all" or a comma-separated list of fields.',
},
],
},
// ----------------------------------
// list:getAll
// ----------------------------------
{
displayName: 'Board ID',
name: 'id',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: ['getAll'],
resource: ['list'],
},
},
description: 'The ID of the board',
},
{
displayName: 'Return All',
name: 'returnAll',
type: 'boolean',
displayOptions: {
show: {
resource: ['list'],
operation: ['getAll'],
},
},
default: false,
description: 'Whether to return all results or only up to a given limit',
},
{
displayName: 'Limit',
name: 'limit',
type: 'number',
typeOptions: {
minValue: 1,
},
description: 'Max number of results to return',
default: 20,
displayOptions: {
show: {
resource: ['list'],
operation: ['getAll'],
returnAll: [false],
},
},
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
displayOptions: {
show: {
operation: ['getAll'],
resource: ['list'],
},
},
default: {},
options: [
{
displayName: 'Fields',
name: 'fields',
type: 'string',
default: 'all',
description: 'Fields to return. Either "all" or a comma-separated list of fields.',
},
],
},
// ----------------------------------
// list:update
// ----------------------------------
{
displayName: 'List ID',
name: 'id',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: ['update'],
resource: ['list'],
},
},
description: 'The ID of the list to update',
},
{
displayName: 'Update Fields',
name: 'updateFields',
type: 'collection',
placeholder: 'Add Field',
displayOptions: {
show: {
operation: ['update'],
resource: ['list'],
},
},
default: {},
options: [
{
displayName: 'Board ID',
name: 'idBoard',
type: 'string',
default: '',
description: 'ID of a board the list should be moved to',
},
{
displayName: 'Closed',
name: 'closed',
type: 'boolean',
default: false,
description: 'Whether the list is closed',
},
{
displayName: 'Name',
name: 'name',
type: 'string',
default: '',
description: 'New name of the list',
},
{
displayName: 'Position',
name: 'pos',
type: 'string',
default: 'bottom',
description: 'The position of the list. top, bottom, or a positive float.',
},
{
displayName: 'Subscribed',
name: 'subscribed',
type: 'boolean',
default: false,
description: 'Whether the acting user is subscribed to the list',
},
],
},
];
@@ -0,0 +1,45 @@
{
"node": "n8n-nodes-base.trello",
"nodeVersion": "1.0",
"codexVersion": "1.0",
"categories": ["Productivity"],
"resources": {
"credentialDocumentation": [
{
"url": "https://docs.n8n.io/integrations/builtin/credentials/trello/"
}
],
"primaryDocumentation": [
{
"url": "https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.trello/"
}
],
"generic": [
{
"label": "6 e-commerce workflows to power up your Shopify s",
"icon": "store",
"url": "https://n8n.io/blog/no-code-ecommerce-workflow-automations/"
},
{
"label": "5 tasks you can automate with the new Notion API ",
"icon": "⚡️",
"url": "https://n8n.io/blog/5-tasks-you-can-automate-with-notion-api/"
},
{
"label": "Hey founders! Your business doesn't need you to operate",
"icon": " 🖥️",
"url": "https://n8n.io/blog/your-business-doesnt-need-you-to-operate/"
},
{
"label": "How a digital strategist uses n8n for online marketing",
"icon": "💻",
"url": "https://n8n.io/blog/how-a-digital-strategist-uses-n8n-for-online-marketing/"
},
{
"label": "Automating Conference Organization Processes with n8n",
"icon": "🙋‍♀️",
"url": "https://n8n.io/blog/automating-conference-organization-processes-with-n8n/"
}
]
}
}
@@ -0,0 +1,916 @@
import type {
IExecuteFunctions,
ILoadOptionsFunctions,
IDataObject,
INodeExecutionData,
INodeListSearchResult,
INodeType,
INodeTypeDescription,
IHttpRequestMethods,
} from 'n8n-workflow';
import { NodeConnectionTypes, NodeOperationError } from 'n8n-workflow';
import { attachmentFields, attachmentOperations } from './AttachmentDescription';
import { boardFields, boardOperations } from './BoardDescription';
import { boardMemberFields, boardMemberOperations } from './BoardMemberDescription';
import { cardCommentFields, cardCommentOperations } from './CardCommentDescription';
import { cardFields, cardOperations } from './CardDescription';
import { checklistFields, checklistOperations } from './ChecklistDescription';
import { apiRequest, apiRequestAllItems } from './GenericFunctions';
import { labelFields, labelOperations } from './LabelDescription';
import { listFields, listOperations } from './ListDescription';
interface TrelloBoardType {
id: string;
name: string;
url: string;
desc: string;
}
export class Trello implements INodeType {
description: INodeTypeDescription = {
displayName: 'Trello',
name: 'trello',
icon: 'file:trello.svg',
group: ['transform'],
version: 1,
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
description: 'Create, change and delete boards and cards',
defaults: {
name: 'Trello',
},
usableAsTool: true,
inputs: [NodeConnectionTypes.Main],
outputs: [NodeConnectionTypes.Main],
credentials: [
{
name: 'trelloApi',
required: true,
},
],
properties: [
{
displayName: 'Resource',
name: 'resource',
type: 'options',
noDataExpression: true,
options: [
{
name: 'Attachment',
value: 'attachment',
},
{
name: 'Board',
value: 'board',
},
{
name: 'Board Member',
value: 'boardMember',
},
{
name: 'Card',
value: 'card',
},
{
name: 'Card Comment',
value: 'cardComment',
},
{
name: 'Checklist',
value: 'checklist',
},
{
name: 'Label',
value: 'label',
},
{
name: 'List',
value: 'list',
},
],
default: 'card',
},
// ----------------------------------
// operations
// ----------------------------------
...attachmentOperations,
...boardOperations,
...boardMemberOperations,
...cardOperations,
...cardCommentOperations,
...checklistOperations,
...labelOperations,
...listOperations,
// ----------------------------------
// fields
// ----------------------------------
...attachmentFields,
...boardFields,
...boardMemberFields,
...cardFields,
...cardCommentFields,
...checklistFields,
...labelFields,
...listFields,
],
};
methods = {
listSearch: {
async searchBoards(
this: ILoadOptionsFunctions,
query?: string,
): Promise<INodeListSearchResult> {
if (!query) {
throw new NodeOperationError(this.getNode(), 'Query required for Trello search');
}
const searchResults = await apiRequest.call(
this,
'GET',
'search',
{},
{
query,
modelTypes: 'boards',
board_fields: 'name,url,desc',
// Enables partial word searching, only for the start of words though
partial: true,
// Seems like a good number since it isn't paginated. Default is 10.
boards_limit: 50,
},
);
return {
results: searchResults.boards.map((b: TrelloBoardType) => ({
name: b.name,
value: b.id,
url: b.url,
description: b.desc,
})),
};
},
async searchCards(
this: ILoadOptionsFunctions,
query?: string,
): Promise<INodeListSearchResult> {
if (!query) {
throw new NodeOperationError(this.getNode(), 'Query required for Trello search');
}
const searchResults = await apiRequest.call(
this,
'GET',
'search',
{},
{
query,
modelTypes: 'cards',
board_fields: 'name,url,desc',
// Enables partial word searching, only for the start of words though
partial: true,
// Seems like a good number since it isn't paginated. Default is 10.
cards_limit: 50,
},
);
return {
results: searchResults.cards.map((b: TrelloBoardType) => ({
name: b.name,
value: b.id,
url: b.url,
description: b.desc,
})),
};
},
},
};
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
const items = this.getInputData();
const returnData: INodeExecutionData[] = [];
const operation = this.getNodeParameter('operation', 0);
const resource = this.getNodeParameter('resource', 0);
// For Post
let body: IDataObject;
// For Query string
let qs: IDataObject;
let requestMethod: IHttpRequestMethods;
let endpoint: string;
let returnAll = false;
let responseData;
for (let i = 0; i < items.length; i++) {
try {
requestMethod = 'GET';
endpoint = '';
body = {};
qs = {};
if (resource === 'board') {
if (operation === 'create') {
// ----------------------------------
// create
// ----------------------------------
requestMethod = 'POST';
endpoint = 'boards';
body.name = this.getNodeParameter('name', i) as string;
body.desc = this.getNodeParameter('description', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i);
Object.assign(body, additionalFields);
} else if (operation === 'delete') {
// ----------------------------------
// delete
// ----------------------------------
requestMethod = 'DELETE';
const id = this.getNodeParameter('id', i, undefined, {
extractValue: true,
}) as string;
endpoint = `boards/${id}`;
} else if (operation === 'get') {
// ----------------------------------
// get
// ----------------------------------
requestMethod = 'GET';
const id = this.getNodeParameter('id', i, undefined, { extractValue: true });
endpoint = `boards/${id}`;
const additionalFields = this.getNodeParameter('additionalFields', i);
Object.assign(qs, additionalFields);
} else if (operation === 'update') {
// ----------------------------------
// update
// ----------------------------------
requestMethod = 'PUT';
const id = this.getNodeParameter('id', i, undefined, { extractValue: true });
endpoint = `boards/${id}`;
const updateFields = this.getNodeParameter('updateFields', i);
Object.assign(qs, updateFields);
} else {
throw new NodeOperationError(
this.getNode(),
`The operation "${operation}" is not known!`,
{ itemIndex: i },
);
}
} else if (resource === 'boardMember') {
if (operation === 'getAll') {
// ----------------------------------
// getAll
// ----------------------------------
requestMethod = 'GET';
const id = this.getNodeParameter('id', i) as string;
returnAll = this.getNodeParameter('returnAll', i);
if (!returnAll) {
qs.limit = this.getNodeParameter('limit', i);
}
endpoint = `boards/${id}/members`;
} else if (operation === 'add') {
// ----------------------------------
// add
// ----------------------------------
requestMethod = 'PUT';
const id = this.getNodeParameter('id', i) as string;
const idMember = this.getNodeParameter('idMember', i) as string;
endpoint = `boards/${id}/members/${idMember}`;
qs.type = this.getNodeParameter('type', i) as string;
qs.allowBillableGuest = this.getNodeParameter(
'additionalFields.allowBillableGuest',
i,
false,
) as boolean;
} else if (operation === 'invite') {
// ----------------------------------
// invite
// ----------------------------------
requestMethod = 'PUT';
const id = this.getNodeParameter('id', i) as string;
endpoint = `boards/${id}/members`;
const additionalFields = this.getNodeParameter('additionalFields', i);
qs.email = this.getNodeParameter('email', i) as string;
qs.type = additionalFields.type as string;
body.fullName = additionalFields.fullName as string;
} else if (operation === 'remove') {
// ----------------------------------
// remove
// ----------------------------------
requestMethod = 'DELETE';
const id = this.getNodeParameter('id', i) as string;
const idMember = this.getNodeParameter('idMember', i) as string;
endpoint = `boards/${id}/members/${idMember}`;
} else {
throw new NodeOperationError(
this.getNode(),
`The operation "${operation}" is not known!`,
{ itemIndex: i },
);
}
} else if (resource === 'card') {
if (operation === 'create') {
// ----------------------------------
// create
// ----------------------------------
requestMethod = 'POST';
endpoint = 'cards';
body.idList = this.getNodeParameter('listId', i) as string;
body.name = this.getNodeParameter('name', i) as string;
body.desc = this.getNodeParameter('description', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i);
Object.assign(body, additionalFields);
} else if (operation === 'delete') {
// ----------------------------------
// delete
// ----------------------------------
requestMethod = 'DELETE';
const id = this.getNodeParameter('id', i, undefined, { extractValue: true });
endpoint = `cards/${id}`;
} else if (operation === 'get') {
// ----------------------------------
// get
// ----------------------------------
requestMethod = 'GET';
const id = this.getNodeParameter('id', i, undefined, { extractValue: true });
endpoint = `cards/${id}`;
const additionalFields = this.getNodeParameter('additionalFields', i);
Object.assign(qs, additionalFields);
} else if (operation === 'update') {
// ----------------------------------
// update
// ----------------------------------
requestMethod = 'PUT';
const id = this.getNodeParameter('id', i, undefined, { extractValue: true });
endpoint = `cards/${id}`;
const updateFields = this.getNodeParameter('updateFields', i);
Object.assign(qs, updateFields);
} else {
throw new NodeOperationError(
this.getNode(),
`The operation "${operation}" is not known!`,
{ itemIndex: i },
);
}
} else if (resource === 'cardComment') {
if (operation === 'create') {
// ----------------------------------
// create
// ----------------------------------
const cardId = this.getNodeParameter('cardId', i, undefined, {
extractValue: true,
}) as string;
body.text = this.getNodeParameter('text', i) as string;
requestMethod = 'POST';
endpoint = `cards/${cardId}/actions/comments`;
} else if (operation === 'delete') {
// ----------------------------------
// delete
// ----------------------------------
requestMethod = 'DELETE';
const cardId = this.getNodeParameter('cardId', i, undefined, {
extractValue: true,
}) as string;
const commentId = this.getNodeParameter('commentId', i) as string;
endpoint = `/cards/${cardId}/actions/${commentId}/comments`;
} else if (operation === 'update') {
// ----------------------------------
// update
// ----------------------------------
requestMethod = 'PUT';
const cardId = this.getNodeParameter('cardId', i, undefined, {
extractValue: true,
}) as string;
const commentId = this.getNodeParameter('commentId', i) as string;
qs.text = this.getNodeParameter('text', i) as string;
endpoint = `cards/${cardId}/actions/${commentId}/comments`;
} else {
throw new NodeOperationError(
this.getNode(),
`The operation "${operation}" is not known!`,
{ itemIndex: i },
);
}
} else if (resource === 'list') {
if (operation === 'archive') {
// ----------------------------------
// archive
// ----------------------------------
requestMethod = 'PUT';
const id = this.getNodeParameter('id', i) as string;
qs.value = this.getNodeParameter('archive', i) as boolean;
endpoint = `lists/${id}/closed`;
} else if (operation === 'create') {
// ----------------------------------
// create
// ----------------------------------
requestMethod = 'POST';
endpoint = 'lists';
body.idBoard = this.getNodeParameter('idBoard', i) as string;
body.name = this.getNodeParameter('name', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i);
Object.assign(body, additionalFields);
} else if (operation === 'get') {
// ----------------------------------
// get
// ----------------------------------
requestMethod = 'GET';
const id = this.getNodeParameter('id', i) as string;
endpoint = `lists/${id}`;
const additionalFields = this.getNodeParameter('additionalFields', i);
Object.assign(qs, additionalFields);
} else if (operation === 'getAll') {
// ----------------------------------
// getAll
// ----------------------------------
requestMethod = 'GET';
returnAll = this.getNodeParameter('returnAll', i);
if (!returnAll) {
qs.limit = this.getNodeParameter('limit', i);
}
const id = this.getNodeParameter('id', i) as string;
endpoint = `boards/${id}/lists`;
const additionalFields = this.getNodeParameter('additionalFields', i);
Object.assign(qs, additionalFields);
} else if (operation === 'getCards') {
// ----------------------------------
// getCards
// ----------------------------------
requestMethod = 'GET';
returnAll = this.getNodeParameter('returnAll', i);
if (!returnAll) {
qs.limit = this.getNodeParameter('limit', i);
}
const id = this.getNodeParameter('id', i) as string;
endpoint = `lists/${id}/cards`;
const additionalFields = this.getNodeParameter('additionalFields', i);
Object.assign(qs, additionalFields);
} else if (operation === 'update') {
// ----------------------------------
// update
// ----------------------------------
requestMethod = 'PUT';
const id = this.getNodeParameter('id', i) as string;
endpoint = `lists/${id}`;
const updateFields = this.getNodeParameter('updateFields', i);
Object.assign(qs, updateFields);
} else {
throw new NodeOperationError(
this.getNode(),
`The operation "${operation}" is not known!`,
{ itemIndex: i },
);
}
} else if (resource === 'attachment') {
if (operation === 'create') {
// ----------------------------------
// create
// ----------------------------------
requestMethod = 'POST';
const cardId = this.getNodeParameter('cardId', i, undefined, {
extractValue: true,
}) as string;
const url = this.getNodeParameter('url', i) as string;
Object.assign(body, {
url,
});
const additionalFields = this.getNodeParameter('additionalFields', i);
Object.assign(body, additionalFields);
endpoint = `cards/${cardId}/attachments`;
} else if (operation === 'delete') {
// ----------------------------------
// delete
// ----------------------------------
requestMethod = 'DELETE';
const cardId = this.getNodeParameter('cardId', i, undefined, {
extractValue: true,
}) as string;
const id = this.getNodeParameter('id', i) as string;
endpoint = `cards/${cardId}/attachments/${id}`;
} else if (operation === 'get') {
// ----------------------------------
// get
// ----------------------------------
requestMethod = 'GET';
const cardId = this.getNodeParameter('cardId', i, undefined, {
extractValue: true,
}) as string;
const id = this.getNodeParameter('id', i) as string;
endpoint = `cards/${cardId}/attachments/${id}`;
const additionalFields = this.getNodeParameter('additionalFields', i);
Object.assign(qs, additionalFields);
} else if (operation === 'getAll') {
// ----------------------------------
// getAll
// ----------------------------------
requestMethod = 'GET';
const cardId = this.getNodeParameter('cardId', i, undefined, {
extractValue: true,
}) as string;
endpoint = `cards/${cardId}/attachments`;
const additionalFields = this.getNodeParameter('additionalFields', i);
Object.assign(qs, additionalFields);
} else {
throw new NodeOperationError(
this.getNode(),
`The operation "${operation}" is not known!`,
{ itemIndex: i },
);
}
} else if (resource === 'checklist') {
if (operation === 'create') {
// ----------------------------------
// create
// ----------------------------------
requestMethod = 'POST';
const cardId = this.getNodeParameter('cardId', i, undefined, {
extractValue: true,
}) as string;
const name = this.getNodeParameter('name', i) as string;
Object.assign(body, { name });
const additionalFields = this.getNodeParameter('additionalFields', i);
Object.assign(body, additionalFields);
endpoint = `cards/${cardId}/checklists`;
} else if (operation === 'delete') {
// ----------------------------------
// delete
// ----------------------------------
requestMethod = 'DELETE';
const cardId = this.getNodeParameter('cardId', i, undefined, {
extractValue: true,
}) as string;
const id = this.getNodeParameter('id', i) as string;
endpoint = `cards/${cardId}/checklists/${id}`;
} else if (operation === 'get') {
// ----------------------------------
// get
// ----------------------------------
requestMethod = 'GET';
const id = this.getNodeParameter('id', i) as string;
endpoint = `checklists/${id}`;
const additionalFields = this.getNodeParameter('additionalFields', i);
Object.assign(qs, additionalFields);
} else if (operation === 'getAll') {
// ----------------------------------
// getAll
// ----------------------------------
requestMethod = 'GET';
const cardId = this.getNodeParameter('cardId', i, undefined, {
extractValue: true,
}) as string;
endpoint = `cards/${cardId}/checklists`;
const additionalFields = this.getNodeParameter('additionalFields', i);
Object.assign(qs, additionalFields);
} else if (operation === 'getCheckItem') {
// ----------------------------------
// getCheckItem
// ----------------------------------
requestMethod = 'GET';
const cardId = this.getNodeParameter('cardId', i, undefined, {
extractValue: true,
}) as string;
const checkItemId = this.getNodeParameter('checkItemId', i) as string;
endpoint = `cards/${cardId}/checkItem/${checkItemId}`;
const additionalFields = this.getNodeParameter('additionalFields', i);
Object.assign(qs, additionalFields);
} else if (operation === 'createCheckItem') {
// ----------------------------------
// createCheckItem
// ----------------------------------
requestMethod = 'POST';
const checklistId = this.getNodeParameter('checklistId', i) as string;
endpoint = `checklists/${checklistId}/checkItems`;
const name = this.getNodeParameter('name', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i);
Object.assign(body, { name, ...additionalFields });
} else if (operation === 'deleteCheckItem') {
// ----------------------------------
// deleteCheckItem
// ----------------------------------
requestMethod = 'DELETE';
const cardId = this.getNodeParameter('cardId', i, undefined, {
extractValue: true,
}) as string;
const checkItemId = this.getNodeParameter('checkItemId', i) as string;
endpoint = `cards/${cardId}/checkItem/${checkItemId}`;
} else if (operation === 'updateCheckItem') {
// ----------------------------------
// updateCheckItem
// ----------------------------------
requestMethod = 'PUT';
const cardId = this.getNodeParameter('cardId', i, undefined, {
extractValue: true,
}) as string;
const checkItemId = this.getNodeParameter('checkItemId', i) as string;
endpoint = `cards/${cardId}/checkItem/${checkItemId}`;
const additionalFields = this.getNodeParameter('additionalFields', i);
Object.assign(qs, additionalFields);
} else if (operation === 'completedCheckItems') {
// ----------------------------------
// completedCheckItems
// ----------------------------------
requestMethod = 'GET';
const cardId = this.getNodeParameter('cardId', i, undefined, {
extractValue: true,
}) as string;
endpoint = `cards/${cardId}/checkItemStates`;
const additionalFields = this.getNodeParameter('additionalFields', i);
Object.assign(qs, additionalFields);
} else {
throw new NodeOperationError(
this.getNode(),
`The operation "${operation}" is not known!`,
{ itemIndex: i },
);
}
} else if (resource === 'label') {
if (operation === 'create') {
// ----------------------------------
// create
// ----------------------------------
requestMethod = 'POST';
const idBoard = this.getNodeParameter('boardId', i, undefined, {
extractValue: true,
}) as string;
const name = this.getNodeParameter('name', i) as string;
const color = this.getNodeParameter('color', i) as string;
Object.assign(body, {
idBoard,
name,
color,
});
endpoint = 'labels';
} else if (operation === 'delete') {
// ----------------------------------
// delete
// ----------------------------------
requestMethod = 'DELETE';
const id = this.getNodeParameter('id', i) as string;
endpoint = `labels/${id}`;
} else if (operation === 'get') {
// ----------------------------------
// get
// ----------------------------------
requestMethod = 'GET';
const id = this.getNodeParameter('id', i) as string;
endpoint = `labels/${id}`;
const additionalFields = this.getNodeParameter('additionalFields', i);
Object.assign(qs, additionalFields);
} else if (operation === 'getAll') {
// ----------------------------------
// getAll
// ----------------------------------
requestMethod = 'GET';
const idBoard = this.getNodeParameter('boardId', i, undefined, {
extractValue: true,
}) as string;
endpoint = `board/${idBoard}/labels`;
const additionalFields = this.getNodeParameter('additionalFields', i);
Object.assign(qs, additionalFields);
} else if (operation === 'update') {
// ----------------------------------
// update
// ----------------------------------
requestMethod = 'PUT';
const id = this.getNodeParameter('id', i) as string;
endpoint = `labels/${id}`;
const updateFields = this.getNodeParameter('updateFields', i);
Object.assign(qs, updateFields);
} else if (operation === 'addLabel') {
// ----------------------------------
// addLabel
// ----------------------------------
requestMethod = 'POST';
const cardId = this.getNodeParameter('cardId', i, undefined, {
extractValue: true,
}) as string;
const id = this.getNodeParameter('id', i) as string;
body.value = id;
endpoint = `/cards/${cardId}/idLabels`;
} else if (operation === 'removeLabel') {
// ----------------------------------
// removeLabel
// ----------------------------------
requestMethod = 'DELETE';
const cardId = this.getNodeParameter('cardId', i, undefined, {
extractValue: true,
}) as string;
const id = this.getNodeParameter('id', i) as string;
endpoint = `/cards/${cardId}/idLabels/${id}`;
} else {
throw new NodeOperationError(
this.getNode(),
`The operation "${operation}" is not known!`,
{ itemIndex: i },
);
}
} else {
throw new NodeOperationError(this.getNode(), `The resource "${resource}" is not known!`, {
itemIndex: i,
});
}
// resources listed here do not support pagination so
// paginate them 'manually'
const skipPagination = ['list:getAll'];
if (returnAll && !skipPagination.includes(`${resource}:${operation}`)) {
responseData = await apiRequestAllItems.call(this, requestMethod, endpoint, body, qs);
} else {
responseData = await apiRequest.call(this, requestMethod, endpoint, body, qs);
if (!returnAll && qs.limit) {
responseData = responseData.splice(0, qs.limit);
}
}
const executionData = this.helpers.constructExecutionMetaData(
this.helpers.returnJsonArray(responseData as IDataObject[]),
{ itemData: { item: i } },
);
returnData.push(...executionData);
} catch (error) {
if (this.continueOnFail()) {
const executionData = this.helpers.constructExecutionMetaData(
this.helpers.returnJsonArray({ error: error.message }),
{ itemData: { item: i } },
);
returnData.push(...executionData);
continue;
}
throw error;
}
}
return [returnData];
}
}
@@ -0,0 +1,25 @@
{
"node": "n8n-nodes-base.trelloTrigger",
"nodeVersion": "1.0",
"codexVersion": "1.0",
"categories": ["Productivity"],
"resources": {
"credentialDocumentation": [
{
"url": "https://docs.n8n.io/integrations/builtin/credentials/trello/"
}
],
"primaryDocumentation": [
{
"url": "https://docs.n8n.io/integrations/builtin/trigger-nodes/n8n-nodes-base.trellotrigger/"
}
],
"generic": [
{
"label": "Hey founders! Your business doesn't need you to operate",
"icon": " 🖥️",
"url": "https://n8n.io/blog/your-business-doesnt-need-you-to-operate/"
}
]
}
}
@@ -0,0 +1,170 @@
import {
type IHookFunctions,
type IWebhookFunctions,
type INodeType,
type INodeTypeDescription,
type IWebhookResponseData,
NodeConnectionTypes,
} from 'n8n-workflow';
import { apiRequest } from './GenericFunctions';
// import { createHmac } from 'crypto';
export class TrelloTrigger implements INodeType {
description: INodeTypeDescription = {
displayName: 'Trello Trigger',
name: 'trelloTrigger',
icon: 'file:trello.svg',
group: ['trigger'],
version: 1,
description: 'Starts the workflow when Trello events occur',
defaults: {
name: 'Trello Trigger',
},
inputs: [],
outputs: [NodeConnectionTypes.Main],
credentials: [
{
name: 'trelloApi',
required: true,
},
],
webhooks: [
{
name: 'setup',
httpMethod: 'HEAD',
responseMode: 'onReceived',
path: 'webhook',
},
{
name: 'default',
httpMethod: 'POST',
responseMode: 'onReceived',
path: 'webhook',
},
],
properties: [
{
displayName: 'Model ID',
name: 'id',
type: 'string',
default: '',
placeholder: '4d5ea62fd76aa1136000000c',
required: true,
description: 'ID of the model of which to subscribe to events',
},
],
};
webhookMethods = {
default: {
async checkExists(this: IHookFunctions): Promise<boolean> {
const credentials = await this.getCredentials('trelloApi');
// Check all the webhooks which exist already if it is identical to the
// one that is supposed to get created.
const endpoint = `tokens/${credentials.apiToken}/webhooks`;
const responseData = await apiRequest.call(this, 'GET', endpoint, {});
const idModel = this.getNodeParameter('id') as string;
const webhookUrl = this.getNodeWebhookUrl('default');
for (const webhook of responseData) {
if (webhook.idModel === idModel && webhook.callbackURL === webhookUrl) {
// Set webhook-id to be sure that it can be deleted
const webhookData = this.getWorkflowStaticData('node');
webhookData.webhookId = webhook.id as string;
return true;
}
}
return false;
},
async create(this: IHookFunctions): Promise<boolean> {
const webhookUrl = this.getNodeWebhookUrl('default');
const credentials = await this.getCredentials('trelloApi');
const idModel = this.getNodeParameter('id') as string;
const endpoint = `tokens/${credentials.apiToken}/webhooks`;
const body = {
description: `n8n Webhook - ${idModel}`,
callbackURL: webhookUrl,
idModel,
};
const responseData = await apiRequest.call(this, 'POST', endpoint, body);
if (responseData.id === undefined) {
// Required data is missing so was not successful
return false;
}
const webhookData = this.getWorkflowStaticData('node');
webhookData.webhookId = responseData.id as string;
return true;
},
async delete(this: IHookFunctions): Promise<boolean> {
const webhookData = this.getWorkflowStaticData('node');
if (webhookData.webhookId !== undefined) {
const credentials = await this.getCredentials('trelloApi');
const endpoint = `tokens/${credentials.apiToken}/webhooks/${webhookData.webhookId}`;
const body = {};
try {
await apiRequest.call(this, 'DELETE', endpoint, body);
} catch (error) {
return false;
}
// Remove from the static workflow data so that it is clear
// that no webhooks are registered anymore
delete webhookData.webhookId;
}
return true;
},
},
};
async webhook(this: IWebhookFunctions): Promise<IWebhookResponseData> {
const webhookName = this.getWebhookName();
if (webhookName === 'setup') {
// Is a create webhook confirmation request
const res = this.getResponseObject();
res.status(200).end();
return {
noWebhookResponse: true,
};
}
const bodyData = this.getBodyData();
// TODO: Check why that does not work as expected even though it gets done as described
// https://developers.trello.com/page/webhooks
//const credentials = await this.getCredentials('trelloApi');
// // Check if the request is valid
// const headerData = this.getHeaderData() as IDataObject;
// const webhookUrl = this.getNodeWebhookUrl('default');
// const checkContent = JSON.stringify(bodyData) + webhookUrl;
// const computedSignature = createHmac('sha1', credentials.oauthSecret as string).update(checkContent).digest('base64');
// if (headerData['x-trello-webhook'] !== computedSignature) {
// // Signature is not valid so ignore call
// return {};
// }
return {
workflowData: [this.helpers.returnJsonArray(bodyData)],
};
}
}
@@ -0,0 +1,62 @@
{
"type": "object",
"properties": {
"date": {
"type": "string"
},
"id": {
"type": "string"
},
"idMember": {
"type": "string"
},
"isMalicious": {
"type": "boolean"
},
"isUpload": {
"type": "boolean"
},
"mimeType": {
"type": "string"
},
"name": {
"type": "string"
},
"pos": {
"type": "integer"
},
"previews": {
"type": "array",
"items": {
"type": "object",
"properties": {
"_id": {
"type": "string"
},
"bytes": {
"type": "integer"
},
"height": {
"type": "integer"
},
"id": {
"type": "string"
},
"scaled": {
"type": "boolean"
},
"url": {
"type": "string"
},
"width": {
"type": "integer"
}
}
}
},
"url": {
"type": "string"
}
},
"version": 1
}
@@ -0,0 +1,65 @@
{
"type": "object",
"properties": {
"date": {
"type": "string"
},
"fileName": {
"type": "string"
},
"id": {
"type": "string"
},
"idMember": {
"type": "string"
},
"isMalicious": {
"type": "boolean"
},
"isUpload": {
"type": "boolean"
},
"mimeType": {
"type": "string"
},
"name": {
"type": "string"
},
"pos": {
"type": "integer"
},
"previews": {
"type": "array",
"items": {
"type": "object",
"properties": {
"_id": {
"type": "string"
},
"bytes": {
"type": "integer"
},
"height": {
"type": "integer"
},
"id": {
"type": "string"
},
"scaled": {
"type": "boolean"
},
"url": {
"type": "string"
},
"width": {
"type": "integer"
}
}
}
},
"url": {
"type": "string"
}
},
"version": 2
}
@@ -0,0 +1,62 @@
{
"type": "object",
"properties": {
"date": {
"type": "string"
},
"fileName": {
"type": "string"
},
"id": {
"type": "string"
},
"idMember": {
"type": "string"
},
"isUpload": {
"type": "boolean"
},
"mimeType": {
"type": "string"
},
"name": {
"type": "string"
},
"pos": {
"type": "integer"
},
"previews": {
"type": "array",
"items": {
"type": "object",
"properties": {
"_id": {
"type": "string"
},
"bytes": {
"type": "integer"
},
"height": {
"type": "integer"
},
"id": {
"type": "string"
},
"scaled": {
"type": "boolean"
},
"url": {
"type": "string"
},
"width": {
"type": "integer"
}
}
}
},
"url": {
"type": "string"
}
},
"version": 1
}
@@ -0,0 +1,219 @@
{
"type": "object",
"properties": {
"closed": {
"type": "boolean"
},
"desc": {
"type": "string"
},
"descData": {
"type": "null"
},
"id": {
"type": "string"
},
"idEnterprise": {
"type": "null"
},
"idOrganization": {
"type": "string"
},
"labelNames": {
"type": "object",
"properties": {
"black": {
"type": "string"
},
"black_dark": {
"type": "string"
},
"black_light": {
"type": "string"
},
"blue": {
"type": "string"
},
"blue_dark": {
"type": "string"
},
"blue_light": {
"type": "string"
},
"green": {
"type": "string"
},
"green_dark": {
"type": "string"
},
"green_light": {
"type": "string"
},
"lime": {
"type": "string"
},
"lime_dark": {
"type": "string"
},
"lime_light": {
"type": "string"
},
"orange": {
"type": "string"
},
"orange_dark": {
"type": "string"
},
"orange_light": {
"type": "string"
},
"pink": {
"type": "string"
},
"pink_dark": {
"type": "string"
},
"pink_light": {
"type": "string"
},
"purple": {
"type": "string"
},
"purple_dark": {
"type": "string"
},
"purple_light": {
"type": "string"
},
"red": {
"type": "string"
},
"red_dark": {
"type": "string"
},
"red_light": {
"type": "string"
},
"sky": {
"type": "string"
},
"sky_dark": {
"type": "string"
},
"sky_light": {
"type": "string"
},
"yellow": {
"type": "string"
},
"yellow_dark": {
"type": "string"
},
"yellow_light": {
"type": "string"
}
}
},
"name": {
"type": "string"
},
"pinned": {
"type": "boolean"
},
"prefs": {
"type": "object",
"properties": {
"background": {
"type": "string"
},
"backgroundBottomColor": {
"type": "string"
},
"backgroundBrightness": {
"type": "string"
},
"backgroundDarkImage": {
"type": "null"
},
"backgroundTile": {
"type": "boolean"
},
"backgroundTopColor": {
"type": "string"
},
"calendarFeedEnabled": {
"type": "boolean"
},
"canBeEnterprise": {
"type": "boolean"
},
"canBeOrg": {
"type": "boolean"
},
"canBePrivate": {
"type": "boolean"
},
"canBePublic": {
"type": "boolean"
},
"canInvite": {
"type": "boolean"
},
"cardAging": {
"type": "string"
},
"cardCounts": {
"type": "boolean"
},
"cardCovers": {
"type": "boolean"
},
"comments": {
"type": "string"
},
"hideVotes": {
"type": "boolean"
},
"invitations": {
"type": "string"
},
"isTemplate": {
"type": "boolean"
},
"permissionLevel": {
"type": "string"
},
"selfJoin": {
"type": "boolean"
},
"showCompleteStatus": {
"type": "boolean"
},
"switcherViews": {
"type": "array",
"items": {
"type": "object",
"properties": {
"enabled": {
"type": "boolean"
},
"viewType": {
"type": "string"
}
}
}
},
"voting": {
"type": "string"
}
}
},
"shortUrl": {
"type": "string"
},
"url": {
"type": "string"
}
},
"version": 1
}
@@ -0,0 +1,219 @@
{
"type": "object",
"properties": {
"closed": {
"type": "boolean"
},
"desc": {
"type": "string"
},
"id": {
"type": "string"
},
"idEnterprise": {
"type": "null"
},
"idOrganization": {
"type": "string"
},
"labelNames": {
"type": "object",
"properties": {
"black": {
"type": "string"
},
"black_dark": {
"type": "string"
},
"black_light": {
"type": "string"
},
"blue": {
"type": "string"
},
"blue_dark": {
"type": "string"
},
"blue_light": {
"type": "string"
},
"green": {
"type": "string"
},
"green_dark": {
"type": "string"
},
"green_light": {
"type": "string"
},
"lime": {
"type": "string"
},
"lime_dark": {
"type": "string"
},
"lime_light": {
"type": "string"
},
"orange": {
"type": "string"
},
"orange_dark": {
"type": "string"
},
"orange_light": {
"type": "string"
},
"pink": {
"type": "string"
},
"pink_dark": {
"type": "string"
},
"pink_light": {
"type": "string"
},
"purple": {
"type": "string"
},
"purple_dark": {
"type": "string"
},
"purple_light": {
"type": "string"
},
"red": {
"type": "string"
},
"red_dark": {
"type": "string"
},
"red_light": {
"type": "string"
},
"sky": {
"type": "string"
},
"sky_dark": {
"type": "string"
},
"sky_light": {
"type": "string"
},
"yellow": {
"type": "string"
},
"yellow_dark": {
"type": "string"
},
"yellow_light": {
"type": "string"
}
}
},
"name": {
"type": "string"
},
"pinned": {
"type": "boolean"
},
"prefs": {
"type": "object",
"properties": {
"background": {
"type": "string"
},
"backgroundBottomColor": {
"type": "string"
},
"backgroundBrightness": {
"type": "string"
},
"backgroundTile": {
"type": "boolean"
},
"backgroundTopColor": {
"type": "string"
},
"calendarFeedEnabled": {
"type": "boolean"
},
"canBeEnterprise": {
"type": "boolean"
},
"canBeOrg": {
"type": "boolean"
},
"canBePrivate": {
"type": "boolean"
},
"canBePublic": {
"type": "boolean"
},
"canInvite": {
"type": "boolean"
},
"cardAging": {
"type": "string"
},
"cardCounts": {
"type": "boolean"
},
"cardCovers": {
"type": "boolean"
},
"comments": {
"type": "string"
},
"hiddenPluginBoardButtons": {
"type": "array",
"items": {
"type": "string"
}
},
"hideVotes": {
"type": "boolean"
},
"invitations": {
"type": "string"
},
"isTemplate": {
"type": "boolean"
},
"permissionLevel": {
"type": "string"
},
"selfJoin": {
"type": "boolean"
},
"showCompleteStatus": {
"type": "boolean"
},
"switcherViews": {
"type": "array",
"items": {
"type": "object",
"properties": {
"enabled": {
"type": "boolean"
},
"viewType": {
"type": "string"
}
}
}
},
"voting": {
"type": "string"
}
}
},
"shortUrl": {
"type": "string"
},
"url": {
"type": "string"
}
},
"version": 1
}
@@ -0,0 +1,210 @@
{
"type": "object",
"properties": {
"closed": {
"type": "boolean"
},
"desc": {
"type": "string"
},
"id": {
"type": "string"
},
"idEnterprise": {
"type": "null"
},
"idOrganization": {
"type": "string"
},
"labelNames": {
"type": "object",
"properties": {
"black": {
"type": "string"
},
"black_dark": {
"type": "string"
},
"black_light": {
"type": "string"
},
"blue": {
"type": "string"
},
"blue_dark": {
"type": "string"
},
"blue_light": {
"type": "string"
},
"green": {
"type": "string"
},
"green_dark": {
"type": "string"
},
"green_light": {
"type": "string"
},
"lime": {
"type": "string"
},
"lime_dark": {
"type": "string"
},
"lime_light": {
"type": "string"
},
"orange": {
"type": "string"
},
"orange_dark": {
"type": "string"
},
"orange_light": {
"type": "string"
},
"pink": {
"type": "string"
},
"pink_dark": {
"type": "string"
},
"pink_light": {
"type": "string"
},
"purple": {
"type": "string"
},
"purple_dark": {
"type": "string"
},
"purple_light": {
"type": "string"
},
"red": {
"type": "string"
},
"red_dark": {
"type": "string"
},
"red_light": {
"type": "string"
},
"sky": {
"type": "string"
},
"sky_dark": {
"type": "string"
},
"sky_light": {
"type": "string"
},
"yellow": {
"type": "string"
},
"yellow_dark": {
"type": "string"
},
"yellow_light": {
"type": "string"
}
}
},
"name": {
"type": "string"
},
"pinned": {
"type": "boolean"
},
"prefs": {
"type": "object",
"properties": {
"background": {
"type": "string"
},
"backgroundBottomColor": {
"type": "string"
},
"backgroundBrightness": {
"type": "string"
},
"backgroundTile": {
"type": "boolean"
},
"backgroundTopColor": {
"type": "string"
},
"calendarFeedEnabled": {
"type": "boolean"
},
"canBeEnterprise": {
"type": "boolean"
},
"canBeOrg": {
"type": "boolean"
},
"canBePrivate": {
"type": "boolean"
},
"canBePublic": {
"type": "boolean"
},
"canInvite": {
"type": "boolean"
},
"cardAging": {
"type": "string"
},
"cardCounts": {
"type": "boolean"
},
"cardCovers": {
"type": "boolean"
},
"comments": {
"type": "string"
},
"hideVotes": {
"type": "boolean"
},
"invitations": {
"type": "string"
},
"isTemplate": {
"type": "boolean"
},
"permissionLevel": {
"type": "string"
},
"selfJoin": {
"type": "boolean"
},
"switcherViews": {
"type": "array",
"items": {
"type": "object",
"properties": {
"enabled": {
"type": "boolean"
},
"viewType": {
"type": "string"
}
}
}
},
"voting": {
"type": "string"
}
}
},
"shortUrl": {
"type": "string"
},
"url": {
"type": "string"
}
},
"version": 1
}
@@ -0,0 +1,15 @@
{
"type": "object",
"properties": {
"fullName": {
"type": "string"
},
"id": {
"type": "string"
},
"username": {
"type": "string"
}
},
"version": 1
}
@@ -0,0 +1,249 @@
{
"type": "object",
"properties": {
"attachments": {
"type": "array",
"items": {
"type": "object",
"properties": {
"bytes": {
"type": "null"
},
"date": {
"type": "string"
},
"edgeColor": {
"type": "null"
},
"id": {
"type": "string"
},
"idMember": {
"type": "string"
},
"isMalicious": {
"type": "boolean"
},
"isUpload": {
"type": "boolean"
},
"mimeType": {
"type": "string"
},
"name": {
"type": "string"
},
"pos": {
"type": "integer"
},
"url": {
"type": "string"
}
}
}
},
"badges": {
"type": "object",
"properties": {
"attachments": {
"type": "integer"
},
"attachmentsByType": {
"type": "object",
"properties": {
"trello": {
"type": "object",
"properties": {
"board": {
"type": "integer"
},
"card": {
"type": "integer"
}
}
}
}
},
"checkItems": {
"type": "integer"
},
"checkItemsChecked": {
"type": "integer"
},
"checkItemsEarliestDue": {
"type": "null"
},
"comments": {
"type": "integer"
},
"description": {
"type": "boolean"
},
"dueComplete": {
"type": "boolean"
},
"externalSource": {
"type": "null"
},
"fogbugz": {
"type": "string"
},
"lastUpdatedByAi": {
"type": "boolean"
},
"location": {
"type": "boolean"
},
"start": {
"type": "null"
},
"subscribed": {
"type": "boolean"
},
"viewingMemberVoted": {
"type": "boolean"
},
"votes": {
"type": "integer"
}
}
},
"cardRole": {
"type": "null"
},
"closed": {
"type": "boolean"
},
"cover": {
"type": "object",
"properties": {
"brightness": {
"type": "string"
},
"color": {
"type": "null"
},
"idAttachment": {
"type": "null"
},
"idPlugin": {
"type": "null"
},
"idUploadedBackground": {
"type": "null"
},
"size": {
"type": "string"
}
}
},
"dateLastActivity": {
"type": "string"
},
"desc": {
"type": "string"
},
"dueComplete": {
"type": "boolean"
},
"dueReminder": {
"type": "null"
},
"email": {
"type": "null"
},
"id": {
"type": "string"
},
"idAttachmentCover": {
"type": "null"
},
"idBoard": {
"type": "string"
},
"idChecklists": {
"type": "array",
"items": {
"type": "string"
}
},
"idLabels": {
"type": "array",
"items": {
"type": "string"
}
},
"idList": {
"type": "string"
},
"idMembers": {
"type": "array",
"items": {
"type": "string"
}
},
"idShort": {
"type": "integer"
},
"isTemplate": {
"type": "boolean"
},
"labels": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"idBoard": {
"type": "string"
},
"idOrganization": {
"type": "string"
},
"name": {
"type": "string"
},
"nodeId": {
"type": "string"
},
"uses": {
"type": "integer"
}
}
}
},
"manualCoverAttachment": {
"type": "boolean"
},
"mirrorSourceId": {
"type": "null"
},
"name": {
"type": "string"
},
"nodeId": {
"type": "string"
},
"pinned": {
"type": "boolean"
},
"shortLink": {
"type": "string"
},
"shortUrl": {
"type": "string"
},
"start": {
"type": "null"
},
"subscribed": {
"type": "boolean"
},
"url": {
"type": "string"
}
},
"version": 1
}
@@ -0,0 +1,201 @@
{
"type": "object",
"properties": {
"badges": {
"type": "object",
"properties": {
"attachments": {
"type": "integer"
},
"attachmentsByType": {
"type": "object",
"properties": {
"trello": {
"type": "object",
"properties": {
"board": {
"type": "integer"
},
"card": {
"type": "integer"
}
}
}
}
},
"checkItems": {
"type": "integer"
},
"checkItemsChecked": {
"type": "integer"
},
"checkItemsEarliestDue": {
"type": "null"
},
"comments": {
"type": "integer"
},
"description": {
"type": "boolean"
},
"dueComplete": {
"type": "boolean"
},
"externalSource": {
"type": "null"
},
"fogbugz": {
"type": "string"
},
"lastUpdatedByAi": {
"type": "boolean"
},
"location": {
"type": "boolean"
},
"subscribed": {
"type": "boolean"
},
"viewingMemberVoted": {
"type": "boolean"
},
"votes": {
"type": "integer"
}
}
},
"cardRole": {
"type": "null"
},
"checkItemStates": {
"type": "array",
"items": {
"type": "object",
"properties": {
"idCheckItem": {
"type": "string"
},
"state": {
"type": "string"
}
}
}
},
"closed": {
"type": "boolean"
},
"cover": {
"type": "object",
"properties": {
"brightness": {
"type": "string"
},
"idUploadedBackground": {
"type": "null"
},
"size": {
"type": "string"
}
}
},
"dateLastActivity": {
"type": "string"
},
"desc": {
"type": "string"
},
"dueComplete": {
"type": "boolean"
},
"email": {
"type": "null"
},
"id": {
"type": "string"
},
"idBoard": {
"type": "string"
},
"idChecklists": {
"type": "array",
"items": {
"type": "string"
}
},
"idLabels": {
"type": "array",
"items": {
"type": "string"
}
},
"idList": {
"type": "string"
},
"idMembers": {
"type": "array",
"items": {
"type": "string"
}
},
"idShort": {
"type": "integer"
},
"isTemplate": {
"type": "boolean"
},
"labels": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"idBoard": {
"type": "string"
},
"idOrganization": {
"type": "string"
},
"name": {
"type": "string"
},
"nodeId": {
"type": "string"
},
"uses": {
"type": "integer"
}
}
}
},
"manualCoverAttachment": {
"type": "boolean"
},
"mirrorSourceId": {
"type": "null"
},
"name": {
"type": "string"
},
"nodeId": {
"type": "string"
},
"pinned": {
"type": "boolean"
},
"shortLink": {
"type": "string"
},
"shortUrl": {
"type": "string"
},
"subscribed": {
"type": "boolean"
},
"url": {
"type": "string"
}
},
"version": 1
}
@@ -0,0 +1,198 @@
{
"type": "object",
"properties": {
"badges": {
"type": "object",
"properties": {
"attachments": {
"type": "integer"
},
"attachmentsByType": {
"type": "object",
"properties": {
"trello": {
"type": "object",
"properties": {
"board": {
"type": "integer"
},
"card": {
"type": "integer"
}
}
}
}
},
"checkItems": {
"type": "integer"
},
"checkItemsChecked": {
"type": "integer"
},
"checkItemsEarliestDue": {
"type": "null"
},
"comments": {
"type": "integer"
},
"description": {
"type": "boolean"
},
"dueComplete": {
"type": "boolean"
},
"fogbugz": {
"type": "string"
},
"lastUpdatedByAi": {
"type": "boolean"
},
"location": {
"type": "boolean"
},
"subscribed": {
"type": "boolean"
},
"viewingMemberVoted": {
"type": "boolean"
},
"votes": {
"type": "integer"
}
}
},
"cardRole": {
"type": "null"
},
"checkItemStates": {
"type": "array",
"items": {
"type": "object",
"properties": {
"idCheckItem": {
"type": "string"
},
"state": {
"type": "string"
}
}
}
},
"closed": {
"type": "boolean"
},
"cover": {
"type": "object",
"properties": {
"brightness": {
"type": "string"
},
"idPlugin": {
"type": "null"
},
"idUploadedBackground": {
"type": "null"
},
"size": {
"type": "string"
}
}
},
"dateLastActivity": {
"type": "string"
},
"desc": {
"type": "string"
},
"dueComplete": {
"type": "boolean"
},
"email": {
"type": "null"
},
"id": {
"type": "string"
},
"idBoard": {
"type": "string"
},
"idChecklists": {
"type": "array",
"items": {
"type": "string"
}
},
"idLabels": {
"type": "array",
"items": {
"type": "string"
}
},
"idList": {
"type": "string"
},
"idMembers": {
"type": "array",
"items": {
"type": "string"
}
},
"idShort": {
"type": "integer"
},
"isTemplate": {
"type": "boolean"
},
"labels": {
"type": "array",
"items": {
"type": "object",
"properties": {
"color": {
"type": "string"
},
"id": {
"type": "string"
},
"idBoard": {
"type": "string"
},
"idOrganization": {
"type": "string"
},
"name": {
"type": "string"
},
"nodeId": {
"type": "string"
},
"uses": {
"type": "integer"
}
}
}
},
"manualCoverAttachment": {
"type": "boolean"
},
"name": {
"type": "string"
},
"pinned": {
"type": "boolean"
},
"shortLink": {
"type": "string"
},
"shortUrl": {
"type": "string"
},
"subscribed": {
"type": "boolean"
},
"url": {
"type": "string"
}
},
"version": 1
}
@@ -0,0 +1,250 @@
{
"type": "object",
"properties": {
"appCreator": {
"type": "object",
"properties": {
"id": {
"type": "string"
}
}
},
"data": {
"type": "object",
"properties": {
"board": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"shortLink": {
"type": "string"
}
}
},
"card": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"idShort": {
"type": "integer"
},
"name": {
"type": "string"
},
"shortLink": {
"type": "string"
}
}
},
"list": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
}
}
},
"text": {
"type": "string"
}
}
},
"date": {
"type": "string"
},
"display": {
"type": "object",
"properties": {
"entities": {
"type": "object",
"properties": {
"card": {
"type": "object",
"properties": {
"hideIfContext": {
"type": "boolean"
},
"id": {
"type": "string"
},
"shortLink": {
"type": "string"
},
"text": {
"type": "string"
},
"type": {
"type": "string"
}
}
},
"comment": {
"type": "object",
"properties": {
"text": {
"type": "string"
},
"type": {
"type": "string"
}
}
},
"contextOn": {
"type": "object",
"properties": {
"hideIfContext": {
"type": "boolean"
},
"idContext": {
"type": "string"
},
"translationKey": {
"type": "string"
},
"type": {
"type": "string"
}
}
},
"memberCreator": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"text": {
"type": "string"
},
"type": {
"type": "string"
},
"username": {
"type": "string"
}
}
}
}
},
"translationKey": {
"type": "string"
}
}
},
"entities": {
"type": "array",
"items": {
"type": "object",
"properties": {
"hideIfContext": {
"type": "boolean"
},
"id": {
"type": "string"
},
"idContext": {
"type": "string"
},
"shortLink": {
"type": "string"
},
"text": {
"type": "string"
},
"type": {
"type": "string"
},
"username": {
"type": "string"
}
}
}
},
"id": {
"type": "string"
},
"idMemberCreator": {
"type": "string"
},
"limits": {
"type": "object",
"properties": {
"reactions": {
"type": "object",
"properties": {
"perAction": {
"type": "object",
"properties": {
"disableAt": {
"type": "integer"
},
"status": {
"type": "string"
},
"warnAt": {
"type": "integer"
}
}
},
"uniquePerAction": {
"type": "object",
"properties": {
"disableAt": {
"type": "integer"
},
"status": {
"type": "string"
},
"warnAt": {
"type": "integer"
}
}
}
}
}
}
},
"memberCreator": {
"type": "object",
"properties": {
"activityBlocked": {
"type": "boolean"
},
"avatarHash": {
"type": "string"
},
"avatarUrl": {
"type": "string"
},
"fullName": {
"type": "string"
},
"id": {
"type": "string"
},
"initials": {
"type": "string"
},
"nonPublicAvailable": {
"type": "boolean"
},
"username": {
"type": "string"
}
}
},
"type": {
"type": "string"
}
},
"version": 1
}
@@ -0,0 +1,53 @@
{
"type": "object",
"properties": {
"checkItems": {
"type": "array",
"items": {
"type": "object",
"properties": {
"due": {
"type": "null"
},
"dueReminder": {
"type": "integer"
},
"id": {
"type": "string"
},
"idChecklist": {
"type": "string"
},
"idMember": {
"type": "null"
},
"name": {
"type": "string"
},
"pos": {
"type": "integer"
},
"state": {
"type": "string"
}
}
}
},
"id": {
"type": "string"
},
"idBoard": {
"type": "string"
},
"idCard": {
"type": "string"
},
"name": {
"type": "string"
},
"pos": {
"type": "integer"
}
},
"version": 1
}
@@ -0,0 +1,30 @@
{
"type": "object",
"properties": {
"due": {
"type": "null"
},
"dueReminder": {
"type": "null"
},
"id": {
"type": "string"
},
"idChecklist": {
"type": "string"
},
"idMember": {
"type": "null"
},
"name": {
"type": "string"
},
"pos": {
"type": "integer"
},
"state": {
"type": "string"
}
},
"version": 1
}
@@ -0,0 +1,41 @@
{
"type": "object",
"properties": {
"checkItems": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"idChecklist": {
"type": "string"
},
"name": {
"type": "string"
},
"state": {
"type": "string"
}
}
}
},
"id": {
"type": "string"
},
"idBoard": {
"type": "string"
},
"idCard": {
"type": "string"
},
"name": {
"type": "string"
},
"pos": {
"type": "integer"
}
},
"version": 1
}
@@ -0,0 +1,44 @@
{
"type": "object",
"properties": {
"checkItems": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"idChecklist": {
"type": "string"
},
"name": {
"type": "string"
},
"pos": {
"type": "integer"
},
"state": {
"type": "string"
}
}
}
},
"id": {
"type": "string"
},
"idBoard": {
"type": "string"
},
"idCard": {
"type": "string"
},
"name": {
"type": "string"
},
"pos": {
"type": "integer"
}
},
"version": 1
}
@@ -0,0 +1,18 @@
{
"type": "object",
"properties": {
"id": {
"type": "string"
},
"idBoard": {
"type": "string"
},
"name": {
"type": "string"
},
"uses": {
"type": "integer"
}
},
"version": 1
}
@@ -0,0 +1,32 @@
{
"type": "object",
"properties": {
"closed": {
"type": "boolean"
},
"color": {
"type": "null"
},
"datasource": {
"type": "object",
"properties": {
"filter": {
"type": "boolean"
}
}
},
"id": {
"type": "string"
},
"idBoard": {
"type": "string"
},
"name": {
"type": "string"
},
"type": {
"type": "null"
}
},
"version": 1
}
@@ -0,0 +1,29 @@
{
"type": "object",
"properties": {
"closed": {
"type": "boolean"
},
"datasource": {
"type": "object",
"properties": {
"filter": {
"type": "boolean"
}
}
},
"id": {
"type": "string"
},
"idBoard": {
"type": "string"
},
"name": {
"type": "string"
},
"type": {
"type": "null"
}
},
"version": 1
}
@@ -0,0 +1,32 @@
{
"type": "object",
"properties": {
"closed": {
"type": "boolean"
},
"datasource": {
"type": "object",
"properties": {
"filter": {
"type": "boolean"
}
}
},
"id": {
"type": "string"
},
"idBoard": {
"type": "string"
},
"name": {
"type": "string"
},
"subscribed": {
"type": "boolean"
},
"type": {
"type": "null"
}
},
"version": 7
}
@@ -0,0 +1,207 @@
{
"type": "object",
"properties": {
"badges": {
"type": "object",
"properties": {
"attachments": {
"type": "integer"
},
"attachmentsByType": {
"type": "object",
"properties": {
"trello": {
"type": "object",
"properties": {
"board": {
"type": "integer"
},
"card": {
"type": "integer"
}
}
}
}
},
"checkItems": {
"type": "integer"
},
"checkItemsChecked": {
"type": "integer"
},
"checkItemsEarliestDue": {
"type": "null"
},
"comments": {
"type": "integer"
},
"description": {
"type": "boolean"
},
"dueComplete": {
"type": "boolean"
},
"fogbugz": {
"type": "string"
},
"lastUpdatedByAi": {
"type": "boolean"
},
"location": {
"type": "boolean"
},
"maliciousAttachments": {
"type": "integer"
},
"subscribed": {
"type": "boolean"
},
"viewingMemberVoted": {
"type": "boolean"
},
"votes": {
"type": "integer"
}
}
},
"cardRole": {
"type": "null"
},
"checkItemStates": {
"type": "array",
"items": {
"type": "object",
"properties": {
"idCheckItem": {
"type": "string"
},
"state": {
"type": "string"
}
}
}
},
"closed": {
"type": "boolean"
},
"cover": {
"type": "object",
"properties": {
"brightness": {
"type": "string"
},
"idUploadedBackground": {
"type": "null"
},
"size": {
"type": "string"
}
}
},
"dateLastActivity": {
"type": "string"
},
"desc": {
"type": "string"
},
"dueComplete": {
"type": "boolean"
},
"email": {
"type": "null"
},
"id": {
"type": "string"
},
"idBoard": {
"type": "string"
},
"idChecklists": {
"type": "array",
"items": {
"type": "string"
}
},
"idLabels": {
"type": "array",
"items": {
"type": "string"
}
},
"idList": {
"type": "string"
},
"idMembers": {
"type": "array",
"items": {
"type": "string"
}
},
"idMembersVoted": {
"type": "array",
"items": {
"type": "string"
}
},
"idShort": {
"type": "integer"
},
"isTemplate": {
"type": "boolean"
},
"labels": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"idBoard": {
"type": "string"
},
"idOrganization": {
"type": "string"
},
"name": {
"type": "string"
},
"nodeId": {
"type": "string"
},
"uses": {
"type": "integer"
}
}
}
},
"manualCoverAttachment": {
"type": "boolean"
},
"mirrorSourceId": {
"type": "null"
},
"name": {
"type": "string"
},
"nodeId": {
"type": "string"
},
"pinned": {
"type": "boolean"
},
"shortLink": {
"type": "string"
},
"shortUrl": {
"type": "string"
},
"subscribed": {
"type": "boolean"
},
"url": {
"type": "string"
}
},
"version": 8
}
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200"><g fill="none" fill-rule="evenodd"><rect width="200" height="200" fill="#0079BF" rx="25"/><rect width="61" height="87.5" x="113" y="26" fill="#FFF" rx="12"/><rect width="61" height="137.5" x="26" y="26" fill="#FFF" rx="12"/></g></svg>

After

Width:  |  Height:  |  Size: 299 B