Commit 080dc368 authored by Sean McGivern's avatar Sean McGivern

Merge branch '250655-check-usage-of-app-views-projects-group_links-update-js-haml' into 'master'

Remove `projects/group_links/update.js.haml` in favor of vanilla JS

See merge request gitlab-org/gitlab!42745
parents 8537faa8 96a97187
...@@ -2,6 +2,7 @@ import $ from 'jquery'; ...@@ -2,6 +2,7 @@ import $ from 'jquery';
import { Rails } from '~/lib/utils/rails_ujs'; import { Rails } from '~/lib/utils/rails_ujs';
import { disableButtonIfEmptyField } from '~/lib/utils/common_utils'; import { disableButtonIfEmptyField } from '~/lib/utils/common_utils';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown'; import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
import { __, sprintf } from '~/locale';
export default class Members { export default class Members {
constructor() { constructor() {
...@@ -64,7 +65,28 @@ export default class Members { ...@@ -64,7 +65,28 @@ export default class Members {
} }
formSuccess(e) { formSuccess(e) {
const { $toggle, $dateInput } = this.getMemberListItems($(e.currentTarget).closest('.member')); const { $toggle, $dateInput, $expiresIn, $expiresInText } = this.getMemberListItems(
$(e.currentTarget).closest('.js-member'),
);
const [data] = e.detail;
const expiresIn = data?.expires_in;
if (expiresIn) {
$expiresIn.removeClass('gl-display-none');
$expiresInText.text(sprintf(__('Expires in %{expires_at}'), { expires_at: expiresIn }));
const { expires_soon: expiresSoon } = data;
if (expiresSoon) {
$expiresInText.addClass('text-warning');
} else {
$expiresInText.removeClass('text-warning');
}
} else {
$expiresIn.addClass('gl-display-none');
}
$toggle.enable(); $toggle.enable();
$dateInput.enable(); $dateInput.enable();
...@@ -72,10 +94,12 @@ export default class Members { ...@@ -72,10 +94,12 @@ export default class Members {
// eslint-disable-next-line class-methods-use-this // eslint-disable-next-line class-methods-use-this
getMemberListItems($el) { getMemberListItems($el) {
const $memberListItem = $el.is('.member') ? $el : $(`#${$el.data('elId')}`); const $memberListItem = $el.is('.js-member') ? $el : $(`#${$el.data('elId')}`);
return { return {
$memberListItem, $memberListItem,
$expiresIn: $memberListItem.find('.js-expires-in'),
$expiresInText: $memberListItem.find('.js-expires-in-text'),
$toggle: $memberListItem.find('.dropdown-menu-toggle'), $toggle: $memberListItem.find('.dropdown-menu-toggle'),
$dateInput: $memberListItem.find('.js-access-expiration-date'), $dateInput: $memberListItem.find('.js-access-expiration-date'),
}; };
......
...@@ -24,6 +24,15 @@ class Groups::GroupLinksController < Groups::ApplicationController ...@@ -24,6 +24,15 @@ class Groups::GroupLinksController < Groups::ApplicationController
def update def update
Groups::GroupLinks::UpdateService.new(@group_link).execute(group_link_params) Groups::GroupLinks::UpdateService.new(@group_link).execute(group_link_params)
if @group_link.expires?
render json: {
expires_in: helpers.distance_of_time_in_words_to_now(@group_link.expires_at),
expires_soon: @group_link.expires_soon?
}
else
render json: {}
end
end end
def destroy def destroy
......
...@@ -21,8 +21,17 @@ class Projects::GroupLinksController < Projects::ApplicationController ...@@ -21,8 +21,17 @@ class Projects::GroupLinksController < Projects::ApplicationController
end end
def update def update
@group_link = @project.project_group_links.find(params[:id]) group_link = @project.project_group_links.find(params[:id])
Projects::GroupLinks::UpdateService.new(@group_link).execute(group_link_params) Projects::GroupLinks::UpdateService.new(group_link).execute(group_link_params)
if group_link.expires?
render json: {
expires_in: helpers.distance_of_time_in_words_to_now(group_link.expires_at),
expires_soon: group_link.expires_soon?
}
else
render json: {}
end
end end
def destroy def destroy
......
: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}"));
...@@ -6,17 +6,18 @@ ...@@ -6,17 +6,18 @@
-# Note this is just for groups. For individual members please see shared/members/_member -# Note this is just for groups. For individual members please see shared/members/_member
%li.member.group_member.py-2.px-3.d-flex.flex-column.flex-md-row{ id: dom_id, data: { qa_selector: 'group_row' } } %li.member.js-member.group_member.py-2.px-3.d-flex.flex-column.flex-md-row{ id: dom_id, data: { qa_selector: 'group_row' } }
%span.list-item-name.mb-2.m-md-0 %span.list-item-name.mb-2.m-md-0
= group_icon(group, class: "avatar s40 flex-shrink-0 flex-grow-0", alt: '') = group_icon(group, class: "avatar s40 flex-shrink-0 flex-grow-0", alt: '')
.user-info .user-info
= link_to group.full_name, group_path(group), class: 'member' = link_to group.full_name, group_path(group), class: 'member'
.cgray .cgray
Given access #{time_ago_with_tooltip(group_link.created_at)} Given access #{time_ago_with_tooltip(group_link.created_at)}
- if group_link.expires? %span.js-expires-in{ class: ('gl-display-none' unless group_link.expires?) }
· &middot;
%span{ class: ('text-warning' if group_link.expires_soon?) } %span.js-expires-in-text{ class: ('text-warning' if group_link.expires_soon?) }
= _("Expires in %{expires_at}").html_safe % { expires_at: distance_of_time_in_words_to_now(group_link.expires_at) } - if group_link.expires?
= _("Expires in %{expires_at}").html_safe % { expires_at: distance_of_time_in_words_to_now(group_link.expires_at) }
.controls.member-controls.align-items-center .controls.member-controls.align-items-center
= form_tag group_link_path, method: :put, remote: true, class: 'js-edit-member-form form-group d-sm-flex' do = form_tag group_link_path, method: :put, remote: true, class: 'js-edit-member-form form-group d-sm-flex' do
= hidden_field_tag "group_link[group_access]", group_link.group_access = hidden_field_tag "group_link[group_access]", group_link.group_access
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
-# Note this is just for individual members. For groups please see shared/members/_group -# Note this is just for individual members. For groups please see shared/members/_group
%li.member.py-2.px-3.d-flex.flex-column{ class: [dom_class(member), ("is-overridden" if override), ("flex-md-row" unless force_mobile_view)], id: dom_id(member), data: { qa_selector: 'member_row' } } %li.member.js-member.py-2.px-3.d-flex.flex-column{ class: [dom_class(member), ("is-overridden" if override), ("flex-md-row" unless force_mobile_view)], id: dom_id(member), data: { qa_selector: 'member_row' } }
%span.list-item-name.mb-2.m-md-0 %span.list-item-name.mb-2.m-md-0
- if user - if user
= image_tag avatar_icon_for_user(user, 40), class: "avatar s40 flex-shrink-0 flex-grow-0", alt: '' = image_tag avatar_icon_for_user(user, 40), class: "avatar s40 flex-shrink-0 flex-grow-0", alt: ''
......
...@@ -136,10 +136,15 @@ RSpec.describe Groups::GroupLinksController do ...@@ -136,10 +136,15 @@ RSpec.describe Groups::GroupLinksController do
let(:expiry_date) { 1.month.from_now.to_date } let(:expiry_date) { 1.month.from_now.to_date }
subject do subject do
post(:update, params: { group_id: shared_group, post(
id: link.id, :update,
group_link: { group_access: Gitlab::Access::GUEST, params: {
expires_at: expiry_date } }) group_id: shared_group,
id: link.id,
group_link: { group_access: Gitlab::Access::GUEST, expires_at: expiry_date }
},
format: :json
)
end end
context 'when user has admin access to the shared group' do context 'when user has admin access to the shared group' do
...@@ -160,6 +165,26 @@ RSpec.describe Groups::GroupLinksController do ...@@ -160,6 +165,26 @@ RSpec.describe Groups::GroupLinksController do
expect(link.expires_at).to eq(expiry_date) expect(link.expires_at).to eq(expiry_date)
end end
context 'when `expires_at` is set' do
it 'returns correct json response' do
travel_to Time.now.utc.beginning_of_day
subject
expect(json_response).to eq({ "expires_in" => "about 1 month", "expires_soon" => false })
end
end
context 'when `expires_at` is not set' do
let(:expiry_date) { nil }
it 'returns empty json response' do
subject
expect(json_response).to be_empty
end
end
it 'updates project permissions' do it 'updates project permissions' do
expect { subject }.to change { group_member.can?(:create_release, project) }.from(true).to(false) expect { subject }.to change { group_member.can?(:create_release, project) }.from(true).to(false)
end end
......
...@@ -3,10 +3,10 @@ ...@@ -3,10 +3,10 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Projects::GroupLinksController do RSpec.describe Projects::GroupLinksController do
let(:group) { create(:group, :private) } let_it_be(:group) { create(:group, :private) }
let(:group2) { create(:group, :private) } let_it_be(:group2) { create(:group, :private) }
let(:project) { create(:project, :private, group: group2) } let_it_be(:project) { create(:project, :private, group: group2) }
let(:user) { create(:user) } let_it_be(:user) { create(:user) }
before do before do
project.add_maintainer(user) project.add_maintainer(user)
...@@ -142,4 +142,47 @@ RSpec.describe Projects::GroupLinksController do ...@@ -142,4 +142,47 @@ RSpec.describe Projects::GroupLinksController do
end end
end end
end end
describe '#update' do
let_it_be(:link) do
create(
:project_group_link,
{
project: project,
group: group
}
)
end
let(:expiry_date) { 1.month.from_now.to_date }
before do
travel_to Time.now.utc.beginning_of_day
put(
:update,
params: {
namespace_id: project.namespace.to_param,
project_id: project.to_param,
id: link.id,
group_link: { group_access: Gitlab::Access::GUEST, expires_at: expiry_date }
},
format: :json
)
end
context 'when `expires_at` is set' do
it 'returns correct json response' do
expect(json_response).to eq({ "expires_in" => "about 1 month", "expires_soon" => false })
end
end
context 'when `expires_at` is not set' do
let(:expiry_date) { nil }
it 'returns empty json response' do
expect(json_response).to be_empty
end
end
end
end end
...@@ -6,62 +6,115 @@ RSpec.describe 'Groups > Members > Manage groups', :js do ...@@ -6,62 +6,115 @@ RSpec.describe 'Groups > Members > Manage groups', :js do
include Select2Helper include Select2Helper
include Spec::Support::Helpers::Features::ListRowsHelpers include Spec::Support::Helpers::Features::ListRowsHelpers
let(:user) { create(:user) } let_it_be(:user) { create(:user) }
let(:shared_with_group) { create(:group) }
let(:shared_group) { create(:group) }
before do before do
stub_feature_flags(vue_group_members_list: false) stub_feature_flags(vue_group_members_list: false)
shared_group.add_owner(user)
sign_in(user) sign_in(user)
end end
it 'add group to group' do context 'when group link does not exist' do
visit group_group_members_path(shared_group) let_it_be(:group) { create(:group) }
let_it_be(:group_to_add) { create(:group) }
add_group(shared_with_group.id, 'Reporter') before do
group.add_owner(user)
visit group_group_members_path(group)
end
click_groups_tab it 'add group to group' do
add_group(group_to_add.id, 'Reporter')
page.within(first_row) do click_groups_tab
expect(page).to have_content(shared_with_group.name)
expect(page).to have_content('Reporter') page.within(first_row) do
expect(page).to have_content(group_to_add.name)
expect(page).to have_content('Reporter')
end
end end
end end
it 'remove group from group' do context 'when group link exists' do
create(:group_group_link, shared_group: shared_group, let_it_be(:shared_with_group) { create(:group) }
shared_with_group: shared_with_group, group_access: ::Gitlab::Access::DEVELOPER) let_it_be(:shared_group) { create(:group) }
visit group_group_members_path(shared_group) let(:additional_link_attrs) { {} }
click_groups_tab let_it_be(:group_link, refind: true) do
create(
:group_group_link,
shared_group: shared_group,
shared_with_group: shared_with_group,
group_access: ::Gitlab::Access::DEVELOPER
)
end
expect(page).to have_content(shared_with_group.name) before do
travel_to Time.now.utc.beginning_of_day
group_link.update!(additional_link_attrs)
accept_confirm do shared_group.add_owner(user)
find(:css, '#tab-groups li', text: shared_with_group.name).find(:css, 'a.btn-remove').click visit group_group_members_path(shared_group)
end end
expect(page).not_to have_content(shared_with_group.name) it 'remove group from group' do
end click_groups_tab
expect(page).to have_content(shared_with_group.name)
accept_confirm do
find(:css, '#tab-groups li', text: shared_with_group.name).find(:css, 'a.btn-remove').click
end
expect(page).not_to have_content(shared_with_group.name)
end
it 'update group to owner level' do it 'update group to owner level' do
create(:group_group_link, shared_group: shared_group, click_groups_tab
shared_with_group: shared_with_group, group_access: ::Gitlab::Access::DEVELOPER)
visit group_group_members_path(shared_group) page.within(first_row) do
click_button('Developer')
click_link('Maintainer')
click_groups_tab wait_for_requests
page.within(first_row) do expect(page).to have_button('Maintainer')
click_button('Developer') end
click_link('Maintainer') end
it 'updates expiry date' do
click_groups_tab
expires_at_field = "member_expires_at_#{shared_with_group.id}"
fill_in "member_expires_at_#{shared_with_group.id}", with: 3.days.from_now.to_date
find_field(expires_at_field).native.send_keys :enter
wait_for_requests wait_for_requests
expect(page).to have_button('Maintainer') page.within(find('li.group_member')) do
expect(page).to have_content('Expires in 3 days')
end
end
context 'when expiry date is set' do
let(:additional_link_attrs) { { expires_at: 3.days.from_now.to_date } }
it 'clears expiry date' do
click_groups_tab
page.within(find('li.group_member')) do
expect(page).to have_content('Expires in 3 days')
page.within(find('.js-edit-member-form')) do
find('.js-clear-input').click
end
wait_for_requests
expect(page).not_to have_content('Expires in')
end
end
end end
end end
......
...@@ -3,20 +3,23 @@ ...@@ -3,20 +3,23 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe 'Projects > Members > Groups with access list', :js do RSpec.describe 'Projects > Members > Groups with access list', :js do
let(:user) { create(:user) } let_it_be(:user) { create(:user) }
let(:group) { create(:group, :public) } let_it_be(:group) { create(:group, :public) }
let(:project) { create(:project, :public) } let_it_be(:project) { create(:project, :public) }
let(:additional_link_attrs) { {} }
let!(:group_link) { create(:project_group_link, project: project, group: group, **additional_link_attrs) }
before do before do
project.add_maintainer(user) travel_to Time.now.utc.beginning_of_day
@group_link = create(:project_group_link, project: project, group: group)
project.add_maintainer(user)
sign_in(user) sign_in(user)
visit project_project_members_path(project) visit project_project_members_path(project)
end end
it 'updates group access level' do it 'updates group access level' do
click_button @group_link.human_access click_button group_link.human_access
page.within '.dropdown-menu' do page.within '.dropdown-menu' do
click_link 'Guest' click_link 'Guest'
...@@ -30,14 +33,32 @@ RSpec.describe 'Projects > Members > Groups with access list', :js do ...@@ -30,14 +33,32 @@ RSpec.describe 'Projects > Members > Groups with access list', :js do
end end
it 'updates expiry date' do it 'updates expiry date' do
tomorrow = Date.today + 3 expires_at_field = "member_expires_at_#{group.id}"
fill_in expires_at_field, with: 3.days.from_now.to_date
fill_in "member_expires_at_#{group.id}", with: tomorrow.strftime("%F") find_field(expires_at_field).native.send_keys :enter
find('body').click
wait_for_requests wait_for_requests
page.within(find('li.group_member')) do page.within(find('li.group_member')) do
expect(page).to have_content('Expires in') expect(page).to have_content('Expires in 3 days')
end
end
context 'when link has expiry date set' do
let(:additional_link_attrs) { { expires_at: 3.days.from_now.to_date } }
it 'clears expiry date' do
page.within(find('li.group_member')) do
expect(page).to have_content('Expires in 3 days')
page.within(find('.js-edit-member-form')) do
find('.js-clear-input').click
end
wait_for_requests
expect(page).not_to have_content('Expires in')
end
end end
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment