mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-24 04:04:06 -08:00
feat(Jira Software Node): Use resource locator component (#5090)
* ⚡️Issue -> Create -> parameter Project RLC * 🔥removed unused loadOptions getProjects * ⚡️Issue -> Create -> parameter Issue Type RLC * 🔥removed unused loadOptions getIssueTypes * ⚡️Issue -> Create/Update -> parameter Assignee RLC * ⚡️Issue -> Create/Update -> parameter Reporter RLC * ⚡️Issue -> Create/Update -> parameter Priority RLC * 🔥removed unused loadOptions getPriorities * ⚡️Issue -> Update -> parameter Status RLC * 🔥removed unused loadOptions getTransitions * 🎨 fix typos * ⚡️Issue -> Create/Update -> Custom Fields parameter Field RLC * 🔥removed unused loadOptions getCustomFields * 🥅 throw custom error for "Field priority cannot be set" * 🚨 fix linter error * ⚡ removed ts-ignore * ⚡ removed ts-ignore Co-authored-by: Michael Kret <michael.k@radency.com>
This commit is contained in:
parent
2b776f39f1
commit
237b1d8614
|
@ -7,13 +7,12 @@ import {
|
||||||
ILoadOptionsFunctions,
|
ILoadOptionsFunctions,
|
||||||
} from 'n8n-core';
|
} from 'n8n-core';
|
||||||
|
|
||||||
import { IDataObject } from 'n8n-workflow';
|
import { IDataObject, INodeListSearchItems, NodeApiError } from 'n8n-workflow';
|
||||||
|
|
||||||
export async function jiraSoftwareCloudApiRequest(
|
export async function jiraSoftwareCloudApiRequest(
|
||||||
this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions,
|
this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions,
|
||||||
endpoint: string,
|
endpoint: string,
|
||||||
method: string,
|
method: string,
|
||||||
|
|
||||||
body: any = {},
|
body: any = {},
|
||||||
query?: IDataObject,
|
query?: IDataObject,
|
||||||
uri?: string,
|
uri?: string,
|
||||||
|
@ -56,8 +55,20 @@ export async function jiraSoftwareCloudApiRequest(
|
||||||
if (Object.keys(query || {}).length === 0) {
|
if (Object.keys(query || {}).length === 0) {
|
||||||
delete options.qs;
|
delete options.qs;
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
return this.helpers.requestWithAuthentication.call(this, credentialType, options);
|
return await this.helpers.requestWithAuthentication.call(this, credentialType, options);
|
||||||
|
} catch (error) {
|
||||||
|
if (
|
||||||
|
error.description?.includes &&
|
||||||
|
error.description.includes("Field 'priority' cannot be set")
|
||||||
|
) {
|
||||||
|
throw new NodeApiError(this.getNode(), error, {
|
||||||
|
message:
|
||||||
|
"Field 'priority' cannot be set. You need to add the Priority field to your Jira Project's Issue Types.",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function jiraSoftwareCloudApiRequestAllItems(
|
export async function jiraSoftwareCloudApiRequestAllItems(
|
||||||
|
@ -65,7 +76,6 @@ export async function jiraSoftwareCloudApiRequestAllItems(
|
||||||
propertyName: string,
|
propertyName: string,
|
||||||
endpoint: string,
|
endpoint: string,
|
||||||
method: string,
|
method: string,
|
||||||
|
|
||||||
body: any = {},
|
body: any = {},
|
||||||
query: IDataObject = {},
|
query: IDataObject = {},
|
||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
|
@ -198,3 +208,22 @@ export const allEvents = [
|
||||||
'worklog_updated',
|
'worklog_updated',
|
||||||
'worklog_deleted',
|
'worklog_deleted',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export function filterSortSearchListItems(items: INodeListSearchItems[], filter?: string) {
|
||||||
|
return items
|
||||||
|
.filter(
|
||||||
|
(item) =>
|
||||||
|
!filter ||
|
||||||
|
item.name.toLowerCase().includes(filter.toLowerCase()) ||
|
||||||
|
item.value.toString().toLowerCase().includes(filter.toLowerCase()),
|
||||||
|
)
|
||||||
|
.sort((a, b) => {
|
||||||
|
if (a.name.toLocaleLowerCase() < b.name.toLocaleLowerCase()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (a.name.toLocaleLowerCase() > b.name.toLocaleLowerCase()) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -71,42 +71,93 @@ export const issueFields: INodeProperties[] = [
|
||||||
/* issue:create */
|
/* issue:create */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
{
|
{
|
||||||
displayName: 'Project Name or ID',
|
displayName: 'Project',
|
||||||
name: 'project',
|
name: 'project',
|
||||||
type: 'options',
|
type: 'resourceLocator',
|
||||||
description:
|
default: { mode: 'list', value: '' },
|
||||||
'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code-examples/expressions/">expression</a>',
|
|
||||||
default: '',
|
|
||||||
required: true,
|
required: true,
|
||||||
|
modes: [
|
||||||
|
{
|
||||||
|
displayName: 'Project',
|
||||||
|
name: 'list',
|
||||||
|
type: 'list',
|
||||||
|
placeholder: 'Select a Project...',
|
||||||
|
typeOptions: {
|
||||||
|
searchListMethod: 'getProjects',
|
||||||
|
// missing searchListDependsOn: ['jiraVersion'],
|
||||||
|
searchable: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'ID',
|
||||||
|
name: 'id',
|
||||||
|
type: 'string',
|
||||||
|
placeholder: '10000',
|
||||||
|
validation: [
|
||||||
|
{
|
||||||
|
type: 'regex',
|
||||||
|
properties: {
|
||||||
|
regex: '([0-9]{2,})[ \t]*',
|
||||||
|
errorMessage: 'Not a valid Jira Project ID',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
extractValue: {
|
||||||
|
type: 'regex',
|
||||||
|
regex: '^([0-9]{2,})',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
displayOptions: {
|
displayOptions: {
|
||||||
show: {
|
show: {
|
||||||
resource: ['issue'],
|
resource: ['issue'],
|
||||||
operation: ['create'],
|
operation: ['create'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
typeOptions: {
|
|
||||||
loadOptionsMethod: 'getProjects',
|
|
||||||
loadOptionsDependsOn: ['jiraVersion'],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Issue Type Name or ID',
|
displayName: 'Issue Type',
|
||||||
name: 'issueType',
|
name: 'issueType',
|
||||||
type: 'options',
|
type: 'resourceLocator',
|
||||||
default: '',
|
default: { mode: 'list', value: '' },
|
||||||
required: true,
|
required: true,
|
||||||
|
modes: [
|
||||||
|
{
|
||||||
|
displayName: 'Issue Type',
|
||||||
|
name: 'list',
|
||||||
|
type: 'list',
|
||||||
|
placeholder: 'Select an Issue Type...',
|
||||||
|
typeOptions: {
|
||||||
|
searchListMethod: 'getIssueTypes',
|
||||||
|
// missing searchListDependsOn: ['project'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'ID',
|
||||||
|
name: 'id',
|
||||||
|
type: 'string',
|
||||||
|
placeholder: '10000',
|
||||||
|
validation: [
|
||||||
|
{
|
||||||
|
type: 'regex',
|
||||||
|
properties: {
|
||||||
|
regex: '([0-9]{2,})[ \t]*',
|
||||||
|
errorMessage: 'Not a valid Jira Issue Type ID',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
extractValue: {
|
||||||
|
type: 'regex',
|
||||||
|
regex: '^([0-9]{2,})',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
displayOptions: {
|
displayOptions: {
|
||||||
show: {
|
show: {
|
||||||
resource: ['issue'],
|
resource: ['issue'],
|
||||||
operation: ['create'],
|
operation: ['create'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
typeOptions: {
|
|
||||||
loadOptionsMethod: 'getIssueTypes',
|
|
||||||
loadOptionsDependsOn: ['project'],
|
|
||||||
},
|
|
||||||
description:
|
|
||||||
'Issue Types. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code-examples/expressions/">expression</a>.',
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Summary',
|
displayName: 'Summary',
|
||||||
|
@ -135,15 +186,41 @@ export const issueFields: INodeProperties[] = [
|
||||||
},
|
},
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
displayName: 'Assignee Name or ID',
|
displayName: 'Assignee',
|
||||||
name: 'assignee',
|
name: 'assignee',
|
||||||
type: 'options',
|
type: 'resourceLocator',
|
||||||
description:
|
default: { mode: 'list', value: '' },
|
||||||
'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code-examples/expressions/">expression</a>',
|
modes: [
|
||||||
typeOptions: {
|
{
|
||||||
loadOptionsMethod: 'getUsers',
|
displayName: 'Assignee',
|
||||||
},
|
name: 'list',
|
||||||
default: '',
|
type: 'list',
|
||||||
|
placeholder: 'Select an Assignee...',
|
||||||
|
typeOptions: {
|
||||||
|
searchListMethod: 'getUsers',
|
||||||
|
searchable: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'ID',
|
||||||
|
name: 'id',
|
||||||
|
type: 'string',
|
||||||
|
placeholder: '62971ebae540870069668714',
|
||||||
|
validation: [
|
||||||
|
{
|
||||||
|
type: 'regex',
|
||||||
|
properties: {
|
||||||
|
regex: '([-:a-z0-9]{2,})[ \t]*',
|
||||||
|
errorMessage: 'Not a valid Jira Assignee ID',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
extractValue: {
|
||||||
|
type: 'regex',
|
||||||
|
regex: '^([-:a-z0-9]{2,})',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Description',
|
displayName: 'Description',
|
||||||
|
@ -178,16 +255,41 @@ export const issueFields: INodeProperties[] = [
|
||||||
displayName: 'Custom Field',
|
displayName: 'Custom Field',
|
||||||
values: [
|
values: [
|
||||||
{
|
{
|
||||||
displayName: 'Field Name or ID',
|
displayName: 'Field',
|
||||||
name: 'fieldId',
|
name: 'fieldId',
|
||||||
type: 'options',
|
type: 'resourceLocator',
|
||||||
typeOptions: {
|
default: { mode: 'list', value: '' },
|
||||||
loadOptionsMethod: 'getCustomFields',
|
modes: [
|
||||||
loadOptionsDependsOn: ['project'],
|
{
|
||||||
},
|
displayName: 'Field',
|
||||||
description:
|
name: 'list',
|
||||||
'ID of the field to set. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code-examples/expressions/">expression</a>.',
|
type: 'list',
|
||||||
default: '',
|
placeholder: 'Select a Field...',
|
||||||
|
typeOptions: {
|
||||||
|
searchListMethod: 'getCustomFields',
|
||||||
|
// missing searchListDependsOn: ['project'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'ID',
|
||||||
|
name: 'id',
|
||||||
|
type: 'string',
|
||||||
|
placeholder: 'customfield_10035',
|
||||||
|
validation: [
|
||||||
|
{
|
||||||
|
type: 'regex',
|
||||||
|
properties: {
|
||||||
|
regex: '(customfield_[0-9]{2,})[ \t]*',
|
||||||
|
errorMessage: 'Not a valid Jira Field ID',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
extractValue: {
|
||||||
|
type: 'regex',
|
||||||
|
regex: '^(customfield_[0-9]{2,})',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Field Value',
|
displayName: 'Field Value',
|
||||||
|
@ -237,26 +339,77 @@ export const issueFields: INodeProperties[] = [
|
||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Priority Name or ID',
|
displayName: 'Priority',
|
||||||
name: 'priority',
|
name: 'priority',
|
||||||
type: 'options',
|
type: 'resourceLocator',
|
||||||
description:
|
default: { mode: 'list', value: '' },
|
||||||
'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code-examples/expressions/">expression</a>',
|
modes: [
|
||||||
typeOptions: {
|
{
|
||||||
loadOptionsMethod: 'getPriorities',
|
displayName: 'Priority',
|
||||||
},
|
name: 'list',
|
||||||
default: '',
|
type: 'list',
|
||||||
|
placeholder: 'Select a Priority...',
|
||||||
|
typeOptions: {
|
||||||
|
searchListMethod: 'getPriorities',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'ID',
|
||||||
|
name: 'id',
|
||||||
|
type: 'string',
|
||||||
|
placeholder: '1',
|
||||||
|
validation: [
|
||||||
|
{
|
||||||
|
type: 'regex',
|
||||||
|
properties: {
|
||||||
|
regex: '([0-9]{1,})[ \t]*',
|
||||||
|
errorMessage: 'Not a valid Jira Priority ID',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
extractValue: {
|
||||||
|
type: 'regex',
|
||||||
|
regex: '^([0-9]{1,})',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Reporter Name or ID',
|
displayName: 'Reporter',
|
||||||
name: 'reporter',
|
name: 'reporter',
|
||||||
type: 'options',
|
type: 'resourceLocator',
|
||||||
description:
|
default: { mode: 'list', value: '' },
|
||||||
'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code-examples/expressions/">expression</a>',
|
modes: [
|
||||||
typeOptions: {
|
{
|
||||||
loadOptionsMethod: 'getUsers',
|
displayName: 'Reporter',
|
||||||
},
|
name: 'list',
|
||||||
default: '',
|
type: 'list',
|
||||||
|
placeholder: 'Select a Reporter...',
|
||||||
|
typeOptions: {
|
||||||
|
searchListMethod: 'getUsers',
|
||||||
|
searchable: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'ID',
|
||||||
|
name: 'id',
|
||||||
|
type: 'string',
|
||||||
|
placeholder: '62971ebae540870069668714',
|
||||||
|
validation: [
|
||||||
|
{
|
||||||
|
type: 'regex',
|
||||||
|
properties: {
|
||||||
|
regex: '([-:a-z0-9]{2,})[ \t]*',
|
||||||
|
errorMessage: 'Not a valid Jira Reporter ID',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
extractValue: {
|
||||||
|
type: 'regex',
|
||||||
|
regex: '^([-:a-z0-9]{2,})',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Update History',
|
displayName: 'Update History',
|
||||||
|
@ -299,15 +452,41 @@ export const issueFields: INodeProperties[] = [
|
||||||
},
|
},
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
displayName: 'Assignee Name or ID',
|
displayName: 'Assignee',
|
||||||
name: 'assignee',
|
name: 'assignee',
|
||||||
type: 'options',
|
type: 'resourceLocator',
|
||||||
description:
|
default: { mode: 'list', value: '' },
|
||||||
'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code-examples/expressions/">expression</a>',
|
modes: [
|
||||||
typeOptions: {
|
{
|
||||||
loadOptionsMethod: 'getUsers',
|
displayName: 'Assignee',
|
||||||
},
|
name: 'list',
|
||||||
default: '',
|
type: 'list',
|
||||||
|
placeholder: 'Select an Assignee...',
|
||||||
|
typeOptions: {
|
||||||
|
searchListMethod: 'getUsers',
|
||||||
|
searchable: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'ID',
|
||||||
|
name: 'id',
|
||||||
|
type: 'string',
|
||||||
|
placeholder: '62971ebae540870069668714',
|
||||||
|
validation: [
|
||||||
|
{
|
||||||
|
type: 'regex',
|
||||||
|
properties: {
|
||||||
|
regex: '([-:a-z0-9]{2,})[ \t]*',
|
||||||
|
errorMessage: 'Not a valid Jira Assignee ID',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
extractValue: {
|
||||||
|
type: 'regex',
|
||||||
|
regex: '^([-:a-z0-9]{2,})',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Description',
|
displayName: 'Description',
|
||||||
|
@ -330,16 +509,41 @@ export const issueFields: INodeProperties[] = [
|
||||||
displayName: 'Custom Field',
|
displayName: 'Custom Field',
|
||||||
values: [
|
values: [
|
||||||
{
|
{
|
||||||
displayName: 'Field Name or ID',
|
displayName: 'Field',
|
||||||
name: 'fieldId',
|
name: 'fieldId',
|
||||||
type: 'options',
|
type: 'resourceLocator',
|
||||||
typeOptions: {
|
default: { mode: 'list', value: '' },
|
||||||
loadOptionsMethod: 'getCustomFields',
|
modes: [
|
||||||
loadOptionsDependsOn: ['issueKey'],
|
{
|
||||||
},
|
displayName: 'Field',
|
||||||
description:
|
name: 'list',
|
||||||
'ID of the field to set. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code-examples/expressions/">expression</a>.',
|
type: 'list',
|
||||||
default: '',
|
placeholder: 'Select a Field...',
|
||||||
|
typeOptions: {
|
||||||
|
searchListMethod: 'getCustomFields',
|
||||||
|
// missing searchListDependsOn: ['issueKey'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'ID',
|
||||||
|
name: 'id',
|
||||||
|
type: 'string',
|
||||||
|
placeholder: 'customfield_10035',
|
||||||
|
validation: [
|
||||||
|
{
|
||||||
|
type: 'regex',
|
||||||
|
properties: {
|
||||||
|
regex: '(customfield_[0-9]{2,})[ \t]*',
|
||||||
|
errorMessage: 'Not a valid Jira Field ID',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
extractValue: {
|
||||||
|
type: 'regex',
|
||||||
|
regex: '^(customfield_[0-9]{2,})',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Field Value',
|
displayName: 'Field Value',
|
||||||
|
@ -396,26 +600,77 @@ export const issueFields: INodeProperties[] = [
|
||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Priority Name or ID',
|
displayName: 'Priority',
|
||||||
name: 'priority',
|
name: 'priority',
|
||||||
type: 'options',
|
type: 'resourceLocator',
|
||||||
description:
|
default: { mode: 'list', value: '' },
|
||||||
'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code-examples/expressions/">expression</a>',
|
modes: [
|
||||||
typeOptions: {
|
{
|
||||||
loadOptionsMethod: 'getPriorities',
|
displayName: 'Priority',
|
||||||
},
|
name: 'list',
|
||||||
default: '',
|
type: 'list',
|
||||||
|
placeholder: 'Select a Priority...',
|
||||||
|
typeOptions: {
|
||||||
|
searchListMethod: 'getPriorities',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'ID',
|
||||||
|
name: 'id',
|
||||||
|
type: 'string',
|
||||||
|
placeholder: '1',
|
||||||
|
validation: [
|
||||||
|
{
|
||||||
|
type: 'regex',
|
||||||
|
properties: {
|
||||||
|
regex: '([0-9]{1,})[ \t]*',
|
||||||
|
errorMessage: 'Not a valid Jira Priority ID',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
extractValue: {
|
||||||
|
type: 'regex',
|
||||||
|
regex: '^([0-9]{1,})',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Reporter Name or ID',
|
displayName: 'Reporter',
|
||||||
name: 'reporter',
|
name: 'reporter',
|
||||||
type: 'options',
|
type: 'resourceLocator',
|
||||||
description:
|
default: { mode: 'list', value: '' },
|
||||||
'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code-examples/expressions/">expression</a>',
|
modes: [
|
||||||
typeOptions: {
|
{
|
||||||
loadOptionsMethod: 'getUsers',
|
displayName: 'Reporter',
|
||||||
},
|
name: 'list',
|
||||||
default: '',
|
type: 'list',
|
||||||
|
placeholder: 'Select a Reporter...',
|
||||||
|
typeOptions: {
|
||||||
|
searchListMethod: 'getUsers',
|
||||||
|
searchable: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'ID',
|
||||||
|
name: 'id',
|
||||||
|
type: 'string',
|
||||||
|
placeholder: '62971ebae540870069668714',
|
||||||
|
validation: [
|
||||||
|
{
|
||||||
|
type: 'regex',
|
||||||
|
properties: {
|
||||||
|
regex: '([-:a-z0-9]{2,})[ \t]*',
|
||||||
|
errorMessage: 'Not a valid Jira Reporter ID',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
extractValue: {
|
||||||
|
type: 'regex',
|
||||||
|
regex: '^([-:a-z0-9]{2,})',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Summary',
|
displayName: 'Summary',
|
||||||
|
@ -424,15 +679,40 @@ export const issueFields: INodeProperties[] = [
|
||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Status Name or ID',
|
displayName: 'Status',
|
||||||
name: 'statusId',
|
name: 'statusId',
|
||||||
type: 'options',
|
type: 'resourceLocator',
|
||||||
typeOptions: {
|
default: { mode: 'list', value: '' },
|
||||||
loadOptionsMethod: 'getTransitions',
|
modes: [
|
||||||
},
|
{
|
||||||
default: '',
|
displayName: 'Status',
|
||||||
description:
|
name: 'list',
|
||||||
'The ID of the issue status. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code-examples/expressions/">expression</a>.',
|
type: 'list',
|
||||||
|
placeholder: 'Select a Status...',
|
||||||
|
typeOptions: {
|
||||||
|
searchListMethod: 'getTransitions',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'ID',
|
||||||
|
name: 'id',
|
||||||
|
type: 'string',
|
||||||
|
placeholder: '11',
|
||||||
|
validation: [
|
||||||
|
{
|
||||||
|
type: 'regex',
|
||||||
|
properties: {
|
||||||
|
regex: '([0-9]{1,})[ \t]*',
|
||||||
|
errorMessage: 'Not a valid Jira Status ID',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
extractValue: {
|
||||||
|
type: 'regex',
|
||||||
|
regex: '^([0-9]{1,})',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
|
@ -7,6 +7,8 @@ import {
|
||||||
IDataObject,
|
IDataObject,
|
||||||
ILoadOptionsFunctions,
|
ILoadOptionsFunctions,
|
||||||
INodeExecutionData,
|
INodeExecutionData,
|
||||||
|
INodeListSearchItems,
|
||||||
|
INodeListSearchResult,
|
||||||
INodePropertyOptions,
|
INodePropertyOptions,
|
||||||
INodeType,
|
INodeType,
|
||||||
INodeTypeDescription,
|
INodeTypeDescription,
|
||||||
|
@ -14,6 +16,7 @@ import {
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
filterSortSearchListItems,
|
||||||
jiraSoftwareCloudApiRequest,
|
jiraSoftwareCloudApiRequest,
|
||||||
jiraSoftwareCloudApiRequestAllItems,
|
jiraSoftwareCloudApiRequestAllItems,
|
||||||
simplifyIssueOutput,
|
simplifyIssueOutput,
|
||||||
|
@ -129,11 +132,14 @@ export class Jira implements INodeType {
|
||||||
};
|
};
|
||||||
|
|
||||||
methods = {
|
methods = {
|
||||||
loadOptions: {
|
listSearch: {
|
||||||
// Get all the projects to display them to user so that he can
|
// Get all the projects to display them to user so that he can
|
||||||
// select them easily
|
// select them easily
|
||||||
async getProjects(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
async getProjects(
|
||||||
const returnData: INodePropertyOptions[] = [];
|
this: ILoadOptionsFunctions,
|
||||||
|
filter?: string,
|
||||||
|
): Promise<INodeListSearchResult> {
|
||||||
|
const returnData: INodeListSearchItems[] = [];
|
||||||
const jiraVersion = this.getCurrentNodeParameter('jiraVersion') as string;
|
const jiraVersion = this.getCurrentNodeParameter('jiraVersion') as string;
|
||||||
let endpoint = '';
|
let endpoint = '';
|
||||||
let projects;
|
let projects;
|
||||||
|
@ -163,24 +169,14 @@ export class Jira implements INodeType {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
returnData.sort((a, b) => {
|
return { results: filterSortSearchListItems(returnData, filter) };
|
||||||
if (a.name < b.name) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (a.name > b.name) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
return returnData;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Get all the issue types to display them to user so that he can
|
// Get all the issue types to display them to user so that he can
|
||||||
// select them easily
|
// select them easily
|
||||||
async getIssueTypes(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
async getIssueTypes(this: ILoadOptionsFunctions): Promise<INodeListSearchResult> {
|
||||||
const projectId = this.getCurrentNodeParameter('project');
|
const projectId = this.getCurrentNodeParameter('project', { extractValue: true });
|
||||||
const returnData: INodePropertyOptions[] = [];
|
const returnData: INodeListSearchItems[] = [];
|
||||||
const { issueTypes } = await jiraSoftwareCloudApiRequest.call(
|
const { issueTypes } = await jiraSoftwareCloudApiRequest.call(
|
||||||
this,
|
this,
|
||||||
`/api/2/project/${projectId}`,
|
`/api/2/project/${projectId}`,
|
||||||
|
@ -204,9 +200,146 @@ export class Jira implements INodeType {
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
return returnData;
|
return { results: returnData };
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Get all the users to display them to user so that he can
|
||||||
|
// select them easily
|
||||||
|
async getUsers(this: ILoadOptionsFunctions, filter?: string): Promise<INodeListSearchResult> {
|
||||||
|
const jiraVersion = this.getCurrentNodeParameter('jiraVersion') as string;
|
||||||
|
const query: IDataObject = {};
|
||||||
|
let endpoint = '/api/2/users/search';
|
||||||
|
|
||||||
|
if (jiraVersion === 'server') {
|
||||||
|
endpoint = '/api/2/user/search';
|
||||||
|
query.username = "'";
|
||||||
|
}
|
||||||
|
|
||||||
|
const users = await jiraSoftwareCloudApiRequest.call(this, endpoint, 'GET', {}, query);
|
||||||
|
const returnData: INodeListSearchItems[] = users.reduce(
|
||||||
|
(activeUsers: INodeListSearchItems[], user: IDataObject) => {
|
||||||
|
if (user.active) {
|
||||||
|
activeUsers.push({
|
||||||
|
name: user.displayName as string,
|
||||||
|
value: (user.accountId ?? user.name) as string,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return activeUsers;
|
||||||
|
},
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
|
return { results: filterSortSearchListItems(returnData, filter) };
|
||||||
|
},
|
||||||
|
|
||||||
|
// Get all the priorities to display them to user so that he can
|
||||||
|
// select them easily
|
||||||
|
async getPriorities(this: ILoadOptionsFunctions): Promise<INodeListSearchResult> {
|
||||||
|
const returnData: INodeListSearchItems[] = [];
|
||||||
|
|
||||||
|
const priorities = await jiraSoftwareCloudApiRequest.call(this, '/api/2/priority', 'GET');
|
||||||
|
|
||||||
|
for (const priority of priorities) {
|
||||||
|
const priorityName = priority.name;
|
||||||
|
const priorityId = priority.id;
|
||||||
|
|
||||||
|
returnData.push({
|
||||||
|
name: priorityName,
|
||||||
|
value: priorityId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
returnData.sort((a, b) => {
|
||||||
|
if (a.name < b.name) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (a.name > b.name) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
return { results: returnData };
|
||||||
|
},
|
||||||
|
|
||||||
|
// Get all the transitions (status) to display them to user so that he can
|
||||||
|
// select them easily
|
||||||
|
async getTransitions(this: ILoadOptionsFunctions): Promise<INodeListSearchResult> {
|
||||||
|
const returnData: INodeListSearchItems[] = [];
|
||||||
|
|
||||||
|
const issueKey = this.getCurrentNodeParameter('issueKey');
|
||||||
|
const transitions = await jiraSoftwareCloudApiRequest.call(
|
||||||
|
this,
|
||||||
|
`/api/2/issue/${issueKey}/transitions`,
|
||||||
|
'GET',
|
||||||
|
);
|
||||||
|
|
||||||
|
for (const transition of transitions.transitions) {
|
||||||
|
returnData.push({
|
||||||
|
name: transition.name,
|
||||||
|
value: transition.id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
returnData.sort((a, b) => {
|
||||||
|
if (a.name < b.name) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (a.name > b.name) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
return { results: returnData };
|
||||||
|
},
|
||||||
|
|
||||||
|
// Get all the custom fields to display them to user so that he can
|
||||||
|
// select them easily
|
||||||
|
async getCustomFields(this: ILoadOptionsFunctions): Promise<INodeListSearchResult> {
|
||||||
|
const returnData: INodeListSearchItems[] = [];
|
||||||
|
const operation = this.getCurrentNodeParameter('operation') as string;
|
||||||
|
let projectId: string;
|
||||||
|
let issueTypeId: string;
|
||||||
|
if (operation === 'create') {
|
||||||
|
projectId = this.getCurrentNodeParameter('project', { extractValue: true }) as string;
|
||||||
|
issueTypeId = this.getCurrentNodeParameter('issueType', { extractValue: true }) as string;
|
||||||
|
} else {
|
||||||
|
const issueKey = this.getCurrentNodeParameter('issueKey') as string;
|
||||||
|
const res = await jiraSoftwareCloudApiRequest.call(
|
||||||
|
this,
|
||||||
|
`/api/2/issue/${issueKey}`,
|
||||||
|
'GET',
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
);
|
||||||
|
projectId = res.fields.project.id;
|
||||||
|
issueTypeId = res.fields.issuetype.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = await jiraSoftwareCloudApiRequest.call(
|
||||||
|
this,
|
||||||
|
`/api/2/issue/createmeta?projectIds=${projectId}&issueTypeIds=${issueTypeId}&expand=projects.issuetypes.fields`,
|
||||||
|
'GET',
|
||||||
|
);
|
||||||
|
|
||||||
|
const fields = res.projects
|
||||||
|
.find((o: any) => o.id === projectId)
|
||||||
|
.issuetypes.find((o: any) => o.id === issueTypeId).fields;
|
||||||
|
|
||||||
|
for (const key of Object.keys(fields)) {
|
||||||
|
const field = fields[key];
|
||||||
|
if (field.schema && Object.keys(field.schema).includes('customId')) {
|
||||||
|
returnData.push({
|
||||||
|
name: field.name,
|
||||||
|
value: field.key || field.fieldId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return { results: returnData };
|
||||||
|
},
|
||||||
|
},
|
||||||
|
loadOptions: {
|
||||||
// Get all the labels to display them to user so that he can
|
// Get all the labels to display them to user so that he can
|
||||||
// select them easily
|
// select them easily
|
||||||
async getLabels(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
async getLabels(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||||
|
@ -237,36 +370,6 @@ export class Jira implements INodeType {
|
||||||
return returnData;
|
return returnData;
|
||||||
},
|
},
|
||||||
|
|
||||||
// Get all the priorities to display them to user so that he can
|
|
||||||
// select them easily
|
|
||||||
async getPriorities(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
|
||||||
const returnData: INodePropertyOptions[] = [];
|
|
||||||
|
|
||||||
const priorities = await jiraSoftwareCloudApiRequest.call(this, '/api/2/priority', 'GET');
|
|
||||||
|
|
||||||
for (const priority of priorities) {
|
|
||||||
const priorityName = priority.name;
|
|
||||||
const priorityId = priority.id;
|
|
||||||
|
|
||||||
returnData.push({
|
|
||||||
name: priorityName,
|
|
||||||
value: priorityId,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
returnData.sort((a, b) => {
|
|
||||||
if (a.name < b.name) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (a.name > b.name) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
return returnData;
|
|
||||||
},
|
|
||||||
|
|
||||||
// Get all the users to display them to user so that he can
|
// Get all the users to display them to user so that he can
|
||||||
// select them easily
|
// select them easily
|
||||||
async getUsers(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
async getUsers(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||||
|
@ -326,90 +429,12 @@ export class Jira implements INodeType {
|
||||||
return returnData;
|
return returnData;
|
||||||
},
|
},
|
||||||
|
|
||||||
// Get all the groups to display them to user so that he can
|
|
||||||
// select them easily
|
|
||||||
async getTransitions(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
|
||||||
const returnData: INodePropertyOptions[] = [];
|
|
||||||
|
|
||||||
const issueKey = this.getCurrentNodeParameter('issueKey');
|
|
||||||
const transitions = await jiraSoftwareCloudApiRequest.call(
|
|
||||||
this,
|
|
||||||
`/api/2/issue/${issueKey}/transitions`,
|
|
||||||
'GET',
|
|
||||||
);
|
|
||||||
|
|
||||||
for (const transition of transitions.transitions) {
|
|
||||||
returnData.push({
|
|
||||||
name: transition.name,
|
|
||||||
value: transition.id,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
returnData.sort((a, b) => {
|
|
||||||
if (a.name < b.name) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (a.name > b.name) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
return returnData;
|
|
||||||
},
|
|
||||||
|
|
||||||
// Get all the custom fields to display them to user so that he can
|
|
||||||
// select them easily
|
|
||||||
async getCustomFields(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
|
||||||
const returnData: INodePropertyOptions[] = [];
|
|
||||||
const operation = this.getCurrentNodeParameter('operation') as string;
|
|
||||||
let projectId: string;
|
|
||||||
let issueTypeId: string;
|
|
||||||
if (operation === 'create') {
|
|
||||||
projectId = this.getCurrentNodeParameter('project') as string;
|
|
||||||
issueTypeId = this.getCurrentNodeParameter('issueType') as string;
|
|
||||||
} else {
|
|
||||||
const issueKey = this.getCurrentNodeParameter('issueKey') as string;
|
|
||||||
const res = await jiraSoftwareCloudApiRequest.call(
|
|
||||||
this,
|
|
||||||
`/api/2/issue/${issueKey}`,
|
|
||||||
'GET',
|
|
||||||
{},
|
|
||||||
{},
|
|
||||||
);
|
|
||||||
projectId = res.fields.project.id;
|
|
||||||
issueTypeId = res.fields.issuetype.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
const res = await jiraSoftwareCloudApiRequest.call(
|
|
||||||
this,
|
|
||||||
`/api/2/issue/createmeta?projectIds=${projectId}&issueTypeIds=${issueTypeId}&expand=projects.issuetypes.fields`,
|
|
||||||
'GET',
|
|
||||||
);
|
|
||||||
|
|
||||||
const fields = res.projects
|
|
||||||
|
|
||||||
.find((o: any) => o.id === projectId)
|
|
||||||
|
|
||||||
.issuetypes.find((o: any) => o.id === issueTypeId).fields;
|
|
||||||
for (const key of Object.keys(fields)) {
|
|
||||||
const field = fields[key];
|
|
||||||
if (field.schema && Object.keys(field.schema).includes('customId')) {
|
|
||||||
returnData.push({
|
|
||||||
name: field.name,
|
|
||||||
value: field.key || field.fieldId,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return returnData;
|
|
||||||
},
|
|
||||||
|
|
||||||
// Get all the components to display them to user so that he can
|
// Get all the components to display them to user so that he can
|
||||||
// select them easily
|
// select them easily
|
||||||
async getProjectComponents(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
async getProjectComponents(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||||
const returnData: INodePropertyOptions[] = [];
|
const returnData: INodePropertyOptions[] = [];
|
||||||
|
|
||||||
const project = this.getCurrentNodeParameter('project');
|
const project = this.getCurrentNodeParameter('project', { extractValue: true });
|
||||||
const { values: components } = await jiraSoftwareCloudApiRequest.call(
|
const { values: components } = await jiraSoftwareCloudApiRequest.call(
|
||||||
this,
|
this,
|
||||||
`/api/2/project/${project}/component`,
|
`/api/2/project/${project}/component`,
|
||||||
|
@ -454,9 +479,29 @@ export class Jira implements INodeType {
|
||||||
if (operation === 'create') {
|
if (operation === 'create') {
|
||||||
for (let i = 0; i < length; i++) {
|
for (let i = 0; i < length; i++) {
|
||||||
const summary = this.getNodeParameter('summary', i) as string;
|
const summary = this.getNodeParameter('summary', i) as string;
|
||||||
const projectId = this.getNodeParameter('project', i) as string;
|
const projectId = this.getNodeParameter('project', i, '', {
|
||||||
const issueTypeId = this.getNodeParameter('issueType', i) as string;
|
extractValue: true,
|
||||||
|
}) as string;
|
||||||
|
const issueTypeId = this.getNodeParameter('issueType', i, '', {
|
||||||
|
extractValue: true,
|
||||||
|
}) as string;
|
||||||
const additionalFields = this.getNodeParameter('additionalFields', i);
|
const additionalFields = this.getNodeParameter('additionalFields', i);
|
||||||
|
|
||||||
|
const assignee = this.getNodeParameter('additionalFields.assignee', i, '', {
|
||||||
|
extractValue: true,
|
||||||
|
});
|
||||||
|
if (assignee) additionalFields.assignee = assignee;
|
||||||
|
|
||||||
|
const reporter = this.getNodeParameter('additionalFields.reporter', i, '', {
|
||||||
|
extractValue: true,
|
||||||
|
});
|
||||||
|
if (reporter) additionalFields.reporter = reporter;
|
||||||
|
|
||||||
|
const priority = this.getNodeParameter('additionalFields.priority', i, '', {
|
||||||
|
extractValue: true,
|
||||||
|
});
|
||||||
|
if (priority) additionalFields.priority = priority;
|
||||||
|
|
||||||
const body: IIssue = {};
|
const body: IIssue = {};
|
||||||
const fields: IFields = {
|
const fields: IFields = {
|
||||||
summary,
|
summary,
|
||||||
|
@ -513,6 +558,12 @@ export class Jira implements INodeType {
|
||||||
const customFields = (additionalFields.customFieldsUi as IDataObject)
|
const customFields = (additionalFields.customFieldsUi as IDataObject)
|
||||||
.customFieldsValues as IDataObject[];
|
.customFieldsValues as IDataObject[];
|
||||||
if (customFields) {
|
if (customFields) {
|
||||||
|
// resolve resource locator fieldId value
|
||||||
|
customFields.forEach((cf) => {
|
||||||
|
if (typeof cf.fieldId !== 'string') {
|
||||||
|
cf.fieldId = ((cf.fieldId as IDataObject).value as string).trim();
|
||||||
|
}
|
||||||
|
});
|
||||||
const data = customFields.reduce(
|
const data = customFields.reduce(
|
||||||
(obj, value) => Object.assign(obj, { [`${value.fieldId}`]: value.fieldValue }),
|
(obj, value) => Object.assign(obj, { [`${value.fieldId}`]: value.fieldValue }),
|
||||||
{},
|
{},
|
||||||
|
@ -560,6 +611,27 @@ export class Jira implements INodeType {
|
||||||
for (let i = 0; i < length; i++) {
|
for (let i = 0; i < length; i++) {
|
||||||
const issueKey = this.getNodeParameter('issueKey', i) as string;
|
const issueKey = this.getNodeParameter('issueKey', i) as string;
|
||||||
const updateFields = this.getNodeParameter('updateFields', i);
|
const updateFields = this.getNodeParameter('updateFields', i);
|
||||||
|
|
||||||
|
const assignee = this.getNodeParameter('updateFields.assignee', i, '', {
|
||||||
|
extractValue: true,
|
||||||
|
});
|
||||||
|
if (assignee) updateFields.assignee = assignee;
|
||||||
|
|
||||||
|
const reporter = this.getNodeParameter('updateFields.reporter', i, '', {
|
||||||
|
extractValue: true,
|
||||||
|
});
|
||||||
|
if (reporter) updateFields.reporter = reporter;
|
||||||
|
|
||||||
|
const priority = this.getNodeParameter('updateFields.priority', i, '', {
|
||||||
|
extractValue: true,
|
||||||
|
});
|
||||||
|
if (priority) updateFields.priority = priority;
|
||||||
|
|
||||||
|
const statusId = this.getNodeParameter('updateFields.statusId', i, '', {
|
||||||
|
extractValue: true,
|
||||||
|
});
|
||||||
|
if (statusId) updateFields.statusId = statusId;
|
||||||
|
|
||||||
const body: IIssue = {};
|
const body: IIssue = {};
|
||||||
const fields: IFields = {};
|
const fields: IFields = {};
|
||||||
if (updateFields.summary) {
|
if (updateFields.summary) {
|
||||||
|
@ -610,6 +682,12 @@ export class Jira implements INodeType {
|
||||||
const customFields = (updateFields.customFieldsUi as IDataObject)
|
const customFields = (updateFields.customFieldsUi as IDataObject)
|
||||||
.customFieldsValues as IDataObject[];
|
.customFieldsValues as IDataObject[];
|
||||||
if (customFields) {
|
if (customFields) {
|
||||||
|
// resolve resource locator fieldId value
|
||||||
|
customFields.forEach((cf) => {
|
||||||
|
if (typeof cf.fieldId !== 'string') {
|
||||||
|
cf.fieldId = ((cf.fieldId as IDataObject).value as string).trim();
|
||||||
|
}
|
||||||
|
});
|
||||||
const data = customFields.reduce(
|
const data = customFields.reduce(
|
||||||
(obj, value) => Object.assign(obj, { [`${value.fieldId}`]: value.fieldValue }),
|
(obj, value) => Object.assign(obj, { [`${value.fieldId}`]: value.fieldValue }),
|
||||||
{},
|
{},
|
||||||
|
@ -825,42 +903,39 @@ export class Jira implements INodeType {
|
||||||
if (!jsonActive) {
|
if (!jsonActive) {
|
||||||
const notificationRecipientsValues = (
|
const notificationRecipientsValues = (
|
||||||
this.getNodeParameter('notificationRecipientsUi', i) as IDataObject
|
this.getNodeParameter('notificationRecipientsUi', i) as IDataObject
|
||||||
).notificationRecipientsValues as IDataObject[];
|
).notificationRecipientsValues as IDataObject;
|
||||||
const notificationRecipients: INotificationRecipients = {};
|
const notificationRecipients: INotificationRecipients = {};
|
||||||
if (notificationRecipientsValues) {
|
if (notificationRecipientsValues) {
|
||||||
// @ts-ignore
|
|
||||||
if (notificationRecipientsValues.reporter) {
|
if (notificationRecipientsValues.reporter) {
|
||||||
// @ts-ignore
|
|
||||||
notificationRecipients.reporter = notificationRecipientsValues.reporter as boolean;
|
notificationRecipients.reporter = notificationRecipientsValues.reporter as boolean;
|
||||||
}
|
}
|
||||||
// @ts-ignore
|
|
||||||
if (notificationRecipientsValues.assignee) {
|
if (notificationRecipientsValues.assignee) {
|
||||||
// @ts-ignore
|
|
||||||
notificationRecipients.assignee = notificationRecipientsValues.assignee as boolean;
|
notificationRecipients.assignee = notificationRecipientsValues.assignee as boolean;
|
||||||
}
|
}
|
||||||
// @ts-ignore
|
|
||||||
if (notificationRecipientsValues.assignee) {
|
if (notificationRecipientsValues.assignee) {
|
||||||
// @ts-ignore
|
|
||||||
notificationRecipients.watchers = notificationRecipientsValues.watchers as boolean;
|
notificationRecipients.watchers = notificationRecipientsValues.watchers as boolean;
|
||||||
}
|
}
|
||||||
// @ts-ignore
|
|
||||||
if (notificationRecipientsValues.voters) {
|
if (notificationRecipientsValues.voters) {
|
||||||
// @ts-ignore
|
|
||||||
notificationRecipients.watchers = notificationRecipientsValues.voters as boolean;
|
notificationRecipients.watchers = notificationRecipientsValues.voters as boolean;
|
||||||
}
|
}
|
||||||
// @ts-ignore
|
|
||||||
if (notificationRecipientsValues.users.length > 0) {
|
if (((notificationRecipientsValues.users as IDataObject[]) || []).length > 0) {
|
||||||
// @ts-ignore
|
notificationRecipients.users = (
|
||||||
notificationRecipients.users = notificationRecipientsValues.users.map((user) => {
|
notificationRecipientsValues.users as IDataObject[]
|
||||||
|
).map((user) => {
|
||||||
return {
|
return {
|
||||||
accountId: user,
|
accountId: user,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// @ts-ignore
|
|
||||||
if (notificationRecipientsValues.groups.length > 0) {
|
if (((notificationRecipientsValues.groups as IDataObject[]) || []).length > 0) {
|
||||||
// @ts-ignore
|
notificationRecipients.groups = (
|
||||||
notificationRecipients.groups = notificationRecipientsValues.groups.map((group) => {
|
notificationRecipientsValues.groups as IDataObject[]
|
||||||
|
).map((group) => {
|
||||||
return {
|
return {
|
||||||
name: group,
|
name: group,
|
||||||
};
|
};
|
||||||
|
@ -870,18 +945,20 @@ export class Jira implements INodeType {
|
||||||
body.to = notificationRecipients;
|
body.to = notificationRecipients;
|
||||||
const notificationRecipientsRestrictionsValues = (
|
const notificationRecipientsRestrictionsValues = (
|
||||||
this.getNodeParameter('notificationRecipientsRestrictionsUi', i) as IDataObject
|
this.getNodeParameter('notificationRecipientsRestrictionsUi', i) as IDataObject
|
||||||
).notificationRecipientsRestrictionsValues as IDataObject[];
|
).notificationRecipientsRestrictionsValues as IDataObject;
|
||||||
const notificationRecipientsRestrictions: NotificationRecipientsRestrictions = {};
|
const notificationRecipientsRestrictions: NotificationRecipientsRestrictions = {};
|
||||||
if (notificationRecipientsRestrictionsValues) {
|
if (notificationRecipientsRestrictionsValues) {
|
||||||
// @ts-ignore
|
if (
|
||||||
if (notificationRecipientsRestrictionsValues.groups.length > 0) {
|
((notificationRecipientsRestrictionsValues.groups as IDataObject[]) || []).length >
|
||||||
notificationRecipientsRestrictions.groups =
|
0
|
||||||
// @ts-ignore
|
) {
|
||||||
notificationRecipientsRestrictionsValues.groups.map((group) => {
|
notificationRecipientsRestrictions.groups = (
|
||||||
return {
|
notificationRecipientsRestrictionsValues.groups as IDataObject[]
|
||||||
name: group,
|
).map((group) => {
|
||||||
};
|
return {
|
||||||
});
|
name: group,
|
||||||
|
};
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
body.restrict = notificationRecipientsRestrictions;
|
body.restrict = notificationRecipientsRestrictions;
|
||||||
|
@ -1075,18 +1152,16 @@ export class Jira implements INodeType {
|
||||||
'GET',
|
'GET',
|
||||||
{},
|
{},
|
||||||
{},
|
{},
|
||||||
// @ts-ignore
|
attachment?.json.content as string,
|
||||||
attachment?.json.content,
|
|
||||||
{ json: false, encoding: null },
|
{ json: false, encoding: null },
|
||||||
);
|
);
|
||||||
//@ts-ignore
|
|
||||||
returnData[index].binary[binaryPropertyName] = await this.helpers.prepareBinaryData(
|
(returnData[index].binary as IBinaryKeyData)[binaryPropertyName] =
|
||||||
buffer,
|
await this.helpers.prepareBinaryData(
|
||||||
// @ts-ignore
|
buffer,
|
||||||
attachment.json.filename,
|
attachment.json.filename as string,
|
||||||
// @ts-ignore
|
attachment.json.mimeType as string,
|
||||||
attachment.json.mimeType,
|
);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1122,25 +1197,21 @@ export class Jira implements INodeType {
|
||||||
const binaryPropertyName = this.getNodeParameter('binaryProperty', 0);
|
const binaryPropertyName = this.getNodeParameter('binaryProperty', 0);
|
||||||
for (const [index, attachment] of returnData.entries()) {
|
for (const [index, attachment] of returnData.entries()) {
|
||||||
returnData[index].binary = {};
|
returnData[index].binary = {};
|
||||||
//@ts-ignore
|
|
||||||
const buffer = await jiraSoftwareCloudApiRequest.call(
|
const buffer = await jiraSoftwareCloudApiRequest.call(
|
||||||
this,
|
this,
|
||||||
'',
|
'',
|
||||||
'GET',
|
'GET',
|
||||||
{},
|
{},
|
||||||
{},
|
{},
|
||||||
// @ts-ignore
|
attachment.json.content as string,
|
||||||
attachment.json.content,
|
|
||||||
{ json: false, encoding: null },
|
{ json: false, encoding: null },
|
||||||
);
|
);
|
||||||
//@ts-ignore
|
(returnData[index].binary as IBinaryKeyData)[binaryPropertyName] =
|
||||||
returnData[index].binary[binaryPropertyName] = await this.helpers.prepareBinaryData(
|
await this.helpers.prepareBinaryData(
|
||||||
buffer,
|
buffer,
|
||||||
// @ts-ignore
|
attachment.json.filename as string,
|
||||||
attachment.json.filename,
|
attachment.json.mimeType as string,
|
||||||
// @ts-ignore
|
);
|
||||||
attachment.json.mimeType,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -359,7 +359,6 @@ export class JiraTrigger implements INodeType {
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
// @ts-ignore (because of request)
|
|
||||||
webhookMethods = {
|
webhookMethods = {
|
||||||
default: {
|
default: {
|
||||||
async checkExists(this: IHookFunctions): Promise<boolean> {
|
async checkExists(this: IHookFunctions): Promise<boolean> {
|
||||||
|
|
Loading…
Reference in a new issue