Skip to content

Commit b59717b

Browse files
authored
Merge pull request #8916 from GilbertCherrie/convert_user_form
Convert user form to React
2 parents 2302577 + 311a08c commit b59717b

56 files changed

Lines changed: 1673 additions & 559 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

app/controllers/ops_controller.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -583,7 +583,9 @@ def replace_right_cell(options = {})
583583

584584
replace_explorer_trees(replace_trees, presenter)
585585
rebuild_toolbars(presenter)
586-
handle_bottom_cell(nodetype, presenter, locals)
586+
unless @hide_bottom_bar
587+
handle_bottom_cell(nodetype, presenter, locals)
588+
end
587589
x_active_tree_replace_cell(nodetype, presenter)
588590
extra_js_commands(presenter)
589591

app/controllers/ops_controller/ops_rbac.rb

Lines changed: 9 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,15 @@ def rbac_tags_edit
5151

5252
def rbac_user_add
5353
assert_privileges("rbac_user_add")
54+
@hide_bottom_bar = true
5455
rbac_edit_reset('new', 'user', User)
5556
end
5657

5758
def rbac_user_copy
5859
# get users id either from gtl check or detail id
5960
user_id = params[:miq_grid_checks].presence || params[:id]
60-
user = User.find(user_id)
61+
user = User.find(user_id)
62+
6163
# check if it is allowed to copy the user
6264
if rbac_user_copy_restriction?(user)
6365
rbac_restricted_user_copy_flash(user)
@@ -66,17 +68,17 @@ def rbac_user_copy
6668
javascript_flash
6769
return
6870
end
71+
72+
@copy_user_id = user_id
6973
assert_privileges("rbac_user_copy")
74+
@hide_bottom_bar = true
7075
rbac_edit_reset('copy', 'user', User)
7176
end
7277

7378
def rbac_user_edit
7479
assert_privileges("rbac_user_edit")
75-
case params[:button]
76-
when 'cancel' then rbac_edit_cancel('user')
77-
when 'save', 'add' then rbac_edit_save_or_add('user')
78-
when 'reset', nil then rbac_edit_reset(params[:typ], 'user', User) # Reset or first time in
79-
end
80+
@hide_bottom_bar = true
81+
rbac_edit_reset(params[:typ], 'user', User)
8082
end
8183

8284
def rbac_group_add
@@ -185,13 +187,6 @@ def rbac_tenant_tags_edit
185187
end
186188
end
187189

188-
# AJAX driven routines to check for changes in ANY field on the form
189-
def rbac_user_field_changed
190-
assert_privileges(params[:id] == "new" ? "rbac_user_add" : "rbac_user_edit")
191-
192-
rbac_field_changed("user")
193-
end
194-
195190
def rbac_group_field_changed
196191
assert_privileges(params[:id] == "new" ? "rbac_group_add" : "rbac_group_edit")
197192

@@ -647,10 +642,6 @@ def rbac_edit_save_or_add(what, rbac_suffix = what)
647642
return unless load_edit("rbac_#{what}_edit__#{id}", "replace_cell__explorer")
648643

649644
case key
650-
when :user
651-
record = @edit[:user_id] ? User.find_by(:id => @edit[:user_id]) : User.new
652-
validated = rbac_user_validate?
653-
rbac_user_set_record_vars(record)
654645
when :group then
655646
record = @edit[:group_id] ? MiqGroup.find_by(:id => @edit[:group_id]) : MiqGroup.new
656647
validated = rbac_group_validate?
@@ -663,7 +654,6 @@ def rbac_edit_save_or_add(what, rbac_suffix = what)
663654
end
664655

665656
if record.valid? && validated && record.save!
666-
record.update!(:miq_groups => Rbac.filtered(MiqGroup.where(:id => rbac_user_get_group_ids))) if key == :user # only set miq_groups if everything is valid
667657
populate_role_features(record) if what == "role"
668658
self.current_user = record if what == 'user' && @edit[:current][:userid] == current_userid
669659
AuditEvent.success(build_saved_audit(record, @edit))
@@ -733,13 +723,10 @@ def rbac_field_changed(rec_type)
733723
return unless load_edit("rbac_#{rec_type}_edit__#{id}", "replace_cell__explorer")
734724

735725
case rec_type
736-
when "user" then rbac_user_get_form_vars
737726
when "group" then rbac_group_get_form_vars
738727
when "role" then rbac_role_get_form_vars
739728
end
740729

741-
@edit[:new][:group] = rbac_user_get_group_ids if rec_type == "user"
742-
743730
session[:changed] = changed = @edit[:new] != @edit[:current]
744731

745732
render :update do |page|
@@ -751,11 +738,6 @@ def rbac_field_changed(rec_type)
751738
page.replace(@refresh_div, :partial => @refresh_partial)
752739
end
753740
else
754-
# only do following for user (adding/editing a user)
755-
if x_node.split("-").first == "u" || x_node == "xx-u"
756-
page.replace("group_selected",
757-
:partial => "ops/rbac_group_selected")
758-
end
759741
# only do following for groups
760742
if @refresh_div
761743
page.replace(@refresh_div,
@@ -953,82 +935,16 @@ def build_rbac_feature_tree
953935
# Set form variables for user edit
954936
def rbac_user_set_form_vars
955937
copy = @sb[:typ] == "copy"
956-
# save a shadow copy of the record if record is being copied
957-
@user = copy ? @record.dup : @record
958-
@user.miq_groups = @record.miq_groups if copy
959938
@edit = {:new => {}, :current => {}}
960939
@edit[:user_id] = @record.id unless copy
961-
@edit[:key] = "rbac_user_edit__#{@edit[:user_id] || "new"}"
962-
# prefill form fields for edit and copy action
963-
@edit[:new].merge!(:name => @user.name,
964-
:email => @user.email,
965-
:group => @user.miq_groups ? @user.miq_groups.map(&:id).sort : nil)
966-
unless copy
967-
@edit[:new].merge!(:userid => @user.userid,
968-
:password => @user.password,
969-
:verify => @user.password)
970-
end
971-
# load all user groups, filter available for tenant
972-
@edit[:groups] = Rbac.filtered(MiqGroup.non_tenant_groups_in_my_region).sort_by { |g| g.description.downcase }.collect { |g| [g.description, g.id] }
973-
# store current state of the new users information
974-
@edit[:current] = copy_hash(@edit[:new])
940+
@edit[:new][:userid] = @record.userid
975941
@right_cell_text = if @edit[:user_id]
976942
_("Editing User \"%{name}\"") % {:name => @record.name}
977943
else
978944
_('Adding a new User')
979945
end
980946
end
981947

982-
# Get variables from user edit form
983-
def rbac_user_get_form_vars
984-
copy_params_if_present(@edit[:new], params, %i[name password verify])
985-
986-
@edit[:new][:userid] = params[:userid].strip.presence if params[:userid]
987-
@edit[:new][:email] = params[:email].strip.presence if params[:email]
988-
@edit[:new][:group] = params[:chosen_group] if params[:chosen_group]
989-
end
990-
991-
# Set user record variables to new values
992-
def rbac_user_set_record_vars(user)
993-
user.name = @edit[:new][:name]
994-
user.userid = @edit[:new][:userid]
995-
user.email = @edit[:new][:email]
996-
user.password = @edit[:new][:password] if @edit[:new][:password]
997-
end
998-
999-
# Get array of group ids
1000-
def rbac_user_get_group_ids
1001-
case @edit[:new][:group]
1002-
when 'null', nil
1003-
[]
1004-
when String
1005-
@edit[:new][:group].split(',').delete_if(&:blank?).map(&:to_i).sort
1006-
when Array
1007-
@edit[:new][:group].map(&:to_i).sort
1008-
end
1009-
end
1010-
1011-
# Validate some of the user fields
1012-
def rbac_user_validate?
1013-
valid = true
1014-
if @edit[:new][:password] != @edit[:new][:verify]
1015-
add_flash(_("Password/Verify Password do not match"), :error)
1016-
valid = false
1017-
end
1018-
1019-
new_group_ids = rbac_user_get_group_ids
1020-
new_groups = new_group_ids.present? && MiqGroup.find(new_group_ids).present? ? MiqGroup.find(new_group_ids) : []
1021-
1022-
if new_group_ids.blank?
1023-
add_flash(_("A User must be assigned to a Group"), :error)
1024-
valid = false
1025-
elsif Rbac.filtered(new_groups).count != new_group_ids.count
1026-
add_flash(_("A User must be assigned to an allowed Group"), :error)
1027-
valid = false
1028-
end
1029-
valid
1030-
end
1031-
1032948
def valid_tenant?(tenant_id)
1033949
Rbac.filtered(Tenant.in_my_region.where(:id => tenant_id)).present?
1034950
end

app/javascript/components/async-credentials/edit-password-field.jsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { useFieldApi, componentTypes } from '@@ddf';
1010

1111
const EditPasswordField = ({ componentClass, ...props }) => {
1212
const {
13-
labelText, validateOnMount, isDisabled, editMode, setEditMode, buttonLabel, input, meta, ...rest
13+
labelText, validateOnMount, isDisabled, editMode, setEditMode, buttonLabel, input, meta, icon, kind, ...rest
1414
} = useFieldApi(prepareProps(props));
1515

1616
const invalid = (meta.touched || validateOnMount) && meta.error;
@@ -71,11 +71,16 @@ const EditPasswordField = ({ componentClass, ...props }) => {
7171
>
7272
<Button
7373
hasIconOnly
74-
kind="secondary"
74+
kind={kind || 'secondary'}
7575
size="md"
7676
onClick={setEditMode}
7777
iconDescription={buttonLabel}
78-
renderIcon={(props) => <EditOff size={16} {...props} />}
78+
renderIcon={(props) => {
79+
if (icon) {
80+
return icon;
81+
}
82+
return (<EditOff size={16} {...props} />);
83+
}}
7984
/>
8085
</Column>
8186
</Grid>
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/* eslint-disable jsx-a11y/label-has-associated-control */
2+
import React from 'react';
3+
import PropTypes from 'prop-types';
4+
5+
const SelectedGroupsList = ({ groups }) => {
6+
const selectedGroups = [];
7+
8+
groups.sort();
9+
if (groups) {
10+
groups.forEach((group) => {
11+
selectedGroups.push(
12+
<div key={group}>
13+
<i className="ff ff-group" />
14+
<p className="group-name" id={group}>
15+
{group}
16+
</p>
17+
<br />
18+
</div>
19+
);
20+
});
21+
}
22+
23+
return (
24+
<div>
25+
<label id="selected-groups-label">
26+
{__('Selected Groups')}
27+
</label>
28+
<div id="selected-groups">
29+
{selectedGroups}
30+
</div>
31+
</div>
32+
);
33+
};
34+
35+
SelectedGroupsList.propTypes = {
36+
groups: PropTypes.arrayOf(PropTypes.string),
37+
};
38+
39+
SelectedGroupsList.defaultProps = {
40+
groups: [],
41+
};
42+
43+
export default SelectedGroupsList;
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
const areGroupsEqual = (initialValues, selectedGroups = []) => {
2+
const selectedGroupsCopy = [...selectedGroups];
3+
selectedGroupsCopy.sort();
4+
const initialGroupValuesCopy = [...initialValues.groups];
5+
initialGroupValuesCopy.sort();
6+
if (selectedGroupsCopy.length !== initialGroupValuesCopy.length) {
7+
return false;
8+
}
9+
return selectedGroupsCopy.every((group, index) => group === initialGroupValuesCopy[index]);
10+
};
11+
12+
export const confirmPasswordValidation = (initialValues, id, editMode, values, setState, selectedGroups) => {
13+
if (values.groups === undefined) {
14+
if (selectedGroups.length > 0) {
15+
setState((state) => ({
16+
...state,
17+
selectedGroups: [],
18+
}));
19+
}
20+
}
21+
const errors = {};
22+
const groupIds = [];
23+
if (values.groups) {
24+
values.groups.forEach((group) => {
25+
if (group.value) {
26+
groupIds.push(group.value);
27+
} else {
28+
groupIds.push(group);
29+
}
30+
});
31+
}
32+
if (!editMode && !!id) {
33+
values.password = undefined;
34+
values.confirmPassword = undefined;
35+
if (values.name === initialValues.name
36+
&& values.userid === initialValues.userid
37+
&& values.email === initialValues.email
38+
&& areGroupsEqual(initialValues, groupIds)) {
39+
errors.confirmPassword = '';
40+
}
41+
}
42+
43+
if ((editMode || !id) && values.password !== values.confirmPassword) {
44+
errors.confirmPassword = 'Password/Verify Password do not match';
45+
}
46+
47+
return errors;
48+
};

0 commit comments

Comments
 (0)