Commit 5b893e91 authored by Simon Knox's avatar Simon Knox Committed by Ezekiel Kigbo

Add checkbox to scope board to current iteration

Add some basic feature specs
parent 5e154e44
......@@ -83,6 +83,10 @@ export function fullBoardId(boardId) {
return `gid://gitlab/Board/${boardId}`;
}
export function fullIterationId(id) {
return `gid://gitlab/Iteration/${id}`;
}
export function fullLabelId(label) {
if (label.project_id !== null) {
return `gid://gitlab/ProjectLabel/${label.id}`;
......@@ -141,6 +145,7 @@ export default {
formatListIssues,
fullBoardId,
fullLabelId,
fullIterationId,
getBoardsPath,
isListDraggable,
};
......@@ -15,6 +15,7 @@ const boardDefaults = {
name: '',
labels: [],
milestone_id: undefined,
iteration_id: undefined,
assignee: {},
assignee_id: undefined,
weight: null,
......@@ -171,6 +172,9 @@ export default {
}
},
methods: {
setIteration(iterationId) {
this.board.iteration_id = iterationId;
},
callBoardMutation(id) {
return this.$apollo.mutate({
mutation: createBoardMutation,
......@@ -289,6 +293,7 @@ export default {
:project-id="projectId"
:group-id="groupId"
:weights="weights"
@set-iteration="setIteration"
/>
</form>
</gl-modal>
......
mutation UpdateBoard($id: ID!, $hideClosedList: Boolean, $hideBacklogList: Boolean) {
mutation UpdateBoard($id: BoardID!, $hideClosedList: Boolean, $hideBacklogList: Boolean) {
updateBoard(
input: { id: $id, hideClosedList: $hideClosedList, hideBacklogList: $hideBacklogList }
) {
......
......@@ -4,7 +4,7 @@ group: Project Management
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
# Issue Boards
# Issue Boards **(CORE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5554) in [GitLab 8.11](https://about.gitlab.com/releases/2016/08/22/gitlab-8-11-released/#issue-board).
......@@ -233,17 +233,18 @@ advanced functionality is present in [higher tiers only](https://about.gitlab.co
### Configurable issue boards **(STARTER)**
> [Introduced](https://about.gitlab.com/releases/2017/11/22/gitlab-10-2-released/#issue-boards-configuration) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.2.
> - [Introduced](https://about.gitlab.com/releases/2017/11/22/gitlab-10-2-released/#issue-boards-configuration) in GitLab 10.2.
> - Setting current iteration as scope [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/196804) in GitLab 13.7.
An issue board can be associated with a GitLab [Milestone](milestones/index.md#milestones),
[Labels](labels.md), Assignee and Weight
An issue board can be associated with a [milestone](milestones/index.md#milestones),
[labels](labels.md), assignee, weight, and current [iteration](../group/iterations/index.md),
which automatically filter the board issues accordingly.
This allows you to create unique boards according to your team's need.
![Create scoped board](img/issue_board_creation_v13_6.png)
You can define the scope of your board when creating it or by clicking the **Edit board** button.
After a milestone, assignee or weight is assigned to an issue board, you can no longer
After a milestone, iteration, assignee, or weight is assigned to an issue board, you can no longer
filter through these in the search bar. In order to do that, you need to remove the desired scope
(for example, milestone, assignee, or weight) from the issue board.
......
......@@ -2,15 +2,17 @@
import { __ } from '~/locale';
import ListLabel from '~/boards/models/label';
import BoardLabelsSelect from '~/vue_shared/components/sidebar/labels_select/base.vue';
import AssigneeSelect from './assignee_select.vue';
import BoardMilestoneSelect from './milestone_select.vue';
import BoardScopeCurrentIteration from './board_scope_current_iteration.vue';
import BoardWeightSelect from './weight_select.vue';
import AssigneeSelect from './assignee_select.vue';
export default {
components: {
AssigneeSelect,
BoardLabelsSelect,
BoardMilestoneSelect,
BoardScopeCurrentIteration,
BoardWeightSelect,
},
......@@ -111,6 +113,12 @@ export default {
:can-edit="canAdminBoard"
/>
<board-scope-current-iteration
:can-admin-board="canAdminBoard"
:iteration-id="board.iteration_id"
@set-iteration="$emit('set-iteration', $event)"
/>
<board-labels-select
:context="board"
:labels-path="labelsPath"
......
<script>
import { GlFormCheckbox } from '@gitlab/ui';
import { __ } from '~/locale';
import { IterationIDs } from '../constants';
export default {
i18n: {
label: __('Scope board to current iteration'),
title: __('Iteration'),
},
components: {
GlFormCheckbox,
},
props: {
canAdminBoard: {
type: Boolean,
required: true,
},
iterationId: {
type: Number,
required: false,
default: 0,
},
},
data() {
return {
checked: this.iterationId === IterationIDs.CURRENT,
};
},
methods: {
handleToggle() {
this.checked = !this.checked;
const iterationId = this.checked ? IterationIDs.CURRENT : null;
this.$emit('set-iteration', iterationId);
},
},
};
</script>
<template>
<div class="block iteration">
<div class="title gl-mb-3">
{{ $options.i18n.title }}
</div>
<gl-form-checkbox
:disabled="!canAdminBoard"
:checked="checked"
class="gl-text-gray-500"
data-testid="scope-to-current-iteration"
@change="handleToggle"
>{{ $options.i18n.label }}
</gl-form-checkbox>
</div>
</template>
......@@ -14,6 +14,7 @@ export const IterationFilterType = {
export const IterationIDs = {
NONE: 0,
CURRENT: -4,
};
export const MilestoneFilterType = {
......
......@@ -5,6 +5,7 @@ module EE
prepended do
expose :milestone_id
expose :iteration_id
expose :weight
expose :label_ids
expose :milestone, using: BoardMilestoneEntity
......
---
title: Add current iteration toggle to board config
merge_request: 46514
author:
type: added
......@@ -271,6 +271,30 @@ RSpec.describe 'Scoped issue boards', :js do
end
end
context 'iteration' do
context 'board not scoped to iteration' do
it 'sets board to current iteration' do
expect(page).to have_selector('.board-card', count: 3)
update_board_scope('current_iteration', true)
expect(page).to have_selector('.board-card', count: 0)
end
end
context 'board scoped to current iteration' do
it 'removes current iteration from board' do
create_board_scope('current_iteration', true)
expect(page).to have_selector('.board-card', count: 0)
update_board_scope('current_iteration', false)
expect(page).to have_selector('.board-card', count: 3)
end
end
end
context 'labels' do
let!(:label_1) { create(:label, project: project, name: 'Label 1') }
let!(:label_2) { create(:label, project: project, name: 'Label 2') }
......@@ -526,6 +550,26 @@ RSpec.describe 'Scoped issue boards', :js do
click_button 'Expand'
click_value(filter, value)
click_on_board_modal
click_button 'Create board'
wait_for_requests
expect(page).not_to have_selector('.board-list-loading')
end
def click_value(filter, value)
if filter == 'current_iteration'
current_iteration_checkbox = 'Scope board to current iteration'
if value
check(current_iteration_checkbox)
else
uncheck(current_iteration_checkbox)
end
else
page.within(".#{filter}") do
click_button 'Edit'
......@@ -539,14 +583,7 @@ RSpec.describe 'Scoped issue boards', :js do
click_link value
end
end
click_on_board_modal
click_button 'Create board'
wait_for_requests
expect(page).not_to have_selector('.board-list-loading')
end
end
def click_on_create_new_board
......@@ -561,13 +598,7 @@ RSpec.describe 'Scoped issue boards', :js do
def update_board_scope(filter, value)
edit_board.click
page.within(".#{filter}") do
click_button 'Edit'
page.within(".dropdown-menu") do
filter == 'weight' ? click_button(value) : click_link(value)
end
end
click_value(filter, value)
click_on_board_modal
......
......@@ -24208,6 +24208,9 @@ msgstr ""
msgid "Scope"
msgstr ""
msgid "Scope board to current iteration"
msgstr ""
msgid "Scopes"
msgstr ""
......
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