From 17fb31920e22cc90dfaad94afd26e08bb5408e1d Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Sat, 27 Feb 2021 12:54:45 +0100 Subject: [PATCH] :sparkles: Add DateTime support to IF and Switch-Node --- packages/nodes-base/nodes/If.node.ts | 70 ++++++++++++- packages/nodes-base/nodes/Switch.node.ts | 124 ++++++++++++++++++++++- 2 files changed, 191 insertions(+), 3 deletions(-) diff --git a/packages/nodes-base/nodes/If.node.ts b/packages/nodes-base/nodes/If.node.ts index beba9d3f0e..65bd545e32 100644 --- a/packages/nodes-base/nodes/If.node.ts +++ b/packages/nodes-base/nodes/If.node.ts @@ -73,6 +73,43 @@ export class If implements INodeType { }, ], }, + { + name: 'dateTime', + displayName: 'DateTime', + values: [ + { + displayName: 'Value 1', + name: 'value1', + type: 'dateTime', + default: '', + description: 'The value to compare with the second one.', + }, + { + displayName: 'Operation', + name: 'operation', + type: 'options', + options: [ + { + name: 'After', + value: 'after', + }, + { + name: 'Before', + value: 'before', + }, + ], + default: 'after', + description: 'Operation to decide where the the data should be mapped to.', + }, + { + displayName: 'Value 2', + name: 'value2', + type: 'dateTime', + default: '', + description: 'The value to compare with the first one.', + }, + ], + }, { name: 'number', displayName: 'Number', @@ -259,6 +296,8 @@ export class If implements INodeType { const compareOperationFunctions: { [key: string]: (value1: NodeParameterValue, value2: NodeParameterValue) => boolean; } = { + after: (value1: NodeParameterValue, value2: NodeParameterValue) => (value1 || 0) > (value2 || 0), + before: (value1: NodeParameterValue, value2: NodeParameterValue) => (value1 || 0) < (value2 || 0), contains: (value1: NodeParameterValue, value2: NodeParameterValue) => (value1 || '').toString().includes((value2 || '').toString()), notContains: (value1: NodeParameterValue, value2: NodeParameterValue) => !(value1 || '').toString().includes((value2 || '').toString()), endsWith: (value1: NodeParameterValue, value2: NodeParameterValue) => (value1 as string).endsWith(value2 as string), @@ -286,9 +325,28 @@ export class If implements INodeType { }, }; + // Converts the input data of a dateTime into a number for easy compare + function convertDateTime(value: NodeParameterValue): number { + let returnValue: number | undefined = undefined; + if (typeof value === 'string') { + returnValue = new Date(value).getTime(); + } else if (typeof value === 'number') { + returnValue = value; + } if ((value as any) instanceof Date) { + returnValue = (value as unknown as Date).getTime(); + } + + if (returnValue === undefined || isNaN(returnValue)) { + throw new Error(`The value "${value}" is not a valid DateTime.`); + } + + return returnValue + } + // The different dataTypes to check the values in const dataTypes = [ 'boolean', + 'dateTime', 'number', 'string', ]; @@ -297,6 +355,7 @@ export class If implements INodeType { // which ones via output "false" let dataType: string; let compareOperationResult: boolean; + let value1: NodeParameterValue, value2: NodeParameterValue; itemLoop: for (let itemIndex = 0; itemIndex < items.length; itemIndex++) { item = items[itemIndex]; @@ -310,7 +369,16 @@ export class If implements INodeType { // Check all the values of the current dataType for (compareData of this.getNodeParameter(`conditions.${dataType}`, itemIndex, []) as INodeParameters[]) { // Check if the values passes - compareOperationResult = compareOperationFunctions[compareData.operation as string](compareData.value1 as NodeParameterValue, compareData.value2 as NodeParameterValue); + + value1 = compareData.value1 as NodeParameterValue; + value2 = compareData.value2 as NodeParameterValue; + + if (dataType === 'dateTime') { + value1 = convertDateTime(value1); + value2 = convertDateTime(value2); + } + + compareOperationResult = compareOperationFunctions[compareData.operation as string](value1, value2); if (compareOperationResult === true && combineOperation === 'any') { // If it passes and the operation is "any" we do not have to check any diff --git a/packages/nodes-base/nodes/Switch.node.ts b/packages/nodes-base/nodes/Switch.node.ts index 3d18abf16a..a03b3cc8e0 100644 --- a/packages/nodes-base/nodes/Switch.node.ts +++ b/packages/nodes-base/nodes/Switch.node.ts @@ -87,6 +87,10 @@ export class Switch implements INodeType { name: 'Boolean', value: 'boolean', }, + { + name: 'DateTime', + value: 'dateTime', + }, { name: 'Number', value: 'number', @@ -185,6 +189,91 @@ export class Switch implements INodeType { ], }, + // ---------------------------------- + // dataType:dateTime + // ---------------------------------- + { + displayName: 'Value 1', + name: 'value1', + type: 'dateTime', + displayOptions: { + show: { + dataType: [ + 'dateTime', + ], + mode: [ + 'rules', + ], + }, + }, + default: '', + description: 'The value to compare with the second one.', + }, + { + displayName: 'Routing Rules', + name: 'rules', + placeholder: 'Add Routing Rule', + type: 'fixedCollection', + typeOptions: { + multipleValues: true, + }, + displayOptions: { + show: { + dataType: [ + 'dateTime', + ], + mode: [ + 'rules', + ], + }, + }, + description: 'The routing rules.', + default: {}, + options: [ + { + name: 'rules', + displayName: 'Dates', + values: [ + { + displayName: 'Operation', + name: 'operation', + type: 'options', + options: [ + { + name: 'After', + value: 'after', + }, + { + name: 'Before', + value: 'before', + }, + ], + default: 'after', + description: 'Operation to decide where the the data should be mapped to.', + }, + { + displayName: 'Value 2', + name: 'value2', + type: 'dateTime', + default: 0, + description: 'The value to compare with the first one.', + }, + { + displayName: 'Output', + name: 'output', + type: 'number', + typeOptions: { + minValue: 0, + maxValue: 3, + }, + default: 0, + description: 'The index of output to which to send data to if rule matches.', + }, + ], + }, + ], + }, + // ---------------------------------- // dataType:number // ---------------------------------- @@ -470,12 +559,14 @@ export class Switch implements INodeType { let mode: string; let outputIndex: number; let ruleData: INodeParameters; - let value1: NodeParameterValue; + let value1: NodeParameterValue, value2: NodeParameterValue; // The compare operations const compareOperationFunctions: { [key: string]: (value1: NodeParameterValue, value2: NodeParameterValue) => boolean; } = { + after: (value1: NodeParameterValue, value2: NodeParameterValue) => (value1 || 0) > (value2 || 0), + before: (value1: NodeParameterValue, value2: NodeParameterValue) => (value1 || 0) < (value2 || 0), contains: (value1: NodeParameterValue, value2: NodeParameterValue) => (value1 || '').toString().includes((value2 || '').toString()), notContains: (value1: NodeParameterValue, value2: NodeParameterValue) => !(value1 || '').toString().includes((value2 || '').toString()), endsWith: (value1: NodeParameterValue, value2: NodeParameterValue) => (value1 as string).endsWith(value2 as string), @@ -502,12 +593,32 @@ export class Switch implements INodeType { }, }; + // Converts the input data of a dateTime into a number for easy compare + function convertDateTime(value: NodeParameterValue): number { + let returnValue: number | undefined = undefined; + if (typeof value === 'string') { + returnValue = new Date(value).getTime(); + } else if (typeof value === 'number') { + returnValue = value; + } if ((value as any) instanceof Date) { + returnValue = (value as unknown as Date).getTime(); + } + + if (returnValue === undefined || isNaN(returnValue)) { + throw new Error(`The value "${value}" is not a valid DateTime.`); + } + + return returnValue + } + function checkIndexRange(index: number) { if (index < 0 || index >= returnData.length) { throw new Error(`The ouput ${index} is not allowed. It has to be between 0 and ${returnData.length - 1}!`); } } + const dataType = this.getNodeParameter('dataType', 0) as string; + // Itterate over all items to check to which output they should be routed to itemLoop: for (let itemIndex = 0; itemIndex < items.length; itemIndex++) { @@ -525,10 +636,19 @@ export class Switch implements INodeType { // Rules decide how to route item value1 = this.getNodeParameter('value1', itemIndex) as NodeParameterValue; + if (dataType === 'dateTime') { + value1 = convertDateTime(value1); + } for (ruleData of this.getNodeParameter('rules.rules', itemIndex, []) as INodeParameters[]) { // Check if the values passes - compareOperationResult = compareOperationFunctions[ruleData.operation as string](value1, ruleData.value2 as NodeParameterValue); + + value2 = ruleData.value2 as NodeParameterValue; + if (dataType === 'dateTime') { + value2 = convertDateTime(value2); + } + + compareOperationResult = compareOperationFunctions[ruleData.operation as string](value1, value2); if (compareOperationResult === true) { // If rule matches add it to the correct output and continue with next item