Skip to content

Commit abab01f

Browse files
Merge pull request #9202 from liu-samuel/automate-simulation-conversion
Automate Simulation Conversion Form from HAML to React
2 parents 680155b + d560e28 commit abab01f

File tree

19 files changed

+1367
-173
lines changed

19 files changed

+1367
-173
lines changed

app/controllers/application_controller/automate.rb

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
module ApplicationController::Automate
22
extend ActiveSupport::Concern
3+
include MiqAeToolsHelper
34

45
def resolve_button_throw
56
if valid_resolve_object?
@@ -21,15 +22,7 @@ def resolve_button_throw
2122
add_flash(_("Automation Error: %{error_message}") % {:error_message => bang.message}, :error)
2223
end
2324
end
24-
render :update do |page|
25-
page << javascript_prologue
26-
page.replace("left_cell_bottom", :partial => "resolve_form_buttons")
27-
page.replace("flash_msg_div", :partial => "layouts/flash_msg")
28-
page << "miqScrollTop();" if @flash_array.present?
29-
page.replace_html("main_div", :partial => "results_tabs")
30-
page << javascript_reload_toolbars
31-
page << "miqSparkle(false);"
32-
end
25+
automation_simulation_data(@ae_simulation_tree, @results, @resolve)
3326
end
3427
private :resolve_button_throw
3528

@@ -85,6 +78,24 @@ def resolve_button_reset_or_none
8578
end
8679
private :resolve_button_reset_or_none
8780

81+
def resolve_automate_simulation
82+
custom_button_redirect = params[:button] == 'simulate' || params[:simulate] == 'simulate'
83+
assert_privileges(custom_button_redirect ? 'ab_button_simulate' : 'miq_ae_class_simulation')
84+
@explorer = true
85+
@breadcrumbs = []
86+
drop_breadcrumb(:name => _("Resolve"), :url => "/miq_ae_tools/resolve")
87+
@lastaction = "resolve"
88+
@right_cell_text = _("Simulation")
89+
get_simulation_form_vars
90+
case params[:button]
91+
when "throw", "retry" then resolve_button_throw
92+
when "copy" then resolve_button_copy
93+
when "paste" then resolve_button_paste
94+
when "simulate" then resolve_button_simulate
95+
else resolve_button_reset_or_none
96+
end
97+
end
98+
8899
def resolve
89100
custom_button_redirect = params[:button] == 'simulate' || params[:simulate] == 'simulate'
90101
assert_privileges(custom_button_redirect ? 'ab_button_simulate' : 'miq_ae_class_simulation')

app/controllers/miq_ae_tools_controller.rb

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,51 @@ def reset_datastore
329329
javascript_flash(:spinner_off => true)
330330
end
331331

332+
def get_simulation_form_vars
333+
assert_privileges('miq_ae_class_simulation')
334+
if params[:object_request]
335+
@resolve[:new][:object_request] = params[:object_request]
336+
end
337+
if params.key?(:starting_object)
338+
@resolve[:new][:starting_object] = params[:starting_object]
339+
@resolve[:new][:instance_name] = nil
340+
end
341+
if params[:readonly]
342+
@resolve[:new][:readonly] = (params[:readonly] != "1")
343+
end
344+
345+
copy_params_if_present(@resolve[:new], params, %i[instance_name other_name object_message object_request target_class target_id])
346+
347+
ApplicationController::AE_MAX_RESOLUTION_FIELDS.times do |i|
348+
ApplicationController::AE_MAX_RESOLUTION_FIELDS.times do |i|
349+
f = ("attribute_" + (i + 1).to_s)
350+
v = ("value_" + (i + 1).to_s)
351+
@resolve[:new][:attrs][i][0] = params[f.to_sym] || nil
352+
@resolve[:new][:attrs][i][1] = params[v.to_sym] || nil
353+
end
354+
end
355+
@resolve[:new][:target_id] = nil if params[:target_class] == ""
356+
copy_params_if_present(@resolve, params, %i[button_text button_number])
357+
@resolve[:throw_ready] = ready_to_throw
358+
end
359+
360+
def get_form_targets
361+
assert_privileges('miq_ae_class_simulation')
362+
if params.key?(:target_class) && params[:target_class] != '-1'
363+
targets = Rbac.filtered(params[:target_class]).select(:id, *columns_for_klass(params[:target_class])) if params[:target_class].present?
364+
unless targets.nil?
365+
@resolve[:targets] = targets.sort_by { |t| t.name.downcase }.collect { |t| [t.name, t.id.to_s] }
366+
if !@resolve[:target_id]
367+
@resolve[:target_id] = nil
368+
end
369+
end
370+
end
371+
372+
render_json = {}
373+
render_json[:targets] = @resolve[:targets] if @resolve[:targets].present?
374+
render :json => render_json
375+
end
376+
332377
private ###########################
333378

334379
def automate_import_json_serializer

app/helpers/miq_ae_tools_helper.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ def git_import_submit_help
1818

1919
def automation_simulation_data(tree, results, resolve)
2020
if results
21-
{
21+
render :json => {
2222
:tree => {:text => _('Tree View'), :rows => ae_result_tree(tree)},
2323
:xml => {:text => _('Xml View'), :rows => ae_result_xml(results)},
2424
:object => {:text => _('Object info'), :rows => ae_result_uri(resolve)}

app/javascript/components/AutomationSimulation/index.jsx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@ import MiqStructuredList from '../miq-structured-list';
77
/** Component to render the summary contents displayed in the Automation / Embedded Automate / Simulation */
88
const AutomationSimulation = ({ data }) => {
99
const [tabConfig, setTabConfig] = useState([]);
10-
1110
useEffect(() => {
12-
const config = Object.keys(data).map((name) => ({ name, text: data[name].text }));
13-
setTabConfig(config);
14-
}, []);
11+
if (Object.keys(data).length > 1) {
12+
const config = Object.keys(data).map((name) => ({ name, text: data[name].text }));
13+
setTabConfig(config);
14+
}
15+
}, [data]);
1516

1617
/** Function to render the tabs contents. */
1718
const renderTabContent = (name) => {
@@ -37,7 +38,7 @@ const AutomationSimulation = ({ data }) => {
3738
</Tabs>
3839
);
3940

40-
return data.notice
41+
return Object.keys(data).length <= 1
4142
? <NotificationMessage type="info" message={data.notice} />
4243
: renderTabs();
4344
};
Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
import { componentTypes, validatorTypes } from '@@ddf';
2+
3+
const targetsURL = (targetClass) => `/miq_ae_tools/get_form_targets?target_class=${encodeURIComponent(targetClass)}`;
4+
const loadTargets = (selectedTargetClass) => http.get(targetsURL(selectedTargetClass))
5+
.then((formVars) => {
6+
if (formVars && formVars.targets) {
7+
return [
8+
{ label: `<${__('None')}>`, value: '-1' },
9+
...formVars.targets.map(([key, value]) => ({
10+
label: String(key),
11+
value: String(value),
12+
})),
13+
];
14+
}
15+
return [];
16+
});
17+
18+
const createSchema = (
19+
resolve, maxNameLength, url, attrValuesPairs, maxLength, typeClassesOptions, formData, setFormData,
20+
) => {
21+
const fields = [
22+
{
23+
component: componentTypes.PLAIN_TEXT,
24+
id: 'object_details',
25+
name: 'object_details',
26+
className: 'automate-object-details',
27+
label: __('Object Details'),
28+
style: { fontSize: '16px' },
29+
},
30+
31+
{
32+
component: componentTypes.SELECT,
33+
id: 'instance_name',
34+
name: 'instance_name',
35+
className: 'automate-instance-name',
36+
label: __('System/Process'),
37+
initialValue: resolve.instance_names.sort((b, a) => a.toLowerCase().localeCompare(b.toLowerCase())),
38+
validate: [{ type: validatorTypes.REQUIRED }],
39+
isSearchable: true,
40+
simpleValue: true,
41+
options: resolve.instance_names.map((name) => ({ label: name, value: name })),
42+
url,
43+
},
44+
{
45+
component: componentTypes.TEXT_FIELD,
46+
id: 'object_message',
47+
name: 'object_message',
48+
className: 'automate-object-message',
49+
label: __('Message'),
50+
maxLength: maxNameLength,
51+
initialValue: resolve.new.object_message,
52+
isRequired: true,
53+
},
54+
55+
{
56+
component: componentTypes.TEXT_FIELD,
57+
id: 'object_request',
58+
name: 'object_request',
59+
className: 'automate-object-request',
60+
label: __('Request'),
61+
initialValue: resolve.new.object_request,
62+
},
63+
64+
{
65+
component: componentTypes.PLAIN_TEXT,
66+
id: 'object_attribute',
67+
name: 'object_attribute',
68+
className: 'automate-object-attribute',
69+
label: __('Object Attribute'),
70+
style: { fontSize: '16px' },
71+
},
72+
73+
{
74+
component: componentTypes.SELECT,
75+
id: 'target_class',
76+
name: 'target_class',
77+
label: __('Type'),
78+
options: typeClassesOptions,
79+
initialValue: resolve.new.target_class,
80+
className: 'automate-target-class',
81+
isSearchable: true,
82+
simpleValue: true,
83+
onChange: (targetClass) => {
84+
if (formData.targetClass !== targetClass) {
85+
setFormData((prevData) => ({ ...prevData, targetClass }));
86+
}
87+
},
88+
validate: [
89+
{
90+
type: validatorTypes.REQUIRED,
91+
condition: {
92+
not: {
93+
or: [
94+
{
95+
when: 'target_class',
96+
is: '-1',
97+
},
98+
{
99+
when: 'target_class',
100+
isEmpty: true,
101+
},
102+
],
103+
},
104+
},
105+
},
106+
],
107+
},
108+
109+
{
110+
component: componentTypes.SELECT,
111+
id: 'selection_target',
112+
name: 'selection_target',
113+
label: __('Selection'),
114+
key: `selection_target_${formData.targetClass}`,
115+
className: 'automate-selection-target',
116+
initialValue: resolve.new.target_id,
117+
loadOptions: () => (loadTargets(formData.targetClass)),
118+
condition: {
119+
not: {
120+
or: [
121+
{
122+
when: 'target_class',
123+
is: '-1',
124+
},
125+
{
126+
when: 'target_class',
127+
isEmpty: true,
128+
},
129+
],
130+
},
131+
},
132+
validate: [
133+
{
134+
type: validatorTypes.REQUIRED,
135+
condition: {
136+
not: {
137+
or: [
138+
{
139+
when: 'target_class',
140+
is: '-1',
141+
},
142+
{
143+
when: 'target_class',
144+
isEmpty: true,
145+
},
146+
],
147+
},
148+
},
149+
},
150+
],
151+
},
152+
{
153+
id: 'simulationParameters',
154+
component: componentTypes.PLAIN_TEXT,
155+
name: 'simulationParameters',
156+
className: 'automate-simulation-parameters',
157+
label: __('Simulation Parameters'),
158+
style: { fontSize: '16px' },
159+
},
160+
{
161+
component: componentTypes.CHECKBOX,
162+
id: 'readonly',
163+
name: 'readonly',
164+
className: 'automate-readonly',
165+
label: __('Execute Methods'),
166+
initialValue: resolve.new.readonly,
167+
title: 'Simulation parameters',
168+
},
169+
{
170+
id: 'AttributeValuePairs',
171+
component: componentTypes.PLAIN_TEXT,
172+
name: 'AttributeValuePairs',
173+
label: __('Attribute/Value Pairs'),
174+
style: { fontSize: '16px' },
175+
},
176+
];
177+
178+
if (!document.getElementById('description') && document.getElementById('object_message')) {
179+
document.getElementById('object_message').focus();
180+
}
181+
182+
attrValuesPairs.forEach((_, i) => {
183+
const f = `attribute_${i + 1}`;
184+
const v = `value_${i + 1}`;
185+
const labelKey = `attributeValuePairLabel_${i + 1}`;
186+
187+
const subForm = [
188+
{
189+
component: componentTypes.SUB_FORM,
190+
id: `subform_${i + 1}`,
191+
name: `subform_${i + 1}`,
192+
className: 'subform',
193+
fields: [
194+
{
195+
component: componentTypes.PLAIN_TEXT,
196+
id: labelKey,
197+
name: labelKey,
198+
className: 'attributeValuePairLabel',
199+
label: `${i + 1}`,
200+
style: { fontWeight: 'bold' },
201+
},
202+
{
203+
component: componentTypes.TEXT_FIELD,
204+
id: f,
205+
name: f,
206+
maxLength,
207+
label: ' ',
208+
initialValue: resolve.new.attrs[i][0],
209+
fieldprops: {
210+
className: 'field-input',
211+
'data-miq_observe': JSON.stringify({ interval: '.5', url }),
212+
},
213+
},
214+
{
215+
component: componentTypes.TEXT_FIELD,
216+
id: v,
217+
name: v,
218+
maxLength,
219+
label: ' ',
220+
initialValue: resolve.new.attrs[i][1],
221+
fieldprops: {
222+
className: 'value-input',
223+
'data-miq_observe': JSON.stringify({ interval: '.5', url }),
224+
},
225+
},
226+
],
227+
},
228+
];
229+
fields.push(subForm);
230+
});
231+
232+
return {
233+
title: 'Object Details',
234+
fields,
235+
};
236+
};
237+
238+
export default createSchema;

0 commit comments

Comments
 (0)