diff --git a/app/controllers/catalog_controller.rb b/app/controllers/catalog_controller.rb index cf519a05c39..c3b6e198c3c 100644 --- a/app/controllers/catalog_controller.rb +++ b/app/controllers/catalog_controller.rb @@ -2,6 +2,7 @@ class CatalogController < ApplicationController include AutomateTreeHelper include Mixins::ServiceDialogCreationMixin include Mixins::BreadcrumbsMixin + include Mixins::AutomationMixin before_action :check_privileges before_action :get_session_data diff --git a/app/controllers/mixins/automation_mixin.rb b/app/controllers/mixins/automation_mixin.rb new file mode 100644 index 00000000000..5765fdf7386 --- /dev/null +++ b/app/controllers/mixins/automation_mixin.rb @@ -0,0 +1,42 @@ +module Mixins + module AutomationMixin + # Returns an object to be reused for passing down to service catalogs(rails) and dialog(angular) form. + # used in catalogs_helper, miq_ae_customization_helper, catalog_controller, editor.html.haml + AUTOMATION_TYPES = { + :automate => { + :key => 'embedded_automate', + :label => _('Embedded Automate'), + :fields => ['ae_namespace', 'ae_class', 'ae_instance', 'ae_message', 'ae_attributes'], + }, + :workflow => { + :key => 'embedded_workflow', + :label => _('Embedded Workflow'), + :fields => ['configuration_script_id', 'workflow_name'], + }, + }.freeze + + # Returns an array of entry point options. + # used in provision_entry_points, retirement_entry_points, reconfigure_entry_points html files + def automation_type_options + options = [["<#{_('No Entry Point')}>", nil]] + options + AUTOMATION_TYPES.values.map do |item| + [item[:label], item[:key]] + end + end + + # Returns true if the field holds value 'embedded_automate' + def embedded_automate(field) + field == AUTOMATION_TYPES[:automate][:key] + end + + # Returns true if the field holds value 'embedded_workflow' + def embedded_workflow(field) + field == AUTOMATION_TYPES[:workflow][:key] + end + + # Returns the default automation type 'embedded_automate' + def default_automation_type + AUTOMATION_TYPES[:automate][:key] + end + end +end diff --git a/app/helpers/miq_ae_customization_helper.rb b/app/helpers/miq_ae_customization_helper.rb index f3d1a7aceab..d15a2b4f016 100644 --- a/app/helpers/miq_ae_customization_helper.rb +++ b/app/helpers/miq_ae_customization_helper.rb @@ -1,4 +1,10 @@ module MiqAeCustomizationHelper + include Mixins::AutomationMixin + + def editor_automation_types + AUTOMATION_TYPES.to_json + end + def dialog_id_action url = request.parameters if url[:id].present? diff --git a/app/javascript/oldjs/controllers/dialog_editor/dialog_editor_controller.js b/app/javascript/oldjs/controllers/dialog_editor/dialog_editor_controller.js index e62addaf796..bf8c76b30f3 100644 --- a/app/javascript/oldjs/controllers/dialog_editor/dialog_editor_controller.js +++ b/app/javascript/oldjs/controllers/dialog_editor/dialog_editor_controller.js @@ -1,4 +1,4 @@ -ManageIQ.angular.app.controller('dialogEditorController', ['$window', 'miqService', 'DialogEditor', 'DialogEditorHttp', 'DialogValidation', 'dialogIdAction', function($window, miqService, DialogEditor, DialogEditorHttp, DialogValidation, dialogIdAction) { +ManageIQ.angular.app.controller('dialogEditorController', ['$window', 'miqService', 'DialogEditor', 'DialogEditorHttp', 'DialogValidation', 'dialogIdAction', 'automationKeys', 'emsWorkflowsEnabled', function($window, miqService, DialogEditor, DialogEditorHttp, DialogValidation, dialogIdAction, automationKeys, emsWorkflowsEnabled) { var vm = this; vm.saveButtonDisabled = false; @@ -9,8 +9,13 @@ ManageIQ.angular.app.controller('dialogEditorController', ['$window', 'miqServic vm.treeOptions = { load: DialogEditorHttp.treeSelectorLoadData, lazyLoad: DialogEditorHttp.treeSelectorLazyLoadData, + loadAvailableWorkflows: DialogEditorHttp.loadAvailableWorkflows, + loadWorkflow: DialogEditorHttp.loadWorkflow, + emsWorkflowsEnabled, }; + vm.dropDownEntryPoints = requestAutomationKeys(); + function requestDialogId() { return JSON.parse(dialogIdAction).id; } @@ -19,6 +24,11 @@ ManageIQ.angular.app.controller('dialogEditorController', ['$window', 'miqServic return JSON.parse(dialogIdAction).action; } + /** Function to get the automation_keys from editor.html.haml which gets the values from AutomationMixin */ + function requestAutomationKeys() { + return JSON.parse(automationKeys); + } + if (requestDialogAction() === 'new') { var dialogInitContent = { 'content': [{ @@ -53,6 +63,23 @@ ManageIQ.angular.app.controller('dialogEditorController', ['$window', 'miqServic } } + /** Function to set the automation_type as 'embedded_automate' / 'embedded_workflow'. + * Also deletes few attributes from resource_action based on the selected automation_type. + */ + function setAutomationFields(field) { + const { automate, workflow } = vm.dropDownEntryPoints; + const automationFields = field.resource_action.configuration_script_id + ? { automationType: workflow.key, resetFields: automate.fields } + : { automationType: automate.key, resetFields: workflow.fields }; + + field.automation_type = automationFields.automationType; + automationFields.resetFields.forEach((item) => { + if (field.resource_action.hasOwnProperty(item)) { + delete field.resource_action[item]; + } + }); + } + function translateResponderNamesToIds(dialog) { var dynamicFields = []; var allFields = []; @@ -60,6 +87,7 @@ ManageIQ.angular.app.controller('dialogEditorController', ['$window', 'miqServic _.forEach(dialog.dialog_tabs, function(tab) { _.forEach(tab.dialog_groups, function(group) { _.forEach(group.dialog_fields, function(field) { + setAutomationFields(field); if (field.dynamic === true) { dynamicFields.push(field); } @@ -149,7 +177,8 @@ ManageIQ.angular.app.controller('dialogEditorController', ['$window', 'miqServic dialog_tabs: [], }, }; - dialogData.content.dialog_tabs = _.cloneDeepWith(DialogEditor.getDialogTabs(), customizer); + const dialogTabs = _.cloneDeepWith(DialogEditor.getDialogTabs(), customizer); + dialogData.content.dialog_tabs = reconfigureDialogTabs(dialogTabs); } else { action = 'create'; dialogId = ''; @@ -159,12 +188,31 @@ ManageIQ.angular.app.controller('dialogEditorController', ['$window', 'miqServic buttons: 'submit,cancel', dialog_tabs: [], }; - dialogData.dialog_tabs = _.cloneDeepWith(DialogEditor.getDialogTabs(), customizer); + const dialogTabs = _.cloneDeepWith(DialogEditor.getDialogTabs(), customizer); + dialogData.dialog_tabs = reconfigureDialogTabs(dialogTabs); } DialogEditorHttp.saveDialog(dialogId, action, dialogData).then(saveSuccess, saveFailure); } + /** Fnuction to remove the automation_type and workflow_name attributes from field's resource_action + * as they are not required to be processed in backend. */ + function reconfigureDialogTabs(dialogTabs) { + dialogTabs.forEach((tab) => { + tab.dialog_groups.forEach((group) => { + group.dialog_fields.forEach((field) => { + if (field.hasOwnProperty('automation_type')) { + delete field.automation_type; + } + if (field.resource_action.hasOwnProperty('workflow_name')) { + delete field.resource_action.workflow_name; + } + }); + }); + }); + return dialogTabs; + } + function dismissChanges() { if (confirm(__('Abandon changes?'))) { DialogEditor.clearSessionStorage(DialogEditor.getDialogId()); diff --git a/app/javascript/oldjs/services/dialog_editor_http_service.js b/app/javascript/oldjs/services/dialog_editor_http_service.js index 6ccf6b15b70..9831a57393e 100644 --- a/app/javascript/oldjs/services/dialog_editor_http_service.js +++ b/app/javascript/oldjs/services/dialog_editor_http_service.js @@ -31,4 +31,18 @@ ManageIQ.angular.app.service('DialogEditorHttp', ['$http', 'API', function($http '?expand=resources' + '&attributes=id,name,description,single_value,children'); }; + + /** Function to load all available workflows when 'Embedded Workflow' is selected for dynamic field. */ + this.loadAvailableWorkflows = () => { + const url = '/api/configuration_script_payloads/?expand=resources'; + return API.get(url); + }; + + /** Function to load a workflow with the provided 'id' */ + this.loadWorkflow = (id) => { + const url = `/api/configuration_script_payloads/${id}`; + return API.get(url) + .then((response) => ({ data: response, status: true })) + .catch((error) => ({ data: error, status: false })); + }; }]); diff --git a/app/views/miq_ae_customization/editor.html.haml b/app/views/miq_ae_customization/editor.html.haml index 70b8dccd528..be3d035396e 100644 --- a/app/views/miq_ae_customization/editor.html.haml +++ b/app/views/miq_ae_customization/editor.html.haml @@ -29,7 +29,10 @@ 'on-click' => "vm.dismissChanges()"} :javascript - ManageIQ.angular.app.value('dialogIdAction', '#{ dialog_id_action.to_json }'); + ManageIQ.angular.app.value('dialogIdAction', '#{dialog_id_action.to_json}'); + ManageIQ.angular.app.value('automationKeys', '#{editor_automation_types}'); + ManageIQ.angular.app.value('emsWorkflowsEnabled', '#{Settings.prototype.ems_workflows.enabled}'); + miq_bootstrap('#dialog-editor'); // Fixes wrong coordinates of draggable element after scrolling in #main-content. // To be selected as scrollParent it cannot have position: static(default setting of #main-content) so it's overridden here diff --git a/package.json b/package.json index 8f7b665949b..9dc428068e0 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "@data-driven-forms/carbon-component-mapper": "~3.18.8", "@data-driven-forms/react-form-renderer": "~3.18.8", "@manageiq/font-fabulous": "~1.0.5", - "@manageiq/ui-components": "1.4.4", + "@manageiq/ui-components": "1.5.0", "@novnc/novnc": "~1.2.0", "@pf3/select": "~1.12.6", "@tshepomgaga/aws-sfn-graph": "0.0.6", diff --git a/yarn.lock b/yarn.lock index 57422535b86..78e428efabc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1934,9 +1934,9 @@ __metadata: languageName: node linkType: hard -"@manageiq/ui-components@npm:1.4.4": - version: 1.4.4 - resolution: "@manageiq/ui-components@npm:1.4.4" +"@manageiq/ui-components@npm:1.5.0": + version: 1.5.0 + resolution: "@manageiq/ui-components@npm:1.5.0" dependencies: angular-bootstrap-switch: ^0.5.1 angular-dragdrop: ^1.0.13 @@ -1944,7 +1944,7 @@ __metadata: es6-shim: ^0.35.3 es7-shim: ^6.0.0 sprintf-js: ^1.1.1 - checksum: 4668f41f8c1f1107b2c21b2a3bbafa293a0e730130801120ccfb1ddf925224dfa3cc4d753a8bdf4af41c274d21b3c1f1d7e56ecfc9440bcc6e5e02174db58358 + checksum: b7037c6a442ac0b35f69624ad085b58148d1005a41a02d43278d6d7f72112d4a4a5a025f2d048477156e903ec2e0b66def1ced467cb08c1581da70da1e1dcdb2 languageName: node linkType: hard @@ -11382,7 +11382,7 @@ fsevents@^1.2.7: "@data-driven-forms/carbon-component-mapper": ~3.18.8 "@data-driven-forms/react-form-renderer": ~3.18.8 "@manageiq/font-fabulous": ~1.0.5 - "@manageiq/ui-components": 1.4.4 + "@manageiq/ui-components": 1.5.0 "@novnc/novnc": ~1.2.0 "@pf3/select": ~1.12.6 "@tshepomgaga/aws-sfn-graph": 0.0.6