diff --git a/packages/nodes-base/nodes/KoBoToolbox/GenericFunctions.ts b/packages/nodes-base/nodes/KoBoToolbox/GenericFunctions.ts index 07afbadbdba7d..efb37d26b224f 100644 --- a/packages/nodes-base/nodes/KoBoToolbox/GenericFunctions.ts +++ b/packages/nodes-base/nodes/KoBoToolbox/GenericFunctions.ts @@ -173,10 +173,14 @@ export async function downloadAttachments(this: IExecuteFunctions | IWebhookFunc for (const [index, attachment] of attachmentList.entries()) { // look for the question name linked to this attachment const filename = attachment.filename; - Object.keys(submission).forEach(question => { - if (filename.endsWith('/' + _.toString(submission[question]).replace(/\s/g, '_'))) { - } - }); + let relatedQuestion = null; + if('question' === options.binaryNamingScheme) { + Object.keys(submission).forEach(question => { + if (filename.endsWith('/' + _.toString(submission[question]).replace(/\s/g, '_'))) { + relatedQuestion = question; + } + }); + } // Download attachment // NOTE: this needs to follow redirects (possibly across domains), while keeping Authorization headers @@ -209,11 +213,18 @@ export async function downloadAttachments(this: IExecuteFunctions | IWebhookFunc } } - const dataPropertyAttachmentsPrefixName = options.dataPropertyAttachmentsPrefixName || 'attachment_'; - const fileName = filename.split('/').pop(); - if (response && response.body) { - binaryItem.binary![`${dataPropertyAttachmentsPrefixName}${index}`] = await this.helpers.prepareBinaryData(response.body, fileName); + // Use the provided prefix if any, otherwise try to use the original question name + let binaryName; + if('question' === options.binaryNamingScheme && relatedQuestion) { + binaryName = relatedQuestion; + } + else { + binaryName = `${options.dataPropertyAttachmentsPrefixName || 'attachment_'}${index}`; + } + const fileName = filename.split('/').pop(); + + binaryItem.binary![binaryName] = await this.helpers.prepareBinaryData(response.body, fileName); } } } else { diff --git a/packages/nodes-base/nodes/KoBoToolbox/KoBoToolbox.node.ts b/packages/nodes-base/nodes/KoBoToolbox/KoBoToolbox.node.ts index 0410da5ca15ec..b6e2c6f092628 100644 --- a/packages/nodes-base/nodes/KoBoToolbox/KoBoToolbox.node.ts +++ b/packages/nodes-base/nodes/KoBoToolbox/KoBoToolbox.node.ts @@ -194,13 +194,14 @@ export class KoBoToolbox implements INodeType { // ---------------------------------- const submissionQueryOptions = this.getNodeParameter('options', i) as IDataObject; + const filterJson = this.getNodeParameter('filterJson', i, null) as string; responseData = await koBoToolboxApiRequest.call(this, { url: `/api/v2/assets/${formId}/data/`, qs: { limit: this.getNodeParameter('limit', i, 1000) as number, - ...(submissionQueryOptions.query && { query: submissionQueryOptions.query }), - //...(submissionQueryOptions.sort && { sort: submissionQueryOptions.sort }), + ...(filterJson && { query: filterJson }), + ...(submissionQueryOptions.sort && { sort: submissionQueryOptions.sort }), ...(submissionQueryOptions.fields && { fields: JSON.stringify(parseStringList(submissionQueryOptions.fields as string)) }), }, scroll: this.getNodeParameter('returnAll', i) as boolean, diff --git a/packages/nodes-base/nodes/KoBoToolbox/KoBoToolboxTrigger.node.ts b/packages/nodes-base/nodes/KoBoToolbox/KoBoToolboxTrigger.node.ts index ed97f2ce3d18b..f62cb48a018e2 100644 --- a/packages/nodes-base/nodes/KoBoToolbox/KoBoToolboxTrigger.node.ts +++ b/packages/nodes-base/nodes/KoBoToolbox/KoBoToolboxTrigger.node.ts @@ -16,7 +16,7 @@ import { } from './GenericFunctions'; import { - options, + options, } from './Options'; export class KoBoToolboxTrigger implements INodeType { @@ -98,13 +98,14 @@ export class KoBoToolboxTrigger implements INodeType { async create(this: IHookFunctions): Promise { const webhookData = this.getWorkflowStaticData('node'); const webhookUrl = this.getNodeWebhookUrl('default'); + const workflow = this.getWorkflow(); const formId = this.getNodeParameter('formId') as string; //tslint:disable-line:variable-name const response = await koBoToolboxApiRequest.call(this, { method: 'POST', url: `/api/v2/assets/${formId}/hooks/`, body: { - name: `n8n-webhook:${webhookUrl}`, + name: `n8n webhook id ${workflow.id}: ${workflow.name}`, endpoint: webhookUrl, email_notification: true, }, diff --git a/packages/nodes-base/nodes/KoBoToolbox/Options.ts b/packages/nodes-base/nodes/KoBoToolbox/Options.ts index db5c3210854d4..6f7613ca1262f 100644 --- a/packages/nodes-base/nodes/KoBoToolbox/Options.ts +++ b/packages/nodes-base/nodes/KoBoToolbox/Options.ts @@ -9,6 +9,36 @@ export const options = { type: 'collection', default: {}, options: [ + { + displayName: 'Download Attachments', + name: 'download', + type: 'boolean', + default: false, + description: 'Download submitted attachments', + }, + { + displayName: 'Attachments Naming Scheme', + name: 'binaryNamingScheme', + type: 'options', + default: 'sequence', + displayOptions: { + show: { + download: [ + true, + ], + }, + }, + options: [ + { + name: 'Sequence (e.g. attachment_N)', + value: 'sequence', + }, + { + name: 'Use Original Form Question ID', + value: 'question', + }, + ], + }, { displayName: 'Attachments Prefix', name: 'dataPropertyAttachmentsPrefixName', @@ -18,18 +48,14 @@ export const options = { download: [ true, ], + binaryNamingScheme: [ + 'sequence', + ], }, }, default: 'attachment_', description: 'Prefix for name of the binary property to which to write the attachments. An index starting with 0 will be added. So if name is "attachment_" the first attachment is saved to "attachment_0"', }, - { - displayName: 'Download Attachments', - name: 'download', - type: 'boolean', - default: false, - description: 'Download submitted attachments', - }, { displayName: 'File Size', name: 'version', diff --git a/packages/nodes-base/nodes/KoBoToolbox/SubmissionDescription.ts b/packages/nodes-base/nodes/KoBoToolbox/SubmissionDescription.ts index 7ccc24751e044..fe9560edebfec 100644 --- a/packages/nodes-base/nodes/KoBoToolbox/SubmissionDescription.ts +++ b/packages/nodes-base/nodes/KoBoToolbox/SubmissionDescription.ts @@ -192,6 +192,73 @@ export const submissionFields: INodeProperties[] = [ default: 100, description: 'Max number of results to return', }, + { + displayName: 'Filter', + name: 'filterType', + type: 'options', + default: 'none', + displayOptions: { + show: { + resource: [ + 'submission', + ], + operation: [ + 'getAll', + ], + }, + }, + options: [ + { + name: 'None', + value: 'none', + }, + { + name: 'JSON', + value: 'json', + }, + ], + }, + { + displayName: 'See Formhub API docs to creating filters, using the MongoDB JSON format - e.g. {"_submission_time":{"$lt":"2021-10-01T01:02:03"}}', + name: 'jsonNotice', + type: 'notice', + displayOptions: { + show: { + resource: [ + 'submission', + ], + operation: [ + 'getAll', + ], + filterType: [ + 'json', + ], + }, + }, + default: '', + }, + { + displayName: 'Filters (JSON)', + name: 'filterJson', + type: 'string', + default: '', + typeOptions: { + // alwaysOpenEditWindow: true, + }, + displayOptions: { + show: { + resource: [ + 'submission', + ], + operation: [ + 'getAll', + ], + filterType: [ + 'json', + ], + }, + }, + }, { displayName: 'Options', name: 'options', @@ -210,6 +277,36 @@ export const submissionFields: INodeProperties[] = [ default: {}, placeholder: 'Add Option', options: [ + { + displayName: 'Download Attachments', + name: 'download', + type: 'boolean', + default: false, + description: 'Download submitted attachments', + }, + { + displayName: 'Attachments Naming Scheme', + name: 'binaryNamingScheme', + type: 'options', + default: 'sequence', + displayOptions: { + show: { + download: [ + true, + ], + }, + }, + options: [ + { + name: 'Sequence (e.g. attachment_N)', + value: 'sequence', + }, + { + name: 'Use Original Form Question ID', + value: 'question', + }, + ], + }, { displayName: 'Attachments Prefix', name: 'dataPropertyAttachmentsPrefixName', @@ -219,18 +316,14 @@ export const submissionFields: INodeProperties[] = [ download: [ true, ], + binaryNamingScheme: [ + 'sequence', + ], }, }, default: 'attachment_', description: 'Prefix for name of the binary property to which to write the attachments. An index starting with 0 will be added. So if name is "attachment_" the first attachment is saved to "attachment_0"', }, - { - displayName: 'Download Attachments', - name: 'download', - type: 'boolean', - default: false, - description: 'Download submitted attachments', - }, { displayName: 'Fields to Retrieve', name: 'fields', @@ -291,13 +384,13 @@ export const submissionFields: INodeProperties[] = [ default: false, description: 'Apply some reformatting to the submission data, such as parsing GeoJSON coordinates', }, - // { - // displayName: 'Sort', - // name: 'sort', - // type: 'json', - // default: '', - // description: 'Sort predicates, in Mongo JSON format (e.g. {"_submission_time":1})', - // }, + { + displayName: 'Sort', + name: 'sort', + type: 'json', + default: '', + description: 'Sort predicates, in MongoDB JSON format (e.g. {"_submission_time":1})', + }, ], }, ];