Commit 0f7b5de4 authored by Sean McGivern's avatar Sean McGivern

Merge branch '7249-group-bulk-edit-issues-milestone-ce' into 'master'

CE Port of Allow bulk update for group issues

See merge request gitlab-org/gitlab-ce!30358
parents a87e2c99 14e2412e
/* eslint-disable consistent-return, func-names, array-callback-return, prefer-arrow-callback, no-unused-vars */
/* eslint-disable consistent-return, func-names, array-callback-return, prefer-arrow-callback */
import $ from 'jquery';
import _ from 'underscore';
......@@ -7,7 +7,7 @@ import Flash from './flash';
import { __ } from './locale';
export default {
init({ container, form, issues, prefixId } = {}) {
init({ form, issues, prefixId } = {}) {
this.prefixId = prefixId || 'issue_';
this.form = form || this.getElement('.bulk-update');
this.$labelDropdown = this.form.find('.js-label-select');
......
......@@ -2,26 +2,13 @@ import $ from 'jquery';
import axios from './lib/utils/axios_utils';
import flash from './flash';
import { s__, __ } from './locale';
import IssuableBulkUpdateSidebar from './issuable_bulk_update_sidebar';
import IssuableBulkUpdateActions from './issuable_bulk_update_actions';
import issuableInitBulkUpdateSidebar from './issuable_init_bulk_update_sidebar';
export default class IssuableIndex {
constructor(pagePrefix) {
this.initBulkUpdate(pagePrefix);
issuableInitBulkUpdateSidebar.init(pagePrefix);
IssuableIndex.resetIncomingEmailToken();
}
initBulkUpdate(pagePrefix) {
const userCanBulkUpdate = $('.issues-bulk-update').length > 0;
const alreadyInitialized = Boolean(this.bulkUpdateSidebar);
if (userCanBulkUpdate && !alreadyInitialized) {
IssuableBulkUpdateActions.init({
prefixId: pagePrefix,
});
this.bulkUpdateSidebar = new IssuableBulkUpdateSidebar();
}
}
static resetIncomingEmailToken() {
const $resetToken = $('.incoming-email-token-reset');
......
import IssuableBulkUpdateSidebar from './issuable_bulk_update_sidebar';
import issuableBulkUpdateActions from './issuable_bulk_update_actions';
export default {
bulkUpdateSidebar: null,
init(prefixId) {
const bulkUpdateEl = document.querySelector('.issues-bulk-update');
const alreadyInitialized = Boolean(this.bulkUpdateSidebar);
if (bulkUpdateEl && !alreadyInitialized) {
issuableBulkUpdateActions.init({ prefixId });
this.bulkUpdateSidebar = new IssuableBulkUpdateSidebar();
}
return this.bulkUpdateSidebar;
},
};
import projectSelect from '~/project_select';
import initFilteredSearch from '~/pages/search/init_filtered_search';
import issuableInitBulkUpdateSidebar from '~/issuable_init_bulk_update_sidebar';
import { FILTERED_SEARCH } from '~/pages/constants';
import IssuableFilteredSearchTokenKeys from 'ee_else_ce/filtered_search/issuable_filtered_search_token_keys';
import initManualOrdering from '~/manual_ordering';
const ISSUE_BULK_UPDATE_PREFIX = 'issue_';
document.addEventListener('DOMContentLoaded', () => {
IssuableFilteredSearchTokenKeys.addExtraTokensForIssues();
issuableInitBulkUpdateSidebar.init(ISSUE_BULK_UPDATE_PREFIX);
initFilteredSearch({
page: FILTERED_SEARCH.ISSUES,
......
......@@ -92,7 +92,7 @@ module IssuableActions
end
def bulk_update
result = Issuable::BulkUpdateService.new(project, current_user, bulk_update_params).execute(resource_name)
result = Issuable::BulkUpdateService.new(current_user, bulk_update_params).execute(resource_name)
quantity = result[:count]
render json: { notice: "#{quantity} #{resource_name.pluralize(quantity)} updated" }
......@@ -181,7 +181,7 @@ module IssuableActions
end
def authorize_admin_issuable!
unless can?(current_user, :"admin_#{resource_name}", @project) # rubocop:disable Gitlab/ModuleWithInstanceVariables
unless can?(current_user, :"admin_#{resource_name}", parent)
return access_denied!
end
end
......
# frozen_string_literal: true
module Issuable
class BulkUpdateService < IssuableBaseService
class BulkUpdateService
include Gitlab::Allowable
attr_accessor :current_user, :params
def initialize(user = nil, params = {})
@current_user, @params = user, params.dup
end
# rubocop: disable CodeReuse/ActiveRecord
def execute(type)
model_class = type.classify.constantize
......
- @can_bulk_update = can?(current_user, :admin_issue, @group)
- page_title "Issues"
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, safe_params.merge(rss_url_options).to_h, title: "#{@group.name} issues")
......@@ -9,8 +11,15 @@
= render 'shared/issuable/nav', type: :issues
.nav-controls
= render 'shared/issuable/feed_buttons'
- if @can_bulk_update
= render_if_exists 'shared/issuable/bulk_update_button'
= render 'shared/new_project_item_select', path: 'issues/new', label: "New issue", type: :issues, with_feature_enabled: 'issues', with_shared: false, include_projects_in_subgroups: true
= render 'shared/issuable/search_bar', type: :issues
- if @can_bulk_update
= render_if_exists 'shared/issuable/group_bulk_update_sidebar', group: @group, type: :issues
= render 'shared/issues'
......@@ -2,14 +2,14 @@ import $ from 'jquery';
import MockAdaptor from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import IssuableIndex from '~/issuable_index';
import issuableInitBulkUpdateSidebar from '~/issuable_init_bulk_update_sidebar';
describe('Issuable', () => {
let Issuable;
describe('initBulkUpdate', () => {
it('should not set bulkUpdateSidebar', () => {
Issuable = new IssuableIndex('issue_');
new IssuableIndex('issue_'); // eslint-disable-line no-new
expect(Issuable.bulkUpdateSidebar).not.toBeDefined();
expect(issuableInitBulkUpdateSidebar.bulkUpdateSidebar).toBeNull();
});
it('should set bulkUpdateSidebar', () => {
......@@ -17,9 +17,9 @@ describe('Issuable', () => {
element.classList.add('issues-bulk-update');
document.body.appendChild(element);
Issuable = new IssuableIndex('issue_');
new IssuableIndex('issue_'); // eslint-disable-line no-new
expect(Issuable.bulkUpdateSidebar).toBeDefined();
expect(issuableInitBulkUpdateSidebar.bulkUpdateSidebar).toBeDefined();
});
});
......@@ -36,7 +36,7 @@ describe('Issuable', () => {
input.setAttribute('id', 'issuable_email');
document.body.appendChild(input);
Issuable = new IssuableIndex('issue_');
new IssuableIndex('issue_'); // eslint-disable-line no-new
mock = new MockAdaptor(axios);
......
......@@ -11,9 +11,27 @@ describe Issuable::BulkUpdateService do
.reverse_merge(issuable_ids: Array(issuables).map(&:id).join(','))
type = Array(issuables).first.model_name.param_key
Issuable::BulkUpdateService.new(project, user, bulk_update_params).execute(type)
Issuable::BulkUpdateService.new(user, bulk_update_params).execute(type)
end
shared_examples 'updates milestones' do
it 'succeeds' do
result = bulk_update(issues, milestone_id: milestone.id)
expect(result[:success]).to be_truthy
expect(result[:count]).to eq(issues.count)
end
it 'updates the issues milestone' do
bulk_update(issues, milestone_id: milestone.id)
issues.each do |issue|
expect(issue.reload.milestone).to eq(milestone)
end
end
end
context 'with project issues' do
describe 'close issues' do
let(:issues) { create_list(:issue, 2, project: project) }
......@@ -153,20 +171,10 @@ describe Issuable::BulkUpdateService do
end
describe 'updating milestones' do
let(:issue) { create(:issue, project: project) }
let(:issues) { [create(:issue, project: project)] }
let(:milestone) { create(:milestone, project: project) }
it 'succeeds' do
result = bulk_update(issue, milestone_id: milestone.id)
expect(result[:success]).to be_truthy
expect(result[:count]).to eq(1)
end
it 'updates the issue milestone' do
expect { bulk_update(issue, milestone_id: milestone.id) }
.to change { issue.reload.milestone }.from(nil).to(milestone)
end
it_behaves_like 'updates milestones'
end
describe 'updating labels' do
......@@ -350,4 +358,24 @@ describe Issuable::BulkUpdateService do
end
end
end
end
context 'with group issues' do
let(:group) { create(:group) }
context 'updating milestone' do
let(:milestone) { create(:milestone, group: group) }
let(:project1) { create(:project, :repository, group: group) }
let(:project2) { create(:project, :repository, group: group) }
let(:issue1) { create(:issue, project: project1) }
let(:issue2) { create(:issue, project: project2) }
let(:issues) { [issue1, issue2] }
before do
group.add_maintainer(user)
end
it_behaves_like 'updates milestones'
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