diff --git a/packages/nodes-base/nodes/Cockpit/Cockpit.node.ts b/packages/nodes-base/nodes/Cockpit/Cockpit.node.ts index bac4b2213f..efd233f749 100644 --- a/packages/nodes-base/nodes/Cockpit/Cockpit.node.ts +++ b/packages/nodes-base/nodes/Cockpit/Cockpit.node.ts @@ -21,6 +21,7 @@ import { formOperations } from './FormDescription'; import { submitForm } from './FormFunctions'; +import { createDataFromParameters } from './GenericFunctions'; import { singletonFields, singletonOperations, @@ -56,7 +57,7 @@ export class Cockpit implements INodeType { displayName: 'Resource', name: 'resource', type: 'options', - default: 'collections', + default: 'collection', description: 'Resource to consume.', options: [ { @@ -74,7 +75,6 @@ export class Cockpit implements INodeType { ], }, - ...collectionOperations, ...collectionFields, ...formOperations, @@ -84,7 +84,6 @@ export class Cockpit implements INodeType { ], }; - methods = { loadOptions: { async getCollections(this: ILoadOptionsFunctions): Promise { @@ -123,34 +122,37 @@ export class Cockpit implements INodeType { for (let i = 0; i < length; i++) { if (resource === 'collection') { const collectionName = this.getNodeParameter('collection', i) as string; + if (operation === 'create') { - const data = this.getNodeParameter('data', i) as IDataObject; + const data = createDataFromParameters.call(this, i); responseData = await createCollectionEntry.call(this, collectionName, data); } else if (operation === 'getAll') { const options = this.getNodeParameter('options', i) as IDataObject; const returnAll = this.getNodeParameter('returnAll', i) as boolean; - if (returnAll !== true) { + if (!returnAll) { options.limit = this.getNodeParameter('limit', i) as number; } responseData = await getAllCollectionEntries.call(this, collectionName, options); } else if (operation === 'update') { const id = this.getNodeParameter('id', i) as string; - const data = this.getNodeParameter('data', i) as IDataObject; + const data = createDataFromParameters.call(this, i); responseData = await createCollectionEntry.call(this, collectionName, data, id); } } else if (resource === 'form') { const formName = this.getNodeParameter('form', i) as string; + if (operation === 'submit') { - const form = this.getNodeParameter('form', i) as IDataObject; + const form = createDataFromParameters.call(this, i); responseData = await submitForm.call(this, formName, form); } } else if (resource === 'singleton') { const singletonName = this.getNodeParameter('singleton', i) as string; + if (operation === 'get') { responseData = await getSingleton.call(this, singletonName); } diff --git a/packages/nodes-base/nodes/Cockpit/CollectionDescription.ts b/packages/nodes-base/nodes/Cockpit/CollectionDescription.ts index e448ce670e..92420c2570 100644 --- a/packages/nodes-base/nodes/Cockpit/CollectionDescription.ts +++ b/packages/nodes-base/nodes/Cockpit/CollectionDescription.ts @@ -14,17 +14,17 @@ export const collectionOperations = [ }, options: [ { - name: 'Create an entry', + name: 'Create an Entry', value: 'create', description: 'Create a collection entry', }, { - name: 'Get all entries', + name: 'Get all Entries', value: 'getAll', description: 'Get all collection entries', }, { - name: 'Update an entry', + name: 'Update an Entry', value: 'update', description: 'Update a collection entries', }, @@ -54,29 +54,6 @@ export const collectionFields = [ description: 'Name of the collection to operate on.' }, - // Collection:entry:create - { - displayName: 'Data', - name: 'data', - type: 'json', - required: true, - default: '', - typeOptions: { - alwaysOpenEditWindow: true, - }, - displayOptions: { - show: { - resource: [ - 'collection', - ], - operation: [ - 'create', - ] - }, - }, - description: 'The data to create.', - }, - // Collection:entry:getAll { displayName: 'Return All', @@ -139,22 +116,24 @@ export const collectionFields = [ { displayName: 'Fields', name: 'fields', - type: 'json', + type: 'string', default: '', typeOptions: { alwaysOpenEditWindow: true, }, - description: 'Fields to get.', + placeholder: '_id,name', + description: 'Comma separated list of fields to get.', }, { - displayName: 'Filter', + displayName: 'Filter Query', name: 'filter', type: 'json', default: '', typeOptions: { alwaysOpenEditWindow: true, }, - description: 'Filter result by fields.', + placeholder: '{"name": "Jim"}', + description: 'Filter query in Mongolite format.', }, { displayName: 'Language', @@ -186,11 +165,12 @@ export const collectionFields = [ description: 'Skip number of entries.', }, { - displayName: 'Sort', + displayName: 'Sort Query', name: 'sort', type: 'json', default: '', - description: 'Sort result by fields.', + placeholder: '{"price": -1}', + description: 'Sort query in Mongolite format.', }, ], }, @@ -214,25 +194,95 @@ export const collectionFields = [ }, description: 'The entry ID.', }, + + // Collection:entry:create + // Collection:entry:update { - displayName: 'Data', - name: 'data', - type: 'json', - required: true, - default: '', - typeOptions: { - alwaysOpenEditWindow: true, - }, + displayName: 'JSON Data fields', + name: 'jsonDataFields', + type: 'boolean', + default: false, displayOptions: { show: { resource: [ 'collection', ], operation: [ + 'create', 'update', ] }, }, - description: 'The data to update.', + description: 'If new entry fields should be set via the value-key pair UI or JSON.', + }, + { + displayName: 'Entry Data', + name: 'dataFieldsJson', + type: 'json', + default: '', + typeOptions: { + alwaysOpenEditWindow: true, + }, + displayOptions: { + show: { + jsonDataFields: [ + true, + ], + resource: [ + 'collection', + ], + operation: [ + 'create', + 'update', + ] + }, + }, + description: 'Entry data to send as JSON.', + }, + { + displayName: 'Entry Data', + name: 'dataFieldsUi', + type: 'fixedCollection', + typeOptions: { + multipleValues: true, + }, + default: {}, + displayOptions: { + show: { + jsonDataFields: [ + false, + ], + resource: [ + 'collection', + ], + operation: [ + 'create', + 'update', + ] + }, + }, + options: [ + { + displayName: 'Field', + name: 'field', + values: [ + { + displayName: 'Name', + name: 'name', + type: 'string', + default: '', + description: 'Name of the field.', + }, + { + displayName: 'Value', + name: 'value', + type: 'string', + default: '', + description: 'Value of the field.', + }, + ], + }, + ], + description: 'Entry data to send.', }, ] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/Cockpit/CollectionFunctions.ts b/packages/nodes-base/nodes/Cockpit/CollectionFunctions.ts index 4a2c640f84..d508629840 100644 --- a/packages/nodes-base/nodes/Cockpit/CollectionFunctions.ts +++ b/packages/nodes-base/nodes/Cockpit/CollectionFunctions.ts @@ -9,7 +9,7 @@ import { cockpitApiRequest } from './GenericFunctions'; export async function createCollectionEntry(this: IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, resourceName: string, data: IDataObject, id?: string): Promise { // tslint:disable-line:no-any const body: ICollection = { - data: JSON.parse(data.toString()) + data, }; if (id) { @@ -27,7 +27,16 @@ export async function getAllCollectionEntries(this: IExecuteFunctions | IExecute const body: ICollection = {}; if (options.fields) { - body.fields = JSON.parse(options.fields.toString()); + const fields = (options.fields as string).split(',').map(field => field.trim() ); + + const bodyFields = { + _id: false, + } as IDataObject; + for (const field of fields) { + bodyFields[field] = true; + } + + body.fields = bodyFields; } if (options.filter) { diff --git a/packages/nodes-base/nodes/Cockpit/FormDescription.ts b/packages/nodes-base/nodes/Cockpit/FormDescription.ts index 8488cbe095..66a5c052ec 100644 --- a/packages/nodes-base/nodes/Cockpit/FormDescription.ts +++ b/packages/nodes-base/nodes/Cockpit/FormDescription.ts @@ -14,7 +14,7 @@ export const formOperations = [ }, options: [ { - name: 'Submit a form', + name: 'Submit a Form', value: 'submit', description: 'Store submission of a form', }, @@ -44,21 +44,88 @@ export const formFields = [ // Form:submit { - displayName: 'Form data', - name: 'form', + displayName: 'JSON Data fields', + name: 'jsonDataFields', + type: 'boolean', + default: false, + displayOptions: { + show: { + resource: [ + 'form', + ], + operation: [ + 'submit', + ] + }, + }, + description: 'If form fields should be set via the value-key pair UI or JSON.', + }, + { + displayName: 'Form Data', + name: 'dataFieldsJson', type: 'json', - required: true, default: '', typeOptions: { alwaysOpenEditWindow: true, }, displayOptions: { show: { + jsonDataFields: [ + true, + ], resource: [ 'form', ], + operation: [ + 'submit', + ] }, }, - description: 'The data to save.', + description: 'Form data to send as JSON.', + }, + { + displayName: 'Form Data', + name: 'dataFieldsUi', + type: 'fixedCollection', + typeOptions: { + multipleValues: true, + }, + default: {}, + displayOptions: { + show: { + jsonDataFields: [ + false, + ], + resource: [ + 'form', + ], + operation: [ + 'submit', + ] + }, + }, + options: [ + { + displayName: 'Field', + name: 'field', + values: [ + { + displayName: 'Name', + name: 'name', + type: 'string', + default: '', + description: 'Name of the field.', + }, + { + displayName: 'Value', + name: 'value', + type: 'string', + default: '', + description: 'Value of the field.', + }, + ], + }, + ], + description: 'Form data to send.', }, ] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/Cockpit/FormFunctions.ts b/packages/nodes-base/nodes/Cockpit/FormFunctions.ts index 437ed210a0..36a1bdc389 100644 --- a/packages/nodes-base/nodes/Cockpit/FormFunctions.ts +++ b/packages/nodes-base/nodes/Cockpit/FormFunctions.ts @@ -9,7 +9,7 @@ import { cockpitApiRequest } from './GenericFunctions'; export async function submitForm(this: IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, resourceName: string, form: IDataObject) { const body: IForm = { - form: JSON.parse(form.toString()) + form }; return cockpitApiRequest.call(this, 'post', `/forms/submit/${resourceName}`, body); diff --git a/packages/nodes-base/nodes/Cockpit/GenericFunctions.ts b/packages/nodes-base/nodes/Cockpit/GenericFunctions.ts index ed923d3bda..3f3bf39ac2 100644 --- a/packages/nodes-base/nodes/Cockpit/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Cockpit/GenericFunctions.ts @@ -44,3 +44,26 @@ export async function cockpitApiRequest(this: IExecuteFunctions | IExecuteSingle throw new Error(`Cockpit error [${error.statusCode}]: ` + errorMessage); } } + +export function createDataFromParameters(this: IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, itemIndex: number): IDataObject { + const dataFieldsAreJson = this.getNodeParameter('jsonDataFields', itemIndex) as boolean; + + if (dataFieldsAreJson) { + // Parameters are defined as JSON + return JSON.parse(this.getNodeParameter('dataFieldsJson', itemIndex, {}) as string); + } + + // Parameters are defined in UI + const uiDataFields = this.getNodeParameter('dataFieldsUi', itemIndex, {}) as IDataObject; + const unpacked: IDataObject = {}; + + if (uiDataFields.field === undefined) { + return unpacked; + } + + for (const field of uiDataFields!.field as IDataObject[]) { + unpacked[field!.name as string] = field!.value; + } + + return unpacked; +} diff --git a/packages/nodes-base/nodes/Cockpit/SingletonDescription.ts b/packages/nodes-base/nodes/Cockpit/SingletonDescription.ts index e9774b4f5f..98df8a03d9 100644 --- a/packages/nodes-base/nodes/Cockpit/SingletonDescription.ts +++ b/packages/nodes-base/nodes/Cockpit/SingletonDescription.ts @@ -16,7 +16,7 @@ export const singletonOperations = [ { name: 'Get', value: 'get', - description: 'Gets a singleton', + description: 'Gets a Singleton', }, ], default: 'get',