diff --git a/nodes/ITop/ITop.node.ts b/nodes/ITop/ITop.node.ts index 4892fce..aa0b57f 100644 --- a/nodes/ITop/ITop.node.ts +++ b/nodes/ITop/ITop.node.ts @@ -9,6 +9,10 @@ import { import { getFields } from './operations/get'; import { updateFields } from './operations/update'; import { iTopApiRequest, formatITopResponse } from './shared/transport'; +import { createFields } from './operations/create'; +import { deleteFields } from './operations/delete'; +import { applyStimulusFields, applyStimulusOperation } from './operations/apply_stimulus'; + export class ITop implements INodeType { description: INodeTypeDescription = { @@ -79,11 +83,32 @@ export class ITop implements INodeType { action: 'Update an iTop object', description: 'Update a single iTop object', }, + { + name: 'Create', + value: 'create', + action: 'Create a new iTop object', + description: 'Create a new object in iTop', + }, + { + name: 'Delete', + value: 'delete', + action: 'Delete an iTop object', + description: 'Delete an existing object in iTop', + }, + { + name: 'Apply Stimulus', + value: 'apply_stimulus', + action: 'Update an object and apply a stimulus to change its state', + description: 'Update fields and apply a stimulus on a single iTop object', + }, ], default: 'get', }, ...getFields, ...updateFields, + ...createFields, + ...deleteFields, + ...applyStimulusFields, ], }; @@ -127,7 +152,6 @@ export class ITop implements INodeType { const comment = this.getNodeParameter('comment', i, '') as string; const additionalOptions = this.getNodeParameter('additionalOptions', i, {}) as IDataObject; - // Convert fixedCollection format to simple object const fields: IDataObject = {}; if (fieldsToUpdate.field && Array.isArray(fieldsToUpdate.field)) { for (const field of fieldsToUpdate.field) { @@ -156,6 +180,88 @@ export class ITop implements INodeType { const response = await iTopApiRequest.call(this, 'core/update', requestData); const formattedItems = formatITopResponse(response); returnData.push(...formattedItems); + + } else if (operation === 'create') { + const className = this.getNodeParameter('class', i) as string; + const fieldsToCreate = this.getNodeParameter('fields', i) as IDataObject; + const outputFields = this.getNodeParameter('output_fields', i) as string; + const comment = this.getNodeParameter('comment', i, '') as string; + + const fields: IDataObject = {}; + if (fieldsToCreate.field && Array.isArray(fieldsToCreate.field)) { + for (const field of fieldsToCreate.field) { + const fieldData = field as IDataObject; + if (fieldData.name && fieldData.value !== undefined) { + fields[fieldData.name as string] = fieldData.value; + } + } + } + + const requestData: IDataObject = { + class: className, + fields, + output_fields: outputFields, + }; + + if (comment) { + requestData.comment = comment; + } + + const response = await iTopApiRequest.call(this, 'core/create', requestData); + const formattedItems = formatITopResponse(response); + returnData.push(...formattedItems); + + } else if (operation === 'delete') { + const className = this.getNodeParameter('class', i) as string; + const key = this.getNodeParameter('key', i) as string; + const comment = this.getNodeParameter('comment', i, '') as string; + + const requestData: IDataObject = { + class: className, + key, + }; + + if (comment) { + requestData.comment = comment; + } + + const response = await iTopApiRequest.call(this, 'core/delete', requestData); + const formattedItems = formatITopResponse(response); + returnData.push(...formattedItems); + + } else if (operation === 'apply_stimulus') { + const className = this.getNodeParameter('class', i) as string; + const key = this.getNodeParameter('key', i) as string; + const stimulus = this.getNodeParameter('stimulus', i) as string; + const fieldsToUpdate = this.getNodeParameter('fields', i) as IDataObject; + const outputFields = this.getNodeParameter('output_fields', i) as string; + const comment = this.getNodeParameter('comment', i, '') as string; + + const fields: IDataObject = {}; + if (fieldsToUpdate.field && Array.isArray(fieldsToUpdate.field)) { + for (const field of fieldsToUpdate.field) { + const fieldData = field as IDataObject; + if (fieldData.name && fieldData.value !== undefined) { + fields[fieldData.name as string] = fieldData.value; + } + } + } + + const requestData: IDataObject = { + class: className, + key, + stimulus, + fields, + output_fields: outputFields, + }; + + if (comment) { + requestData.comment = comment; + } + + const response = await iTopApiRequest.call(this, 'core/apply_stimulus', requestData); + const formattedItems = formatITopResponse(response); + returnData.push(...formattedItems); } } catch (error) { if (this.continueOnFail()) { diff --git a/nodes/ITop/iTop_Logo_pure_900x311.png b/nodes/ITop/iTop_Logo_pure_900x311.png new file mode 100644 index 0000000..7ff5529 Binary files /dev/null and b/nodes/ITop/iTop_Logo_pure_900x311.png differ diff --git a/nodes/ITop/logo-itop-blanc.png b/nodes/ITop/logo-itop-blanc.png new file mode 100644 index 0000000..7b669d9 Binary files /dev/null and b/nodes/ITop/logo-itop-blanc.png differ diff --git a/nodes/ITop/operations/apply_stimulus.ts b/nodes/ITop/operations/apply_stimulus.ts new file mode 100644 index 0000000..74c9984 --- /dev/null +++ b/nodes/ITop/operations/apply_stimulus.ts @@ -0,0 +1,105 @@ +import type { INodeProperties } from 'n8n-workflow'; +import { classNameField, keyField, outputFieldsField, commentField } from '../shared/descriptions'; + +export const applyStimulusOperation: INodeProperties = { + displayName: 'Operation', + name: 'operation', + type: 'options', + noDataExpression: true, + options: [ + { + name: 'Apply Stimulus', + value: 'apply_stimulus', + action: 'Update an object and apply a stimulus to change its state', + description: 'Update fields and apply a stimulus on a single iTop object', + }, + ], + default: 'apply_stimulus', +}; + +export const applyStimulusFields: INodeProperties[] = [ + { + ...classNameField, + displayOptions: { + show: { + operation: ['apply_stimulus'], + }, + }, + }, + { + ...keyField, + description: 'Object identifier: numeric ID or search criteria. Must uniquely identify one object.', + displayOptions: { + show: { + operation: ['apply_stimulus'], + }, + }, + }, + { + displayName: 'Stimulus', + name: 'stimulus', + type: 'string', + default: '', + required: true, + description: 'The stimulus to apply (e.g. ev_assign)', + displayOptions: { + show: { + operation: ['apply_stimulus'], + }, + }, + }, + { + displayName: 'Fields to Update', + name: 'fields', + type: 'fixedCollection', + typeOptions: { + multipleValues: true, + }, + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + operation: ['apply_stimulus'], + }, + }, + options: [ + { + name: 'field', + displayName: 'Field', + values: [ + { + displayName: 'Field Name', + name: 'name', + type: 'string', + default: '', + placeholder: 'e.g. agent_id, team_id', + description: 'Name of the field to update before applying the stimulus', + }, + { + displayName: 'Field Value', + name: 'value', + type: 'string', + default: '', + description: 'Value to assign to the field', + }, + ], + }, + ], + }, + { + ...outputFieldsField, + displayOptions: { + show: { + operation: ['apply_stimulus'], + }, + }, + }, + { + ...commentField, + displayOptions: { + show: { + operation: ['apply_stimulus'], + }, + }, + }, +]; diff --git a/nodes/ITop/operations/create.ts b/nodes/ITop/operations/create.ts new file mode 100644 index 0000000..23b367b --- /dev/null +++ b/nodes/ITop/operations/create.ts @@ -0,0 +1,84 @@ +import type { INodeProperties } from 'n8n-workflow'; +import { classNameField, outputFieldsField, commentField } from '../shared/descriptions'; + +export const createOperation: INodeProperties = { + displayName: 'Operation', + name: 'operation', + type: 'options', + noDataExpression: true, + options: [ + { + name: 'Create', + value: 'create', + action: 'Create a new iTop object', + description: 'Create a new object in iTop with given field values', + }, + ], + default: 'create', +}; + +export const createFields: INodeProperties[] = [ + { + ...classNameField, + displayOptions: { + show: { + operation: ['create'], + }, + }, + }, + { + displayName: 'Fields', + name: 'fields', + type: 'fixedCollection', + typeOptions: { + multipleValues: true, + }, + placeholder: 'Add Field', + default: {}, + required: true, + displayOptions: { + show: { + operation: ['create'], + }, + }, + options: [ + { + name: 'field', + displayName: 'Field', + values: [ + { + displayName: 'Field Name', + name: 'name', + type: 'string', + default: '', + placeholder: 'e.g. name, org_id, description', + description: 'Name of the field to set when creating the object', + }, + { + displayName: 'Field Value', + name: 'value', + type: 'string', + default: '', + description: 'Value to assign to the field', + }, + ], + }, + ], + }, + { + ...outputFieldsField, + displayOptions: { + show: { + operation: ['create'], + }, + }, + }, + { + ...commentField, + displayOptions: { + show: { + operation: ['create'], + }, + }, + }, +]; diff --git a/nodes/ITop/operations/delete.ts b/nodes/ITop/operations/delete.ts new file mode 100644 index 0000000..76c9c8e --- /dev/null +++ b/nodes/ITop/operations/delete.ts @@ -0,0 +1,46 @@ +import type { INodeProperties } from 'n8n-workflow'; +import { classNameField, keyField, commentField } from '../shared/descriptions'; + +export const deleteOperation: INodeProperties = { + displayName: 'Operation', + name: 'operation', + type: 'options', + noDataExpression: true, + options: [ + { + name: 'Delete', + value: 'delete', + action: 'Delete an iTop object', + description: 'Delete an existing object in iTop', + }, + ], + default: 'delete', +}; + +export const deleteFields: INodeProperties[] = [ + { + ...classNameField, + displayOptions: { + show: { + operation: ['delete'], + }, + }, + }, + { + ...keyField, + description: 'The key or ID of the object to delete. Must uniquely identify one object.', + displayOptions: { + show: { + operation: ['delete'], + }, + }, + }, + { + ...commentField, + displayOptions: { + show: { + operation: ['delete'], + }, + }, + }, +];