Commit ec4105ab authored by Felipe Artur's avatar Felipe Artur

Show issues of subgroups in group-level issue board

parent 55a0095b
...@@ -61,10 +61,6 @@ gl.issueBoards.BoardSidebar = Vue.extend({ ...@@ -61,10 +61,6 @@ gl.issueBoards.BoardSidebar = Vue.extend({
this.issue = this.detail.issue; this.issue = this.detail.issue;
this.list = this.detail.list; this.list = this.detail.list;
this.$nextTick(() => {
this.endpoint = this.$refs.assigneeDropdown.dataset.issueUpdate;
});
}, },
deep: true deep: true
}, },
...@@ -92,7 +88,7 @@ gl.issueBoards.BoardSidebar = Vue.extend({ ...@@ -92,7 +88,7 @@ gl.issueBoards.BoardSidebar = Vue.extend({
saveAssignees () { saveAssignees () {
this.loadingAssignees = true; this.loadingAssignees = true;
gl.issueBoards.BoardsStore.detail.issue.update(this.endpoint) gl.issueBoards.BoardsStore.detail.issue.update()
.then(() => { .then(() => {
this.loadingAssignees = false; this.loadingAssignees = false;
}) })
......
...@@ -70,15 +70,6 @@ gl.issueBoards.IssueCardInner = Vue.extend({ ...@@ -70,15 +70,6 @@ gl.issueBoards.IssueCardInner = Vue.extend({
return this.issue.assignees.length > this.numberOverLimit; return this.issue.assignees.length > this.numberOverLimit;
}, },
cardUrl() {
let baseUrl = this.issueLinkBase;
if (this.groupId && this.issue.project) {
baseUrl = this.issueLinkBase.replace(':project_path', this.issue.project.path);
}
return `${baseUrl}/${this.issue.iid}`;
},
issueId() { issueId() {
if (this.issue.iid) { if (this.issue.iid) {
return `#${this.issue.iid}`; return `#${this.issue.iid}`;
...@@ -155,13 +146,13 @@ gl.issueBoards.IssueCardInner = Vue.extend({ ...@@ -155,13 +146,13 @@ gl.issueBoards.IssueCardInner = Vue.extend({
/> />
<a <a
class="js-no-trigger" class="js-no-trigger"
:href="cardUrl" :href="issue.path"
:title="issue.title">{{ issue.title }}</a> :title="issue.title">{{ issue.title }}</a>
<span <span
class="card-number" class="card-number"
v-if="issueId" v-if="issueId"
> >
<template v-if="groupId && issue.project">{{issue.project.path}}</template>{{ issueId }} {{ issue.referencePath }}
</span> </span>
<issue-card-weight <issue-card-weight
v-if="issue.weight" v-if="issue.weight"
......
...@@ -17,14 +17,10 @@ gl.issueBoards.RemoveIssueBtn = Vue.extend({ ...@@ -17,14 +17,10 @@ gl.issueBoards.RemoveIssueBtn = Vue.extend({
type: Object, type: Object,
required: true, required: true,
}, },
issueUpdate: {
type: String,
required: true,
},
}, },
computed: { computed: {
updateUrl() { updateUrl() {
return this.issueUpdate.replace(':project_path', this.issue.project.path); return this.issue.path;
}, },
}, },
methods: { methods: {
......
...@@ -8,6 +8,7 @@ export default class FilteredSearchBoards extends FilteredSearchManager { ...@@ -8,6 +8,7 @@ export default class FilteredSearchBoards extends FilteredSearchManager {
super({ super({
page: 'boards', page: 'boards',
isGroup: true, isGroup: true,
isGroupDecendent: true,
filteredSearchTokenKeys: FilteredSearchTokenKeysIssues, filteredSearchTokenKeys: FilteredSearchTokenKeysIssues,
stateFiltersSelector: '.issues-state-filters', stateFiltersSelector: '.issues-state-filters',
}); });
......
...@@ -26,6 +26,8 @@ class ListIssue { ...@@ -26,6 +26,8 @@ class ListIssue {
weight: false, weight: false,
}; };
this.sidebarInfoEndpoint = obj.issue_sidebar_endpoint; this.sidebarInfoEndpoint = obj.issue_sidebar_endpoint;
this.referencePath = obj.reference_path;
this.path = obj.real_path;
this.toggleSubscriptionEndpoint = obj.toggle_subscription_endpoint; this.toggleSubscriptionEndpoint = obj.toggle_subscription_endpoint;
this.milestone_id = obj.milestone_id; this.milestone_id = obj.milestone_id;
this.project_id = obj.project_id; this.project_id = obj.project_id;
...@@ -102,7 +104,7 @@ class ListIssue { ...@@ -102,7 +104,7 @@ class ListIssue {
this.isLoading[key] = value; this.isLoading[key] = value;
} }
update (url) { update () {
const data = { const data = {
issue: { issue: {
milestone_id: this.milestone ? this.milestone.id : null, milestone_id: this.milestone ? this.milestone.id : null,
...@@ -117,7 +119,7 @@ class ListIssue { ...@@ -117,7 +119,7 @@ class ListIssue {
} }
const projectPath = this.project ? this.project.path : ''; const projectPath = this.project ? this.project.path : '';
return Vue.http.patch(url.replace(':project_path', projectPath), data); return Vue.http.patch(this.path + '.json', data);
} }
} }
......
...@@ -96,7 +96,8 @@ module Boards ...@@ -96,7 +96,8 @@ module Boards
resource.as_json( resource.as_json(
only: [:id, :iid, :project_id, :title, :confidential, :due_date, :relative_position, :weight], only: [:id, :iid, :project_id, :title, :confidential, :due_date, :relative_position, :weight],
labels: true, labels: true,
sidebar_endpoints: true, issue_endpoints: true,
include_full_project_path: board.group_board?,
include: { include: {
project: { only: [:id, :path] }, project: { only: [:id, :path] },
assignees: { only: [:id, :name, :username], methods: [:avatar_url] }, assignees: { only: [:id, :name, :username], methods: [:avatar_url] },
......
...@@ -12,7 +12,7 @@ class Groups::MilestonesController < Groups::ApplicationController ...@@ -12,7 +12,7 @@ class Groups::MilestonesController < Groups::ApplicationController
@milestones = Kaminari.paginate_array(milestones).page(params[:page]) @milestones = Kaminari.paginate_array(milestones).page(params[:page])
end end
format.json do format.json do
render json: milestones.map { |m| m.for_display.slice(:title, :name, :id) } render json: milestones.map { |m| m.for_display.slice(:id, :title, :name) }
end end
end end
end end
......
...@@ -296,11 +296,17 @@ class Issue < ActiveRecord::Base ...@@ -296,11 +296,17 @@ class Issue < ActiveRecord::Base
def as_json(options = {}) def as_json(options = {})
super(options).tap do |json| super(options).tap do |json|
if options.key?(:sidebar_endpoints) && project if options.key?(:issue_endpoints) && project
url_helper = Gitlab::Routing.url_helpers url_helper = Gitlab::Routing.url_helpers
json.merge!(issue_sidebar_endpoint: url_helper.project_issue_path(project, self, format: :json, serializer: 'sidebar'), issue_reference = options[:include_full_project_path] ? to_reference(full: true) : to_reference
toggle_subscription_endpoint: url_helper.toggle_subscription_project_issue_path(project, self))
json.merge!(
reference_path: issue_reference,
real_path: url_helper.project_issue_path(project, self),
issue_sidebar_endpoint: url_helper.project_issue_path(project, self, format: :json, serializer: 'sidebar'),
toggle_subscription_endpoint: url_helper.toggle_subscription_project_issue_path(project, self)
)
end end
if options.key?(:labels) if options.key?(:labels)
......
...@@ -37,6 +37,8 @@ module Boards ...@@ -37,6 +37,8 @@ module Boards
def filter_params def filter_params
set_parent set_parent
set_state set_state
set_scope
params params
end end
...@@ -52,6 +54,10 @@ module Boards ...@@ -52,6 +54,10 @@ module Boards
params[:state] = list && list.closed? ? 'closed' : 'opened' params[:state] = list && list.closed? ? 'closed' : 'opened'
end end
def set_scope
params[:include_subgroups] = true if board.group_board?
end
def board_label_ids def board_label_ids
@board_label_ids ||= board.lists.movable.pluck(:label_id) @board_label_ids ||= board.lists.movable.pluck(:label_id)
end end
......
...@@ -53,9 +53,10 @@ class IssuableBaseService < BaseService ...@@ -53,9 +53,10 @@ class IssuableBaseService < BaseService
return unless milestone_id return unless milestone_id
params[:milestone_id] = '' if milestone_id == IssuableFinder::NONE params[:milestone_id] = '' if milestone_id == IssuableFinder::NONE
group_ids = project.group&.self_and_ancestors&.pluck(:id)
milestone = milestone =
Milestone.for_projects_and_groups([project.id], [project.group&.id]).find_by_id(milestone_id) Milestone.for_projects_and_groups([project.id], group_ids).find_by_id(milestone_id)
params[:milestone_id] = '' unless milestone params[:milestone_id] = '' unless milestone
end end
......
...@@ -26,6 +26,6 @@ ...@@ -26,6 +26,6 @@
= render "shared/boards/components/sidebar/weight" = render "shared/boards/components/sidebar/weight"
= render "shared/boards/components/sidebar/notifications" = render "shared/boards/components/sidebar/notifications"
%remove-btn{ ":issue" => "issue", %remove-btn{ ":issue" => "issue",
":issue-update" => "'#{build_issue_link_base}/' + issue.iid + '.json'", ":issue-update" => "issue.sidebarInfoEndpoint",
":list" => "list", ":list" => "list",
"v-if" => "canRemove" } "v-if" => "canRemove" }
...@@ -21,8 +21,7 @@ ...@@ -21,8 +21,7 @@
.dropdown .dropdown
- dropdown_options = issue_assignees_dropdown_options - dropdown_options = issue_assignees_dropdown_options
%button.dropdown-menu-toggle.js-user-search.js-author-search.js-multiselect.js-save-user-data.js-issue-board-sidebar{ type: 'button', ref: 'assigneeDropdown', data: board_sidebar_user_data, %button.dropdown-menu-toggle.js-user-search.js-author-search.js-multiselect.js-save-user-data.js-issue-board-sidebar{ type: 'button', ref: 'assigneeDropdown', data: board_sidebar_user_data,
":data-issuable-id" => "issue.iid", ":data-issuable-id" => "issue.iid" }
":data-issue-update" => "'#{build_issue_link_base}/' + issue.iid + '.json'" }
= dropdown_options[:title] = dropdown_options[:title]
= icon("chevron-down") = icon("chevron-down")
.dropdown-menu.dropdown-select.dropdown-menu-user.dropdown-menu-selectable.dropdown-menu-author .dropdown-menu.dropdown-select.dropdown-menu-user.dropdown-menu-selectable.dropdown-menu-author
......
...@@ -22,8 +22,7 @@ ...@@ -22,8 +22,7 @@
":value" => "issue.dueDate" } ":value" => "issue.dueDate" }
.dropdown .dropdown
%button.dropdown-menu-toggle.js-due-date-select.js-issue-boards-due-date{ type: 'button', %button.dropdown-menu-toggle.js-due-date-select.js-issue-boards-due-date{ type: 'button',
data: { toggle: 'dropdown', field_name: "issue[due_date]", ability_name: "issue" }, data: { toggle: 'dropdown', field_name: "issue[due_date]", ability_name: "issue" }}
":data-issue-update" => "'#{build_issue_link_base}/' + issue.iid + '.json'" }
%span.dropdown-toggle-text Due date %span.dropdown-toggle-text Due date
= icon('chevron-down') = icon('chevron-down')
.dropdown-menu.dropdown-menu-due-date .dropdown-menu.dropdown-menu-due-date
......
...@@ -26,8 +26,7 @@ ...@@ -26,8 +26,7 @@
project_id: @project&.try(:id), project_id: @project&.try(:id),
labels: labels_filter_path(false), labels: labels_filter_path(false),
namespace_path: @namespace_path, namespace_path: @namespace_path,
project_path: @project.try(:path) }, project_path: @project.try(:path) }}
":data-issue-update" => "'#{build_issue_link_base}/' + issue.iid + '.json'" }
%span.dropdown-toggle-text %span.dropdown-toggle-text
Label Label
= icon('chevron-down') = icon('chevron-down')
......
...@@ -18,8 +18,7 @@ ...@@ -18,8 +18,7 @@
.dropdown .dropdown
%button.dropdown-menu-toggle.js-milestone-select.js-issue-board-sidebar{ type: "button", data: { toggle: "dropdown", show_no: "true", field_name: "issue[milestone_id]", milestones: milestones_filter_path(format: :json), ability_name: "issue", use_id: "true", default_no: "true" }, %button.dropdown-menu-toggle.js-milestone-select.js-issue-board-sidebar{ type: "button", data: { toggle: "dropdown", show_no: "true", field_name: "issue[milestone_id]", milestones: milestones_filter_path(format: :json), ability_name: "issue", use_id: "true", default_no: "true" },
":data-selected" => "milestoneTitle", ":data-selected" => "milestoneTitle",
":data-issuable-id" => "issue.iid", ":data-issuable-id" => "issue.iid" }
":data-issue-update" => "'#{build_issue_link_base}/' + issue.iid + '.json'" }
Milestone Milestone
= icon("chevron-down") = icon("chevron-down")
.dropdown-menu.dropdown-select.dropdown-menu-selectable .dropdown-menu.dropdown-select.dropdown-menu-selectable
......
---
title: Show issues of subgroups in group-level issue board
merge_request:
author:
type: changed
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
Delete board Delete board
%board-form{ ":milestone-path" => "milestonePath", %board-form{ ":milestone-path" => "milestonePath",
"labels-path" => labels_filter_path(true), "labels-path" => labels_filter_path(true, include_descendant_groups: true),
":project-id" => "Number(#{@project&.id})", ":project-id" => "Number(#{@project&.id})",
":group-id" => "Number(#{@group&.id})", ":group-id" => "Number(#{@group&.id})",
":can-admin-board" => can?(current_user, :admin_board, parent), ":can-admin-board" => can?(current_user, :admin_board, parent),
......
...@@ -48,10 +48,8 @@ describe Boards::Issues::ListService do ...@@ -48,10 +48,8 @@ describe Boards::Issues::ListService do
context 'when parent is a group' do context 'when parent is a group' do
let(:user) { create(:user) } let(:user) { create(:user) }
let(:group) { create(:group) }
let(:project) { create(:project, :empty_repo, namespace: group) } let(:project) { create(:project, :empty_repo, namespace: group) }
let(:project1) { create(:project, :empty_repo, namespace: group) } let(:project1) { create(:project, :empty_repo, namespace: group) }
let(:board) { create(:board, group: group) }
let(:m1) { create(:milestone, group: group) } let(:m1) { create(:milestone, group: group) }
let(:m2) { create(:milestone, group: group) } let(:m2) { create(:milestone, group: group) }
...@@ -92,13 +90,30 @@ describe Boards::Issues::ListService do ...@@ -92,13 +90,30 @@ describe Boards::Issues::ListService do
let!(:closed_issue4) { create(:labeled_issue, :closed, project: project1, labels: [p1, p1_project1]) } let!(:closed_issue4) { create(:labeled_issue, :closed, project: project1, labels: [p1, p1_project1]) }
let!(:closed_issue5) { create(:labeled_issue, :closed, project: project1, labels: [development]) } let!(:closed_issue5) { create(:labeled_issue, :closed, project: project1, labels: [development]) }
before do
group.add_developer(user)
end
context 'and group has no parent' do
let(:parent) { group } let(:parent) { group }
let(:group) { create(:group) }
let(:board) { create(:board, group: group) }
it_behaves_like 'issues list service'
end
context 'and group is an ancestor' do
let(:parent) { create(:group) }
let(:group) { create(:group, parent: parent) }
let!(:backlog) { create(:backlog_list, board: board) }
let(:board) { create(:board, group: parent) }
before do before do
group.add_developer(user) parent.add_developer(user)
end end
it_behaves_like 'issues list service' it_behaves_like 'issues list service'
end end
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