Commit f6793a80 authored by Sean McGivern's avatar Sean McGivern

Merge branch 'add-board-scope-highlight' into 'master'

Add board scope highlight

Closes #4067

See merge request gitlab-org/gitlab-ee!3499
parents c55155b3 b9dea9ca
......@@ -25,11 +25,11 @@ import './components/board_sidebar';
import './components/new_list_dropdown';
import './components/modal/index';
import '../vue_shared/vue_resource_interceptor';
import { convertPermissionToBoolean } from '../lib/utils/common_utils';
import './components/boards_selector';
import collapseIcon from './icons/fullscreen_collapse.svg';
import expandIcon from './icons/fullscreen_expand.svg';
import tooltip from '../vue_shared/directives/tooltip';
Vue.use(VueResource);
......@@ -212,11 +212,14 @@ $(() => {
el: configEl,
data() {
return {
canAdminList: convertPermissionToBoolean(
this.$options.el.dataset.canAdminList,
),
canAdminList: this.$options.el.hasAttribute('data-can-admin-list'),
hasScope: this.$options.el.hasAttribute('data-has-scope'),
state: Store.state,
};
},
directives: {
tooltip,
},
methods: {
showPage: page => gl.issueBoards.BoardsStore.showPage(page),
},
......@@ -224,11 +227,17 @@ $(() => {
buttonText() {
return this.canAdminList ? 'Edit board' : 'View scope';
},
tooltipTitle() {
return this.hasScope ? __('This board\'s scope is reduced') : '';
}
},
template: `
<div class="prepend-left-10">
<button
v-tooltip
:title="tooltipTitle"
class="btn btn-inverted"
:class="{ 'dot-highlight': hasScope }"
type="button"
@click.prevent="showPage('edit')"
>
......@@ -247,12 +256,8 @@ $(() => {
modal: ModalStore.store,
store: Store.state,
isFullscreen: false,
focusModeAvailable: convertPermissionToBoolean(
$boardApp.dataset.focusModeAvailable,
),
canAdminList: this.$options.el && convertPermissionToBoolean(
this.$options.el.dataset.canAdminList,
),
focusModeAvailable: $boardApp.hasAttribute('data-focus-mode-available'),
canAdminList: this.$options.el.hasAttribute('data-can-admin-list'),
};
},
watch: {
......@@ -320,7 +325,7 @@ $(() => {
modal: ModalStore.store,
store: Store.state,
isFullscreen: false,
focusModeAvailable: convertPermissionToBoolean($boardApp.dataset.focusModeAvailable),
focusModeAvailable: $boardApp.hasAttribute('data-focus-mode-available'),
},
methods: {
toggleFocusMode() {
......
......@@ -243,6 +243,16 @@
}
}
&.dot-highlight::after {
content: '';
background-color: $blue-500;
width: $gl-padding * 0.5;
height: $gl-padding * 0.5;
display: inline-block;
border-radius: 50%;
margin-left: 3px;
}
svg {
height: 15px;
width: 15px;
......
......@@ -125,7 +125,7 @@
- if type == :boards
- user_can_admin_list = can?(current_user, :admin_list, board.parent)
.js-board-config{ data: { can_admin_list: user_can_admin_list.to_s } }
.js-board-config{ data: { can_admin_list: user_can_admin_list, has_scope: board.scoped? } }
- if user_can_admin_list
.dropdown.prepend-left-10#js-add-list
%button.btn.btn-create.btn-inverted.js-new-board-list{ type: "button", data: board_list_data }
......@@ -136,7 +136,7 @@
= render partial: "shared/issuable/label_page_create"
= dropdown_loading
- if @project
#js-add-issues-btn.prepend-left-10{ data: { can_admin_list: can?(current_user, :admin_list, @project).to_s } }
#js-add-issues-btn.prepend-left-10{ data: { can_admin_list: can?(current_user, :admin_list, @project) } }
#js-toggle-focus-btn.prepend-left-10
- elsif type != :boards_modal
= render 'shared/sort_dropdown'
......@@ -81,13 +81,8 @@ class BoardsStoreEE {
this.store.updateFiltersUrl(true);
}
shouldAddPromotionState() {
// Decide whether to add the promotion state
return this.$boardApp.dataset.showPromotion === 'true';
}
addPromotion() {
if (!this.shouldAddPromotionState() || this.promotionIsHidden() || this.store.disabled) return;
if (!this.$boardApp.hasAttribute('data-show-promotion') || this.promotionIsHidden() || this.store.disabled) return;
this.store.addList({
id: 'promotion',
......
......@@ -8,7 +8,7 @@ module EE
show_feature_promotion = (@project && show_promotions? &&
(!@project.feature_available?(:multiple_issue_boards) ||
!@project.feature_available?(:scoped_issue_board) ||
!@project.feature_available?(:issue_board_focus_mode))).to_s
!@project.feature_available?(:issue_board_focus_mode)))
data = {
board_milestone_title: board.milestone&.name,
......@@ -17,7 +17,7 @@ module EE
label_ids: board.label_ids,
labels: board.labels.to_json(only: [:id, :title, :color, :text_color] ),
board_weight: board.weight,
focus_mode_available: parent.feature_available?(:issue_board_focus_mode).to_s,
focus_mode_available: parent.feature_available?(:issue_board_focus_mode),
show_promotion: show_feature_promotion
}
......
......@@ -2,6 +2,9 @@ module EE
module Board
extend ActiveSupport::Concern
# Empty state for milestones and weights.
EMPTY_SCOPE_STATE = [nil, -1].freeze
prepended do
belongs_to :group
belongs_to :milestone
......@@ -45,6 +48,15 @@ module EE
end
end
def scoped?
return false unless parent.feature_available?(:scoped_issue_board)
EMPTY_SCOPE_STATE.exclude?(milestone_id) ||
EMPTY_SCOPE_STATE.exclude?(weight) ||
labels.any? ||
assignee.present?
end
def as_json(options = {})
milestone_attrs = options.fetch(:include, {})
.extract!(:milestone)
......
......@@ -53,6 +53,12 @@ describe 'Scoped issue boards', :js do
expect(find('.tokens-container')).to have_content("")
expect(page).to have_selector('.card', count: 3)
end
it 'displays dot highlight and tooltip' do
create_board_milestone(milestone.title)
expect_dot_highlight('Edit board')
end
end
context 'labels' do
......@@ -101,6 +107,12 @@ describe 'Scoped issue boards', :js do
end
end
end
it 'displays dot highlight and tooltip' do
create_board_label(label_1.title)
expect_dot_highlight('Edit board')
end
end
context 'assignee' do
......@@ -126,6 +138,12 @@ describe 'Scoped issue boards', :js do
expect(page).not_to have_css('.js-visual-token')
expect(page).to have_selector('.card', count: 3)
end
it 'displays dot highlight and tooltip' do
create_board_assignee(user.name)
expect_dot_highlight('Edit board')
end
end
context 'weight' do
......@@ -151,6 +169,12 @@ describe 'Scoped issue boards', :js do
expect(page).to have_selector('.card', count: 4)
end
it 'displays dot highlight and tooltip' do
create_board_weight(1)
expect_dot_highlight('Edit board')
end
end
end
......@@ -381,6 +405,10 @@ describe 'Scoped issue boards', :js do
expect(page).not_to have_button('Cancel')
end
end
it 'does not display dot highlight and tooltip' do
expect_no_dot_highlight('View scope')
end
end
context 'with scoped_issue_boards feature disabled' do
......@@ -394,6 +422,10 @@ describe 'Scoped issue boards', :js do
wait_for_requests
end
it 'does not display dot highlight and tooltip' do
expect_no_dot_highlight('Edit board')
end
it "doesn't show the input when creating a board" do
page.within '#js-multiple-boards-switcher' do
find('.dropdown-menu-toggle').click
......@@ -412,6 +444,20 @@ describe 'Scoped issue boards', :js do
end
end
def expect_dot_highlight(button_title)
button = first('.filter-dropdown-container .btn.btn-inverted')
expect(button.text).to include(button_title)
expect(button[:class]).to include('dot-highlight')
expect(button['data-original-title']).to include('This board\'s scope is reduced')
end
def expect_no_dot_highlight(button_title)
button = first('.filter-dropdown-container .btn.btn-inverted')
expect(button.text).to include(button_title)
expect(button[:class]).not_to include('dot-highlight')
expect(button['data-original-title']).not_to include('This board\'s scope is reduced')
end
# Create board helper methods
#
def create_board_milestone(milestone_title)
......
......@@ -61,4 +61,49 @@ describe Board do
expect(board.milestone).to be_nil
end
end
describe '#scoped?' do
before do
stub_licensed_features(scoped_issue_board: true)
end
it 'returns true when milestone is not nil AND is not "Any milestone"' do
milestone = create(:milestone)
board = create(:board, milestone: milestone, weight: nil, labels: [], assignee: nil)
expect(board).to be_scoped
end
it 'returns true when weight is not nil AND is not "Any weight"' do
board = create(:board, milestone: nil, weight: 2, labels: [], assignee: nil)
expect(board).to be_scoped
end
it 'returns true when any label exists' do
board = create(:board, milestone: nil, weight: nil, assignee: nil)
board.labels.create!(title: 'foo')
expect(board).to be_scoped
end
it 'returns true when assignee is present' do
user = create(:user)
board = create(:board, milestone: nil, weight: nil, labels: [], assignee: user)
expect(board).to be_scoped
end
it 'returns false when feature is not available' do
stub_licensed_features(scoped_issue_board: false)
expect(board).not_to be_scoped
end
it 'returns false when board is not scoped' do
board = create(:board, milestone_id: -1, weight: -1, labels: [], assignee: nil)
expect(board).not_to be_scoped
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