Skip to content

Commit f0f829e

Browse files
committed
Added service dialog from orchestration template react component.
1 parent ed36c85 commit f0f829e

File tree

9 files changed

+137
-111
lines changed

9 files changed

+137
-111
lines changed

app/controllers/catalog_controller.rb

Lines changed: 3 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -620,10 +620,6 @@ def ot_copy
620620
replace_right_cell(:action => "ot_copy")
621621
end
622622

623-
def ot_form_field_changed
624-
dialog_creation_form_field_changed("ot_edit__#{params[:id]}")
625-
end
626-
627623
def ot_remove_submit
628624
assert_privileges("orchestration_template_remove")
629625
elements = find_records_with_rbac(OrchestrationTemplate, checked_or_params)
@@ -651,49 +647,23 @@ def ot_add
651647
assert_privileges("orchestration_template_add")
652648
ot_type = x_node == "root" ? "ManageIQ::Providers::Amazon::CloudManager::OrchestrationTemplate" : node_name_to_template_name(x_node)
653649
@edit = {:new => {:type => ot_type}}
654-
@edit[:new][:available_managers] = available_orchestration_managers_for_template_type(ot_type)
655650
@edit[:current] = @edit[:new].dup
656651
@edit[:key] = "ot_add__new"
657652
@right_cell_text = _("Adding a new Orchestration Template")
658653
@in_a_form = true
659654
replace_right_cell(:action => "ot_add")
660655
end
661656

662-
def ot_add_form_field_changed
663-
return unless load_edit("ot_add__new", "replace_cell__explorer")
664-
copy_params_if_set(@edit[:new], params, %i[name description type content manager_id])
665-
@edit[:new][:draft] = params[:draft] == "true" if params[:draft]
666-
@edit[:new][:available_managers] = available_orchestration_managers_for_template_type(params[:type])
667-
668-
render :update do |page|
669-
page << javascript_prologue
670-
page << javascript_hide("buttons_off")
671-
page << javascript_show("buttons_on")
672-
page << "miqSparkle(false);"
673-
page.replace("form_div", :partial => "ot_add") if params[:type]
674-
end
675-
end
676-
677657
def service_dialog_from_ot
678658
assert_privileges("service_dialog_from_ot")
679659
ot = OrchestrationTemplate.find(params[:id])
680660
@right_cell_text = _("Adding a new Service Dialog from Orchestration Template \"%{name}\"") % {:name => ot.name}
681-
@edit = {:new => {:dialog_name => ""},
682-
:key => "ot_edit__#{ot.id}",
683-
:rec_id => ot.id}
661+
# id for create service dialog from ot for react form
662+
@edit = {:rec_id => ot.id}
684663
@in_a_form = true
685664
replace_right_cell(:action => "service_dialog_from_ot")
686665
end
687666

688-
def service_dialog_from_ot_submit
689-
case params[:button]
690-
when "cancel"
691-
service_dialog_from_ot_submit_cancel
692-
when "save"
693-
service_dialog_from_ot_submit_save
694-
end
695-
end
696-
697667
def ot_show
698668
assert_privileges("orchestration_templates_view")
699669
id = params.delete(:id)
@@ -952,32 +922,6 @@ def ot_edit_set_form_vars(right_cell_text)
952922
@in_a_form = true
953923
end
954924

955-
def service_dialog_from_ot_submit_cancel
956-
add_flash(_("Creation of a new Service Dialog was cancelled by the user"))
957-
@in_a_form = false
958-
@sb[:action] = @edit = @record = nil
959-
replace_right_cell
960-
end
961-
962-
def service_dialog_from_ot_submit_save
963-
assert_privileges("service_dialog_from_ot")
964-
load_edit("ot_edit__#{params[:id]}", "replace_cell__explorer")
965-
begin
966-
ot = OrchestrationTemplate.find(params[:id])
967-
Dialog::OrchestrationTemplateServiceDialog.new.create_dialog(@edit[:new][:dialog_name], ot)
968-
rescue => bang
969-
add_flash(_("Error when creating a Service Dialog from Orchestration Template: %{error_message}") %
970-
{:error_message => bang.message}, :error)
971-
javascript_flash
972-
else
973-
add_flash(_("Service Dialog \"%{name}\" was successfully created") %
974-
{:name => @edit[:new][:dialog_name]}, :success)
975-
@in_a_form = false
976-
@edit = @record = nil
977-
replace_right_cell
978-
end
979-
end
980-
981925
def st_catalog_set_form_vars
982926
checked = find_checked_items
983927
checked[0] = params[:id] if checked.blank? && params[:id]
@@ -1916,13 +1860,6 @@ def replace_right_cell(options = {})
19161860
]
19171861
)
19181862
end
1919-
elsif %w[service_dialog_from_ot].include?(action)
1920-
presenter.hide(:toolbar).show(:paging_div, :form_buttons_div).remove_paging
1921-
locals = {:record_id => @edit[:rec_id],
1922-
:action_url => "#{action}_submit",
1923-
:serialize => true,
1924-
:no_reset => true}
1925-
presenter.update(:form_buttons_div, r[:partial => "layouts/x_edit_buttons", :locals => locals])
19261863
else
19271864
# Added so buttons can be turned off even tho div is not being displayed it still pops up Abandon changes box when trying to change a node on tree after saving a record
19281865
presenter.hide(:buttons_on, :form_buttons_div).show(:toolbar).hide(:paging_div)
@@ -1932,7 +1869,7 @@ def replace_right_cell(options = {})
19321869
end
19331870

19341871
# hide form buttons and toolbar for react forms actions
1935-
if %w[ot_add ot_edit ot_copy].include?(action)
1872+
if %w[ot_add ot_edit ot_copy service_dialog_from_ot].include?(action)
19361873
presenter.hide(:toolbar, :paging_div, :form_buttons_div)
19371874
else
19381875
presenter.set_visibility(h_tb.present? || c_tb.present? || v_tb.present?, :toolbar)
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
3+
import { Grid } from 'patternfly-react';
4+
5+
import MiqFormRenderer from '../../forms/data-driven-form';
6+
import miqRedirectBack from '../../helpers/miq-redirect-back';
7+
import { API } from '../../http_api';
8+
import serviceDialogFromOtSchema from './service-dialog-from-ot.schema';
9+
10+
const ServiceDialogFromOt = ({ otId }) => {
11+
const onSubmit = values => API.post('/api/service_dialogs', {
12+
action: 'orchestration_template_service_dialog',
13+
resource: {
14+
...values,
15+
ot_id: otId,
16+
},
17+
}).then(() => miqRedirectBack(
18+
sprintf(__('Service Dialog "%s" was successfully created'), values.label),
19+
'success', '/catalog/explorer',
20+
));
21+
22+
return (
23+
<Grid fluid>
24+
<MiqFormRenderer
25+
schema={serviceDialogFromOtSchema}
26+
onSubmit={onSubmit}
27+
onCancel={() => miqRedirectBack('Creation of a new Service Dialog was cancelled by the user', 'success', '/catalog/explorer')}
28+
buttonsLabels={{ submitLabel: __('Save') }}
29+
/>
30+
</Grid>
31+
);
32+
};
33+
34+
ServiceDialogFromOt.propTypes = {
35+
otId: PropTypes.number.isRequired,
36+
};
37+
38+
export default ServiceDialogFromOt;
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { componentTypes } from '@data-driven-forms/react-form-renderer';
2+
import { API } from '../../http_api';
3+
import debouncePromise from '../../helpers/promise-debounce';
4+
5+
const asyncValidator = label => API.get(`/api/service_dialogs?filter[]=label=${label}`)
6+
.then(({ subcount }) => {
7+
if (!label) {
8+
return __('Required');
9+
}
10+
if (subcount !== 0) {
11+
return __('Name has already been taken');
12+
}
13+
return undefined;
14+
});
15+
16+
const asyncValidatorDebounced = debouncePromise(asyncValidator);
17+
18+
const serviceDialogFromOtSchema = ({
19+
fields: [{
20+
component: componentTypes.TEXT_FIELD,
21+
name: 'label',
22+
label: __('Service Dialog Name'),
23+
isRequired: true,
24+
validateOnMount: true,
25+
validate: [asyncValidatorDebounced],
26+
}],
27+
});
28+
29+
export default serviceDialogFromOtSchema;

app/javascript/packs/component-definitions-common.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import ImportDatastoreViaGit from '../components/automate-import-export-form/imp
1616
import MiqAboutModal from '../components/miq-about-modal';
1717
import OrcherstrationTemplateForm from '../components/orchestration-template/orcherstration-template-form';
1818
import RemoveCatalogItemModal from '../components/remove-catalog-item-modal';
19+
import ServiceDialogFromOtForm from '../components/orchestration-template/service-dialog-from-ot';
1920
import ServiceForm from '../components/service-form';
2021
import SetServiceOwnershipForm from '../components/set-service-ownership-form';
2122
import TableListViewWrapper from '../react/table_list_view_wrapper';
@@ -44,6 +45,7 @@ ManageIQ.component.addReact('ImportDatastoreViaGit', ImportDatastoreViaGit);
4445
ManageIQ.component.addReact('MiqAboutModal', MiqAboutModal);
4546
ManageIQ.component.addReact('OrcherstrationTemplateForm', OrcherstrationTemplateForm);
4647
ManageIQ.component.addReact('RemoveCatalogItemModal', RemoveCatalogItemModal);
48+
ManageIQ.component.addReact('ServiceDialogFromOtForm', ServiceDialogFromOtForm);
4749
ManageIQ.component.addReact('ServiceForm', ServiceForm);
4850
ManageIQ.component.addReact('SetServiceOwnershipForm', SetServiceOwnershipForm);
4951
ManageIQ.component.addReact('TableListView', TableListView);
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import React from 'react';
2+
import { mount } from 'enzyme';
3+
import fetchMock from 'fetch-mock';
4+
5+
import '../helpers/addFlash';
6+
import '../helpers/miqFlashLater';
7+
import '../helpers/miqSparkle';
8+
import '../helpers/sprintf';
9+
10+
import ServiceDialogFromOt from '../../components/orchestration-template/service-dialog-from-ot';
11+
12+
describe('<ServiceDialogFromOt />', () => {
13+
let initialProps;
14+
15+
beforeEach(() => {
16+
initialProps = {
17+
otId: 123,
18+
};
19+
});
20+
21+
afterEach(() => {
22+
fetchMock.reset();
23+
});
24+
25+
it('should submit data correctly', (done) => {
26+
fetchMock.postOnce('/api/service_dialogs', {});
27+
fetchMock.getOnce('/api/service_dialogs?filter[]=label=undefined', { subcount: 0 });
28+
fetchMock.getOnce('/api/service_dialogs?filter[]=label=Foo', { subcount: 0 });
29+
30+
const wrapper = mount(<ServiceDialogFromOt {...initialProps} />);
31+
// need to use timeout because of debounced request
32+
setTimeout(() => {
33+
// should check if label is unique
34+
expect(fetchMock.calls()).toHaveLength(1);
35+
// form is invalid so should not call submit;
36+
wrapper.find('button').first().simulate('click');
37+
wrapper.find('input').simulate('change', { target: { value: 'Foo' } });
38+
setTimeout(() => {
39+
wrapper.find('button').first().simulate('click');
40+
expect(JSON.parse(fetchMock.lastCall()[1].body)).toEqual({
41+
action: 'orchestration_template_service_dialog',
42+
resource: { label: 'Foo', ot_id: 123 },
43+
});
44+
done();
45+
}, 500);
46+
}, 500);
47+
});
48+
49+
it('should fail async label validation', (done) => {
50+
fetchMock.getOnce('/api/service_dialogs?filter[]=label=undefined', { subcount: 1 });
51+
fetchMock.getOnce('/api/service_dialogs?filter[]=label=Bla', { subcount: 1 });
52+
53+
const wrapper = mount(<ServiceDialogFromOt {...initialProps} />);
54+
55+
setTimeout(() => {
56+
wrapper.find('input').simulate('change', { target: { value: 'Bla' } });
57+
setTimeout(() => {
58+
wrapper.update();
59+
expect(wrapper.find('button').first().props().disabled).toEqual(true);
60+
done();
61+
}, 500);
62+
}, 500);
63+
});
64+
});
Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,4 @@
11
#form_div
22
#basic_info_div
33
= render :partial => "layouts/flash_msg"
4-
- url = url_for_only_path(:action => "ot_form_field_changed", :id => @edit[:rec_id])
5-
.form-horizontal
6-
.form-group
7-
%label.col-md-2.control-label
8-
= _('Service Dialog Name')
9-
.col-md-8
10-
= text_field_tag("dialog_name",
11-
"",
12-
:autocomplete => 'off',
13-
:diabled => false,
14-
:class => "form-control",
15-
:maxlength => 255,
16-
"data-miq_observe" => {:interval => '.5',
17-
:url => url}.to_json)
4+
= react('ServiceDialogFromOtForm', { :otId => @edit[:rec_id] })

config/routes.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,6 @@
311311
orchestration_template_copy
312312
orchestration_template_edit
313313
ot_add_form_field_changed
314-
ot_form_field_changed
315314
ot_tags_edit
316315
ownership_form_fields
317316
ownership_update

spec/controllers/catalog_controller_spec.rb

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -419,34 +419,6 @@
419419
end
420420
end
421421

422-
describe "#service_dialog_create_from_ot" do
423-
before do
424-
@ot = FactoryBot.create(:orchestration_template_amazon_in_json)
425-
@dialog_label = "New Dialog 01"
426-
session[:edit] = {
427-
:new => {:dialog_name => @dialog_label},
428-
:key => "ot_edit__#{@ot.id}",
429-
:rec_id => @ot.id
430-
}
431-
controller.instance_variable_set(:@sb, :trees => {:ot_tree => {:open_nodes => []}}, :active_tree => :ot_tree)
432-
controller.instance_variable_set(:@_response, ActionDispatch::TestResponse.new)
433-
end
434-
435-
after(:each) do
436-
expect(controller.send(:flash_errors?)).not_to be_truthy
437-
expect(assigns(:edit)).to be_nil
438-
expect(response.status).to eq(200)
439-
end
440-
441-
it "Service Dialog is created from an Orchestration Template" do
442-
controller.params = {:button => "save", :id => @ot.id}
443-
allow(controller).to receive(:replace_right_cell)
444-
controller.send(:service_dialog_from_ot_submit)
445-
expect(assigns(:flash_array).first[:message]).to include("was successfully created")
446-
expect(Dialog.where(:label => @dialog_label).first).not_to be_nil
447-
end
448-
end
449-
450422
describe "#ot_rendering" do
451423
render_views
452424
before do

spec/routing/catalog_routing_spec.rb

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,11 @@
4040
orchestration_template_add
4141
orchestration_template_copy
4242
orchestration_template_edit
43-
ot_form_field_changed
4443
ot_tags_edit
4544
prov_field_changed
4645
reload
4746
resolve
4847
resource_delete
49-
service_dialog_from_ot_submit
5048
servicetemplate_edit
5149
sort_ds_grid
5250
sort_host_grid

0 commit comments

Comments
 (0)