diff options
author | Fatih Acet <acetfatih@gmail.com> | 2016-12-09 18:11:47 +0000 |
---|---|---|
committer | Fatih Acet <acetfatih@gmail.com> | 2016-12-09 18:11:47 +0000 |
commit | 5bb43bb9531422545f974df8a6cf5616b7631f51 (patch) | |
tree | 9a38a0888f498def6d26a5ee590963509a1085bd | |
parent | b546fd7bba7434c787debb92e944b34420a0ee4c (diff) | |
parent | fcf332a4fa544d4a5eba200878a7b9298e5b6f6b (diff) | |
download | gitlab-ce-5bb43bb9531422545f974df8a6cf5616b7631f51.tar.gz |
Merge branch 'members-dropdowns' into 'master'
Updated members dropdowns
## What does this MR do?
EE has different dropdowns to allow for group LDAP members to be overridden, this ports the dropdown changes over to reduce conflicts.
## Screenshots (if relevant)
![Screen_Shot_2016-12-07_at_15.28.20](/uploads/6cb6def34015b024dc878aa3b99be4a0/Screen_Shot_2016-12-07_at_15.28.20.png)
See merge request !7974
-rw-r--r-- | app/assets/javascripts/gl_dropdown.js | 5 | ||||
-rw-r--r-- | app/assets/javascripts/members.js.es6 | 65 | ||||
-rw-r--r-- | app/assets/stylesheets/framework/dropdowns.scss | 5 | ||||
-rw-r--r-- | app/assets/stylesheets/pages/members.scss | 4 | ||||
-rw-r--r-- | app/views/groups/group_members/update.js.haml | 1 | ||||
-rw-r--r-- | app/views/projects/group_links/update.js.haml | 1 | ||||
-rw-r--r-- | app/views/projects/project_members/update.js.haml | 1 | ||||
-rw-r--r-- | app/views/shared/members/_group.html.haml | 21 | ||||
-rw-r--r-- | app/views/shared/members/_member.html.haml | 20 | ||||
-rw-r--r-- | changelogs/unreleased/members-dropdowns.yml | 4 | ||||
-rw-r--r-- | features/steps/group/members.rb | 7 | ||||
-rw-r--r-- | features/steps/project/team_management.rb | 8 | ||||
-rw-r--r-- | spec/features/projects/members/group_links_spec.rb | 9 |
13 files changed, 131 insertions, 20 deletions
diff --git a/app/assets/javascripts/gl_dropdown.js b/app/assets/javascripts/gl_dropdown.js index 969778dded7..9a91018a8e4 100644 --- a/app/assets/javascripts/gl_dropdown.js +++ b/app/assets/javascripts/gl_dropdown.js @@ -650,6 +650,11 @@ } else if(value) { field = this.dropdown.parent().find("input[name='" + fieldName + "'][value='" + value.toString().replace(/'/g, '\\\'') + "']"); } + + if (this.options.isSelectable && !this.options.isSelectable(selectedObject, el)) { + return; + } + if (el.hasClass(ACTIVE_CLASS)) { el.removeClass(ACTIVE_CLASS); if (field && field.length) { diff --git a/app/assets/javascripts/members.js.es6 b/app/assets/javascripts/members.js.es6 index 895bc10784f..e3f367a11eb 100644 --- a/app/assets/javascripts/members.js.es6 +++ b/app/assets/javascripts/members.js.es6 @@ -1,38 +1,81 @@ -/* eslint-disable */ -((w) => { - w.gl = w.gl || {}; +/* eslint-disable class-methods-use-this */ +(() => { + window.gl = window.gl || {}; class Members { constructor() { this.addListeners(); + this.initGLDropdown(); } addListeners() { $('.project_member, .group_member').off('ajax:success').on('ajax:success', this.removeRow); - $('.js-member-update-control').off('change').on('change', this.formSubmit); - $('.js-edit-member-form').off('ajax:success').on('ajax:success', this.formSuccess); + $('.js-member-update-control').off('change').on('change', this.formSubmit.bind(this)); + $('.js-edit-member-form').off('ajax:success').on('ajax:success', this.formSuccess.bind(this)); gl.utils.disableButtonIfEmptyField('#user_ids', 'input[name=commit]', 'change'); } + initGLDropdown() { + $('.js-member-permissions-dropdown').each((i, btn) => { + const $btn = $(btn); + + $btn.glDropdown({ + selectable: true, + isSelectable(selected, $el) { + return !$el.hasClass('is-active'); + }, + fieldName: $btn.data('field-name'), + id(selected, $el) { + return $el.data('id'); + }, + toggleLabel(selected, $el) { + return $el.text(); + }, + clicked: (selected, $link) => { + this.formSubmit(null, $link); + }, + }); + }); + } + removeRow(e) { const $target = $(e.target); if ($target.hasClass('btn-remove')) { $target.closest('.member') - .fadeOut(function () { + .fadeOut(function fadeOutMemberRow() { $(this).remove(); }); } } - formSubmit() { - $(this).closest('form').trigger("submit.rails").end().disable(); + formSubmit(e, $el = null) { + const $this = e ? $(e.currentTarget) : $el; + const { $toggle, $dateInput } = this.getMemberListItems($this); + + $this.closest('form').trigger('submit.rails'); + + $toggle.disable(); + $dateInput.disable(); } - formSuccess() { - $(this).find('.js-member-update-control').enable(); + formSuccess(e) { + const { $toggle, $dateInput } = this.getMemberListItems($(e.currentTarget).closest('.member')); + + $toggle.enable(); + $dateInput.enable(); + } + + getMemberListItems($el) { + const $memberListItem = $el.is('.member') ? $el : $(`#${$el.data('el-id')}`); + + return { + $memberListItem, + $toggle: $memberListItem.find('.dropdown-menu-toggle'), + $dateInput: $memberListItem.find('.js-access-expiration-date'), + }; } } gl.Members = Members; -})(window); +})(); diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss index 33de652c06f..d5914b900e2 100644 --- a/app/assets/stylesheets/framework/dropdowns.scss +++ b/app/assets/stylesheets/framework/dropdowns.scss @@ -42,6 +42,11 @@ border-radius: $border-radius-base; white-space: nowrap; + &[disabled] { + background-color: $input-bg-disabled; + cursor: not-allowed; + } + &.no-outline { outline: 0; } diff --git a/app/assets/stylesheets/pages/members.scss b/app/assets/stylesheets/pages/members.scss index 756efa9c7fa..5f3bbb40ba0 100644 --- a/app/assets/stylesheets/pages/members.scss +++ b/app/assets/stylesheets/pages/members.scss @@ -54,6 +54,10 @@ @media (min-width: $screen-sm-min) { width: 50%; } + + .dropdown-menu-toggle { + width: 100%; + } } .member-access-text { diff --git a/app/views/groups/group_members/update.js.haml b/app/views/groups/group_members/update.js.haml index de8f53b6b52..9d05bff6c4e 100644 --- a/app/views/groups/group_members/update.js.haml +++ b/app/views/groups/group_members/update.js.haml @@ -1,3 +1,4 @@ :plain var $listItem = $('#{escape_javascript(render('shared/members/member', member: @group_member))}'); $("##{dom_id(@group_member)} .list-item-name").replaceWith($listItem.find('.list-item-name')); + gl.utils.localTimeAgo($('.js-timeago'), $("##{dom_id(@group_member)}")); diff --git a/app/views/projects/group_links/update.js.haml b/app/views/projects/group_links/update.js.haml index af9a5b19060..55520fda494 100644 --- a/app/views/projects/group_links/update.js.haml +++ b/app/views/projects/group_links/update.js.haml @@ -1,3 +1,4 @@ :plain var $listItem = $('#{escape_javascript(render('shared/members/group', group_link: @group_link))}'); $("#group_member_#{@group_link.id} .list-item-name").replaceWith($listItem.find('.list-item-name')); + gl.utils.localTimeAgo($('.js-timeago'), $("#group_member_#{@group_link.id}")); diff --git a/app/views/projects/project_members/update.js.haml b/app/views/projects/project_members/update.js.haml index 91927181efb..d15f4310ff5 100644 --- a/app/views/projects/project_members/update.js.haml +++ b/app/views/projects/project_members/update.js.haml @@ -1,3 +1,4 @@ :plain var $listItem = $('#{escape_javascript(render('shared/members/member', member: @project_member))}'); $("##{dom_id(@project_member)} .list-item-name").replaceWith($listItem.find('.list-item-name')); + gl.utils.localTimeAgo($('.js-timeago'), $("##{dom_id(@project_member)}")); diff --git a/app/views/shared/members/_group.html.haml b/app/views/shared/members/_group.html.haml index 1c0346bbc78..8928de9097b 100644 --- a/app/views/shared/members/_group.html.haml +++ b/app/views/shared/members/_group.html.haml @@ -1,7 +1,8 @@ - group_link = local_assigns[:group_link] - group = group_link.group - can_admin_member = can?(current_user, :admin_project_member, @project) -%li.member.group_member{ id: "group_member_#{group_link.id}" } +- dom_id = "group_member_#{group_link.id}" +%li.member.group_member{ id: dom_id } %span{ class: "list-item-name" } = image_tag group_icon(group), class: "avatar s40", alt: '' %strong @@ -14,7 +15,23 @@ Expires in #{distance_of_time_in_words_to_now(group_link.expires_at)} .controls.member-controls = form_tag namespace_project_group_link_path(@project.namespace, @project, group_link), method: :put, remote: true, class: 'form-horizontal js-edit-member-form' do - = select_tag 'group_link[group_access]', options_for_select(ProjectGroupLink.access_options, group_link.group_access), class: 'form-control member-form-control append-right-5 js-member-update-control', id: "member_access_level_#{group.id}", disabled: !can_admin_member + = hidden_field_tag "group_link[group_access]", group_link.group_access + .member-form-control.dropdown.append-right-5 + %button.dropdown-menu-toggle.js-member-permissions-dropdown{ type: "button", + disabled: !can_admin_member, + data: { toggle: "dropdown", field_name: "group_link[group_access]" } } + %span.dropdown-toggle-text + = group_link.human_access + = icon("chevron-down") + .dropdown-menu.dropdown-select.dropdown-menu-align-right.dropdown-menu-selectable + = dropdown_title("Change permissions") + .dropdown-content + %ul + - Gitlab::Access.options.each do |role, role_id| + %li + = link_to role, "javascript:void(0)", + class: ("is-active" if group_link.group_access == role_id), + data: { id: role_id, el_id: dom_id } .prepend-left-5.clearable-input.member-form-control = text_field_tag 'group_link[expires_at]', group_link.expires_at, class: 'form-control js-access-expiration-date js-member-update-control', placeholder: 'Expiration date', id: "member_expires_at_#{group.id}", disabled: !can_admin_member %i.clear-icon.js-clear-input diff --git a/app/views/shared/members/_member.html.haml b/app/views/shared/members/_member.html.haml index e67f7d5a352..659d4c905fc 100644 --- a/app/views/shared/members/_member.html.haml +++ b/app/views/shared/members/_member.html.haml @@ -48,9 +48,25 @@ - if show_controls && (member.respond_to?(:group) && @group) || (member.respond_to?(:project) && @project) - if user != current_user = form_for member, remote: true, html: { class: 'form-horizontal js-edit-member-form' } do |f| - = f.select :access_level, options_for_select(member.class.access_level_roles, member.access_level), {}, class: 'form-control member-form-control append-right-5 js-member-update-control', id: "member_access_level_#{member.id}", disabled: !can_admin_member + = f.hidden_field :access_level + .member-form-control.dropdown.append-right-5 + %button.dropdown-menu-toggle.js-member-permissions-dropdown{ type: "button", + disabled: !can_admin_member, + data: { toggle: "dropdown", field_name: "#{f.object_name}[access_level]" } } + %span.dropdown-toggle-text + = member.human_access + = icon("chevron-down") + .dropdown-menu.dropdown-select.dropdown-menu-align-right.dropdown-menu-selectable + = dropdown_title("Change permissions") + .dropdown-content + %ul + - Gitlab::Access.options.each do |role, role_id| + %li + = link_to role, "javascript:void(0)", + class: ("is-active" if member.access_level == role_id), + data: { id: role_id, el_id: dom_id(member) } .prepend-left-5.clearable-input.member-form-control - = f.text_field :expires_at, class: 'form-control js-access-expiration-date js-member-update-control', placeholder: 'Expiration date', id: "member_expires_at_#{member.id}", disabled: !can_admin_member + = f.text_field :expires_at, class: 'form-control js-access-expiration-date js-member-update-control', placeholder: 'Expiration date', id: "member_expires_at_#{member.id}", disabled: !can_admin_member, data: { el_id: dom_id(member) } %i.clear-icon.js-clear-input - else %span.member-access-text= member.human_access diff --git a/changelogs/unreleased/members-dropdowns.yml b/changelogs/unreleased/members-dropdowns.yml new file mode 100644 index 00000000000..b15403d6d62 --- /dev/null +++ b/changelogs/unreleased/members-dropdowns.yml @@ -0,0 +1,4 @@ +--- +title: Updated members dropdowns +merge_request: +author: diff --git a/features/steps/group/members.rb b/features/steps/group/members.rb index cefc55d07ab..adaf375453c 100644 --- a/features/steps/group/members.rb +++ b/features/steps/group/members.rb @@ -117,7 +117,12 @@ class Spinach::Features::GroupMembers < Spinach::FeatureSteps member = mary_jane_member page.within "#group_member_#{member.id}" do - select 'Developer', from: "member_access_level_#{member.id}" + click_button member.human_access + + page.within '.dropdown-menu' do + click_link 'Developer' + end + wait_for_ajax end end diff --git a/features/steps/project/team_management.rb b/features/steps/project/team_management.rb index b21d0849ad1..22d971fadfb 100644 --- a/features/steps/project/team_management.rb +++ b/features/steps/project/team_management.rb @@ -65,7 +65,11 @@ class Spinach::Features::ProjectTeamManagement < Spinach::FeatureSteps user = User.find_by(name: 'Dmitriy') project_member = project.project_members.find_by(user_id: user.id) page.within "#project_member_#{project_member.id}" do - select "Reporter", from: "member_access_level_#{project_member.id}" + click_button project_member.human_access + + page.within '.dropdown-menu' do + click_link 'Reporter' + end end end @@ -144,7 +148,7 @@ class Spinach::Features::ProjectTeamManagement < Spinach::FeatureSteps step 'I should see "Opensource" group user listing' do page.within '.project-members-groups' do expect(page).to have_content('OpenSource') - expect(find('select').value).to eq('40') + expect(first('.group_member')).to have_content('Master') end end end diff --git a/spec/features/projects/members/group_links_spec.rb b/spec/features/projects/members/group_links_spec.rb index cc2f695211c..94995f7cf95 100644 --- a/spec/features/projects/members/group_links_spec.rb +++ b/spec/features/projects/members/group_links_spec.rb @@ -16,12 +16,17 @@ feature 'Projects > Members > Anonymous user sees members', feature: true, js: t end it 'updates group access level' do - select 'Guest', from: "member_access_level_#{group.id}" + click_button @group_link.human_access + + page.within '.dropdown-menu' do + click_link 'Guest' + end + wait_for_ajax visit namespace_project_project_members_path(project.namespace, project) - expect(page).to have_select("member_access_level_#{group.id}", selected: 'Guest') + expect(first('.group_member')).to have_content('Guest') end it 'updates expiry date' do |