Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introducing embedded_workflow to dynamic select box in service dialogs #471

Merged
merged 1 commit into from
Jul 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -114,14 +114,25 @@
<div ng-if="vm.modalTabIsSet('options') && vm.modalData.dynamic">
<form class="form-horizontal">
<div ng-show="!vm.treeOptions.show">
<div pf-form-group pf-label="{{'Entry Point'|translate}}">
<div class="input-group">
<input type="text" class="form-control" ng-value="vm.showFullyQualifiedName(vm.modalData.resource_action)" disabled>
<div pf-form-group pf-label="Automation Type" class="entry_point_selector_types">
<select ng-show="vm.treeOptions.emsWorkflowsEnabled" class="form-control automation_type_selector" miq-select ng-model="vm.modalData.automation_type" ng-change="vm.treeOptions.onAutomationTypeChange()">
<option value="{{vm.treeOptions.automationTypes.automate}}" translate>Embedded Automate</option>
<option value="{{vm.treeOptions.automationTypes.workflow}}" translate>Embedded Workflows</option>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably should only show this if the prototype flag is enabled. This can be found via API.

</select>
<div class="input-group entry_point" style="margin-top:0;" ng-if="vm.treeOptions.displayAutomationType().automate">
<input type="text" placeholder="Embedded Automate" class="form-control" ng-value="vm.showFullyQualifiedName(vm.modalData.resource_action)" disabled>
<span class="input-group-btn">
<button class="btn btn-default" ng-click="vm.treeOptions.toggle();"><i class="ff ff-load-balancer"></i></button>
</span>
</div>
</div>
<div ng-show="vm.treeOptions.emsWorkflowsEnabled" class="input-group" ng-if="vm.treeOptions.displayAutomationType().workflow">
<input type="text" placeholder="Embedded Workflow" class="form-control" ng-value="vm.modalData.resource_action.workflow_name" disabled>
<span class="input-group-btn">
<button class="btn btn-default" ng-click="vm.treeOptions.toggleWorkflows();"><i class="ff ff-load-balancer"></i></button>
</span>
<input type="hidden" class="form-control" ng-value="vm.modalData.resource_action.configuration_script_id" disabled>
</div>
</div>
<dialog-editor-modal-field-template template="dynamic-values.html"
modal-data="vm.modalData">
</dialog-editor-modal-field-template>
Expand Down
100 changes: 92 additions & 8 deletions src/dialog-editor/components/modal-field/modalFieldComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,50 @@ class ModalFieldController extends ModalController {
public validation: any;

public $onInit() {

const emsWorkflowsEnabled = this.treeOptions.emsWorkflowsEnabled === 'true' ? true : false;

/** Function to load the selected workflow if configuration_script_id is available. */
if (emsWorkflowsEnabled && this.modalData.resource_action && this.modalData.resource_action.configuration_script_id) {
this.loadWorkflow(this.modalData.resource_action.configuration_script_id);
};

this.treeOptions = {
...this.treeOptions,

show: false,
includeDomain: false,
data: null,
automationType: null,
automationTypes: {
automate: 'embedded_automate',
workflow: 'embedded_workflow',
},
emsWorkflowsEnabled: emsWorkflowsEnabled,

/** Function to reset the modalData while changin the Automation Type. */
onAutomationTypeChange: () => {
this.treeOptions.automationType = this.modalData.automation_type;
},

/** Function to display the automation_type select box
* 'Embedded Automate' will be displayed, by default.
* When the workflows are enabled, and automation_type === embedded_automate, 'Embedded Automate' select box will be displayed.
* Else, 'Embedded Workflow' will be selected.
*/
displayAutomationType: () => {
let displayAutomate = true;

if(emsWorkflowsEnabled) {
displayAutomate = this.modalData.automation_type === this.treeOptions.automationTypes.automate;
}
return {automate: displayAutomate, workflow: !displayAutomate};
},

/** Function to open the modal box and load the automate tree. */
toggle: () => {
this.treeOptions.show = ! this.treeOptions.show;
this.treeOptions.automationType = this.treeOptions.automationTypes.automate;

if (this.treeOptions.show) {
const fqname = this.showFullyQualifiedName(this.modalData.resource_action) || null;
Expand All @@ -41,38 +76,87 @@ class ModalFieldController extends ModalController {
}
},

/** Function to open the modal box and load the workflows list. */
toggleWorkflows: () => {
this.treeOptions.show = ! this.treeOptions.show;
this.treeOptions.automationType = this.treeOptions.automationTypes.workflow;

if (this.treeOptions.show) {
this.treeOptions.loadAvailableWorkflows().then((data) => {
this.treeOptions.data = data.resources.filter((item: any) => item.payload);
const workflow = this.treeOptions.data.find((item) => item.id === this.modalData.resource_action.configuration_script_id);
this.treeOptions.selected = workflow ? workflow.name : null;
});
}
},

/** Function to handle the onclick event of an item in tree. */
onSelect: (node) => {
this.treeSelectorSelect(node, this.modalData);
}
};
}

public showFullyQualifiedName(resourceAction) {
if (resourceAction.ae_namespace && resourceAction.ae_class && resourceAction.ae_instance) {
if (!resourceAction) {
return '';
}
const actionKeys = ['ae_namespace', 'ae_class', 'ae_instance'];
const keysPresent = actionKeys.every((item) => resourceAction.hasOwnProperty(item));

if (keysPresent && resourceAction.ae_namespace && resourceAction.ae_class && resourceAction.ae_instance) {
return `${resourceAction.ae_namespace}/${resourceAction.ae_class}/${resourceAction.ae_instance}`;
} else {
return '';
}
}

public treeSelectorSelect(node, elementData) {
/** Function to extract the values needed for embedded_automate during onclick event of an item from the tree */
public onEmbeddedAutomateSelect(node, elementData) {
const fqname = node.fqname.split('/');

if (this.treeOptions.includeDomain === false) {
fqname.splice(1, 1);
}
if (elementData.resource_action) {
elementData.resource_action = {
...elementData.resource_action,
ae_instance: fqname.pop(),
ae_class: fqname.pop(),
ae_namespace: fqname.filter(String).join('/'),
};
}
}

elementData.resource_action = {
...elementData.resource_action,
ae_instance: fqname.pop(),
ae_class: fqname.pop(),
ae_namespace: fqname.filter(String).join('/'),
};
/** Function to extract the values needed for embedded_workflow during onclick event of an item from the list */
public onEmbeddedWorkflowsSelect(workflow, elementData) {
if (elementData.resource_action) {
elementData.resource_action = {
...elementData.resource_action,
configuration_script_id: workflow.id,
workflow_name: workflow.name,
};
}
}

/** Function to extract the values needed for entry points during onclick event of an item from the tree or list */
public treeSelectorSelect(node, elementData) {
if (this.treeOptions.automationType === this.treeOptions.automationTypes.automate) {
this.onEmbeddedAutomateSelect(node, elementData);
} else if (this.treeOptions.automationType === this.treeOptions.automationTypes.workflow) {
this.onEmbeddedWorkflowsSelect(node, elementData);
}
this.treeOptions.show = false;
}

public modalFieldIsValid() {
return this.validation.validateField(this.modalData);
}

/** Function to load a selected workflow. */
public loadWorkflow(id: number) {
this.treeOptions.loadWorkflow(id).then(({data, status}) => {
this.modalData.resource_action.workflow_name = status ? data.name : '';
});
}
}
9 changes: 8 additions & 1 deletion src/dialog-editor/components/modal/modalComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,21 @@ class ModalController {
}
}

/** Function to set automationType in modalFieldData. */
private setAutomationType(modalFieldData: any) {
const automationType = modalFieldData.resource_action && modalFieldData.resource_action.configuration_script_id ? 'embedded_workflow' : 'embedded_automate';
modalFieldData.automation_type = automationType;
return modalFieldData;
}

public loadModalFieldData(tab: number, box: number, field: number) {
if (typeof tab !== 'undefined' &&
typeof box !== 'undefined' &&
typeof field !== 'undefined') {
let tabList = this.DialogEditor.getDialogTabs();
let boxList = tabList[tab];
let fieldList = boxList.dialog_groups[box];
return fieldList.dialog_fields[field];
return this.setAutomationType(fieldList.dialog_fields[field]);
}
}

Expand Down
77 changes: 51 additions & 26 deletions src/dialog-editor/components/tree-selector/tree-selector.html
Original file line number Diff line number Diff line change
@@ -1,28 +1,53 @@
<div class="pull-right">
<button type="button" class="close" ng-click="$ctrl.treeOptions.toggle()" aria-hidden="true">
<span class="pficon pficon-close"></span>
</button>
</div>

<div ng-if="!$ctrl.treeOptions.data" class="spinner spinner-lg"></div>
<div ng-if="$ctrl.treeOptions.data">
<miq-tree-selector
name="tree-selector"
data="$ctrl.treeOptions.data"
selectable="{key: '^aei-'}"
on-select="$ctrl.treeOptions.onSelect(node)"
lazy-load="$ctrl.treeOptions.lazyLoad(node)"
selected="$ctrl.treeOptions.selected"
></miq-tree-selector>
</div>

<div class="col-sm-4">
<div class="form-group pull-right">
<label class="control-label" translate>Include domain prefix in the path:</label>
<input bs-switch
type="checkbox"
ng-model="$ctrl.treeOptions.includeDomain"
switch-on-text="{{'Yes'|translate}}"
switch-off-text="{{'No'|translate}}"/>
<div class="tree_selector_wrapper">
<div class="tree_selector_title_wrapper">
<div class="tree_selector_dialog_title">
<span ng-if="$ctrl.treeOptions.automationType==$ctrl.treeOptions.automationTypes.automate">
Select Embededded Automate
</span>
<span ng-if="$ctrl.treeOptions.automationType==$ctrl.treeOptions.automationTypes.workflow">
Select Embededded Workflow
</span>
</div>
<div class="tree_selector_action">
<div class="pull-right">
<button type="button" class="close" ng-click="$ctrl.treeOptions.toggle()" aria-hidden="true">
<span class="pficon pficon-close"></span>
</button>
</div>
</div>
</div>
<div class="tree_selector_content_wrapper">
<div ng-if="!$ctrl.treeOptions.data" class="spinner spinner-lg"></div>
<div ng-if="$ctrl.treeOptions.automationType==$ctrl.treeOptions.automationTypes.automate">
<div ng-if="$ctrl.treeOptions.data">
<miq-tree-selector
name="tree-selector"
data="$ctrl.treeOptions.data"
selectable="{key: '^aei-'}"
on-select="$ctrl.treeOptions.onSelect(node)"
lazy-load="$ctrl.treeOptions.lazyLoad(node)"
selected="$ctrl.treeOptions.selected"
></miq-tree-selector>
</div>
<div class="col-sm-4">
<div class="form-group pull-right">
<label class="control-label" translate>Include domain prefix in the path:</label>
<input bs-switch
type="checkbox"
ng-model="$ctrl.treeOptions.includeDomain"
switch-on-text="{{'Yes'|translate}}"
switch-off-text="{{'No'|translate}}"/>
</div>
</div>
</div>
<div ng-if="$ctrl.treeOptions.automationType==$ctrl.treeOptions.automationTypes.workflow">
<div ng-if="$ctrl.treeOptions.data">
<ul class="nav nav-list workflows_list_wrapper" ng-repeat="workflow in $ctrl.treeOptions.data">
<li class="workflow_item" ng-click="$ctrl.treeOptions.onSelect(workflow)">
{{workflow.name}}
</li>
</ul>
</div>
</div>
</div>
</div>
2 changes: 1 addition & 1 deletion src/dialog-editor/services/dialogValidationService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export default class DialogValidationService {
field => ({ status: (field.type !== 'DialogFieldTagControl') || tagHasCategory(field),
errorMessage: __('Category needs to be set for TagControl field'),
local: true }),
field => ({ status: ! (field.dynamic && _.isEmpty(field.resource_action.ae_class)),
field => ({ status: ! (field.dynamic && !field.resource_action.configuration_script_id && _.isEmpty(field.resource_action.ae_class)),
errorMessage: __('Entry Point needs to be set for Dynamic elements'),
local: true }),
field => ({ status: ! ((field.type === 'DialogFieldDropDownList' ||
Expand Down
4 changes: 2 additions & 2 deletions src/dialog-user/services/dialogData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,14 @@ export default class DialogDataService {
options,
values,
}) {
let dropDownValues = values.map((option) => {
let dropDownValues = values && values.map((option) => {
const value = this.convertDropdownValue(option[0], data_type);
const description = (!Number.isInteger(option[1]) ? option[1] : parseInt(option[1], 10));

return [value, description];
});

if (options.sort_by !== 'none') {
if (values && options.sort_by !== 'none') {
return this.updateFieldSortOrder({
options,
values: dropDownValues,
Expand Down
70 changes: 70 additions & 0 deletions src/styles/dialog-editor-boxes.scss
Original file line number Diff line number Diff line change
Expand Up @@ -137,3 +137,73 @@
.draggable-field-dropdown {
z-index: initial;
}

.entry_point_selector_types {

.automation_type_selector {
margin-bottom: 20px !important;
}
.entry_point {
margin-top: 20px;
}
}


l.nav.nav-list.workflows {
background-color: #f5f5f5;
border: 1px solid #e3e3e3;

li {
border-bottom: 1px solid lightgray;
padding: 10px;
}
}

.tree_selector_wrapper {
display: flex;
flex-direction: column;
border: 1px solid lightgray;
margin-top: 10px;

.tree_selector_title_wrapper {
display: flex;
flex-direction: row;
background: lightgray;
padding: 5px;

.tree_selector_dialog_title {
display: flex;
flex-grow: 1;
font-weight: bold;
padding: 5px 0;
font-size: 14px;
}
.tree_selector_action {
display: flex;
justify-content: center;
align-items: center;
min-width: 30px;
}
}
.tree_selector_content_wrapper {
display: flex;
flex-direction: column;
padding: 10px;

ul.workflows_list_wrapper {
display: flex;

li.workflow_item {
display: flex;
flex-grow: 1;
padding: 5px;

&:hover {
background: #e4e5e6;
cursor: pointer;
}

}
}
}
}
2 changes: 1 addition & 1 deletion src/styles/ui-components.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
/* Begin Patternfly Tab overrides used in the Dialog Editor */

.dialog-editor-tab-list {
margin-bottom: 20px;
margin-bottom: 20px !important;
}

.delete-tab {
Expand Down