Commit 47dfc12f authored by Florie Guibert's avatar Florie Guibert Committed by Vitaly Slobodin

Removing some vale exclusions

In some cases, we can use backticks, or refactor
in other ways to avoid the vale warnings.
parent c126034b
...@@ -34,16 +34,26 @@ module BoardsActions ...@@ -34,16 +34,26 @@ module BoardsActions
def boards def boards
strong_memoize(:boards) do strong_memoize(:boards) do
Boards::ListService.new(parent, current_user).execute existing_boards = boards_finder.execute
if existing_boards.any?
existing_boards
else
# if no board exists, create one
[board_create_service.execute.payload]
end
end end
end end
def board def board
strong_memoize(:board) do strong_memoize(:board) do
boards.find(params[:id]) board_finder.execute.first
end end
end end
def board_type
board_klass.to_type
end
def serializer def serializer
BoardSerializer.new(current_user: current_user) BoardSerializer.new(current_user: current_user)
end end
......
...@@ -65,6 +65,7 @@ module MultipleBoardsActions ...@@ -65,6 +65,7 @@ module MultipleBoardsActions
private private
def redirect_to_recent_board def redirect_to_recent_board
return unless board_type == Board.to_type
return if request.format.json? || !parent.multiple_issue_boards_available? || !latest_visited_board return if request.format.json? || !parent.multiple_issue_boards_available? || !latest_visited_board
redirect_to board_path(latest_visited_board.board) redirect_to board_path(latest_visited_board.board)
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
class Groups::BoardsController < Groups::ApplicationController class Groups::BoardsController < Groups::ApplicationController
include BoardsActions include BoardsActions
include RecordUserLastActivity include RecordUserLastActivity
include Gitlab::Utils::StrongMemoize
before_action :authorize_read_board!, only: [:index, :show] before_action :authorize_read_board!, only: [:index, :show]
before_action :assign_endpoint_vars before_action :assign_endpoint_vars
...@@ -14,6 +15,28 @@ class Groups::BoardsController < Groups::ApplicationController ...@@ -14,6 +15,28 @@ class Groups::BoardsController < Groups::ApplicationController
private private
def board_klass
Board
end
def boards_finder
strong_memoize :boards_finder do
Boards::ListService.new(parent, current_user)
end
end
def board_finder
strong_memoize :board_finder do
Boards::ListService.new(parent, current_user, board_id: params[:id])
end
end
def board_create_service
strong_memoize :board_create_service do
Boards::CreateService.new(parent, current_user)
end
end
def assign_endpoint_vars def assign_endpoint_vars
@boards_endpoint = group_boards_path(group) @boards_endpoint = group_boards_path(group)
@namespace_path = group.to_param @namespace_path = group.to_param
......
...@@ -15,6 +15,28 @@ class Projects::BoardsController < Projects::ApplicationController ...@@ -15,6 +15,28 @@ class Projects::BoardsController < Projects::ApplicationController
private private
def board_klass
Board
end
def boards_finder
strong_memoize :boards_finder do
Boards::ListService.new(parent, current_user)
end
end
def board_finder
strong_memoize :board_finder do
Boards::ListService.new(parent, current_user, board_id: params[:id])
end
end
def board_create_service
strong_memoize :board_create_service do
Boards::CreateService.new(parent, current_user)
end
end
def assign_endpoint_vars def assign_endpoint_vars
@boards_endpoint = project_boards_path(project) @boards_endpoint = project_boards_path(project)
@bulk_issues_path = bulk_update_project_issues_path(project) @bulk_issues_path = bulk_update_project_issues_path(project)
......
...@@ -13,7 +13,7 @@ module Resolvers ...@@ -13,7 +13,7 @@ module Resolvers
def resolve(id: nil) def resolve(id: nil)
return unless parent return unless parent
::Boards::ListService.new(parent, context[:current_user], board_id: extract_board_id(id)).execute(create_default_board: false).first ::Boards::ListService.new(parent, context[:current_user], board_id: extract_board_id(id)).execute.first
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
nil nil
end end
......
...@@ -16,7 +16,7 @@ module Resolvers ...@@ -16,7 +16,7 @@ module Resolvers
return Board.none unless parent return Board.none unless parent
::Boards::ListService.new(parent, context[:current_user], board_id: extract_board_id(id)).execute(create_default_board: false) ::Boards::ListService.new(parent, context[:current_user], board_id: extract_board_id(id)).execute
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
Board.none Board.none
end end
......
...@@ -21,7 +21,8 @@ module BoardsHelper ...@@ -21,7 +21,8 @@ module BoardsHelper
group_id: @group&.id, group_id: @group&.id,
labels_filter_base_path: build_issue_link_base, labels_filter_base_path: build_issue_link_base,
labels_fetch_path: labels_fetch_path, labels_fetch_path: labels_fetch_path,
labels_manage_path: labels_manage_path labels_manage_path: labels_manage_path,
board_type: board.to_type
} }
end end
......
...@@ -44,6 +44,14 @@ class Board < ApplicationRecord ...@@ -44,6 +44,14 @@ class Board < ApplicationRecord
def scoped? def scoped?
false false
end end
def self.to_type
name.demodulize
end
def to_type
self.class.to_type
end
end end
Board.prepend_if_ee('EE::Board') Board.prepend_if_ee('EE::Board')
...@@ -2,9 +2,7 @@ ...@@ -2,9 +2,7 @@
module Boards module Boards
class ListService < Boards::BaseService class ListService < Boards::BaseService
def execute(create_default_board: true) def execute
create_board! if create_default_board && parent.boards.empty?
find_boards find_boards
end end
...@@ -18,10 +16,6 @@ module Boards ...@@ -18,10 +16,6 @@ module Boards
parent.boards.first_board parent.boards.first_board
end end
def create_board!
Boards::CreateService.new(parent, current_user).execute
end
def find_boards def find_boards
found = found =
if parent.multiple_issue_boards_available? if parent.multiple_issue_boards_available?
......
...@@ -5,6 +5,7 @@ module Boards ...@@ -5,6 +5,7 @@ module Boards
class CreateService < Boards::BaseService class CreateService < Boards::BaseService
def execute(board) def execute(board)
return unless current_user && Gitlab::Database.read_write? return unless current_user && Gitlab::Database.read_write?
return unless board.is_a?(Board) # other board types do not support board visits yet
if parent.is_a?(Group) if parent.is_a?(Group)
BoardGroupRecentVisit.visited!(current_user, board) BoardGroupRecentVisit.visited!(current_user, board)
......
...@@ -6,7 +6,10 @@ ...@@ -6,7 +6,10 @@
- @no_breadcrumb_container = true - @no_breadcrumb_container = true
- @no_container = true - @no_container = true
- @content_class = "issue-boards-content js-focus-mode-board" - @content_class = "issue-boards-content js-focus-mode-board"
- breadcrumb_title _("Issue Boards") - if board.to_type == "EpicBoard"
- breadcrumb_title _("Epic Boards")
- else
- breadcrumb_title _("Issue Boards")
- page_title("#{board.name}", _("Boards")) - page_title("#{board.name}", _("Boards"))
- add_page_specific_style 'page_bundles/boards' - add_page_specific_style 'page_bundles/boards'
......
// This is a true violation of @gitlab/no-runtime-template-compiler, as it
// relies on app/views/shared/boards/_show.html.haml for its
// template.
/* eslint-disable @gitlab/no-runtime-template-compiler */
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import { mapActions } from 'vuex';
import BoardSidebar from 'ee_component/boards/components/board_sidebar';
import toggleLabels from 'ee_component/boards/toggle_labels';
import BoardContent from '~/boards/components/board_content.vue';
import createDefaultClient from '~/lib/graphql';
import store from '~/boards/stores';
import '~/boards/filters/due_date_filters';
import BoardAddIssuesModal from '~/boards/components/modal/index.vue';
import { NavigationType, parseBoolean } from '~/lib/utils/common_utils';
import mountMultipleBoardsSwitcher from '~/boards/mount_multiple_boards_switcher';
Vue.use(VueApollo);
const apolloProvider = new VueApollo({
defaultClient: createDefaultClient(),
});
export default () => {
const $boardApp = document.getElementById('board-app');
// check for browser back and trigger a hard reload to circumvent browser caching.
window.addEventListener('pageshow', (event) => {
const isNavTypeBackForward =
window.performance && window.performance.navigation.type === NavigationType.TYPE_BACK_FORWARD;
if (event.persisted || isNavTypeBackForward) {
window.location.reload();
}
});
// eslint-disable-next-line no-new
new Vue({
el: $boardApp,
components: {
BoardContent,
BoardSidebar,
BoardAddIssuesModal,
BoardSettingsSidebar: () => import('~/boards/components/board_settings_sidebar.vue'),
},
provide: {
boardId: $boardApp.dataset.boardId,
groupId: parseInt($boardApp.dataset.groupId, 10),
rootPath: $boardApp.dataset.rootPath,
currentUserId: gon.current_user_id || null,
canUpdate: $boardApp.dataset.canUpdate,
labelsFetchPath: $boardApp.dataset.labelsFetchPath,
labelsManagePath: $boardApp.dataset.labelsManagePath,
labelsFilterBasePath: $boardApp.dataset.labelsFilterBasePath,
timeTrackingLimitToHours: parseBoolean($boardApp.dataset.timeTrackingLimitToHours),
weightFeatureAvailable: parseBoolean($boardApp.dataset.weightFeatureAvailable),
boardWeight: $boardApp.dataset.boardWeight
? parseInt($boardApp.dataset.boardWeight, 10)
: null,
scopedLabelsAvailable: parseBoolean($boardApp.dataset.scopedLabels),
},
store,
apolloProvider,
data() {
return {
state: {},
loading: 0,
boardsEndpoint: $boardApp.dataset.boardsEndpoint,
recentBoardsEndpoint: $boardApp.dataset.recentBoardsEndpoint,
listsEndpoint: $boardApp.dataset.listsEndpoint,
disabled: parseBoolean($boardApp.dataset.disabled),
bulkUpdatePath: $boardApp.dataset.bulkUpdatePath,
parent: $boardApp.dataset.parent,
detailIssueVisible: false,
};
},
created() {
this.setInitialBoardData({
boardId: $boardApp.dataset.boardId,
fullPath: $boardApp.dataset.fullPath,
boardType: this.parent,
disabled: this.disabled,
boardConfig: {
milestoneId: parseInt($boardApp.dataset.boardMilestoneId, 10),
milestoneTitle: $boardApp.dataset.boardMilestoneTitle || '',
iterationId: parseInt($boardApp.dataset.boardIterationId, 10),
iterationTitle: $boardApp.dataset.boardIterationTitle || '',
assigneeId: $boardApp.dataset.boardAssigneeId,
assigneeUsername: $boardApp.dataset.boardAssigneeUsername,
labels: $boardApp.dataset.labels ? JSON.parse($boardApp.dataset.labels) : [],
labelIds: $boardApp.dataset.labelIds ? JSON.parse($boardApp.dataset.labelIds) : [],
weight: $boardApp.dataset.boardWeight
? parseInt($boardApp.dataset.boardWeight, 10)
: null,
},
});
},
methods: {
...mapActions(['setInitialBoardData']),
getNodes(data) {
return data[this.parent]?.board?.lists.nodes;
},
},
});
toggleLabels();
mountMultipleBoardsSwitcher({
fullPath: $boardApp.dataset.fullPath,
rootPath: $boardApp.dataset.boardsEndpoint,
});
};
import initEpicBoards from 'ee/epic_boards';
import UsersSelect from '~/users_select';
import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
new UsersSelect(); // eslint-disable-line no-new
new ShortcutsNavigation(); // eslint-disable-line no-new
initEpicBoards();
# frozen_string_literal: true # frozen_string_literal: true
class Groups::EpicBoardsController < Groups::BoardsController class Groups::EpicBoardsController < Groups::ApplicationController
include BoardsActions include BoardsActions
include RecordUserLastActivity
include Gitlab::Utils::StrongMemoize
extend ::Gitlab::Utils::Override
before_action :authorize_read_board!, only: [:index] before_action :authorize_read_board!, only: [:index]
before_action :assign_endpoint_vars
feature_category :boards
private
def board_klass
::Boards::EpicBoard
end
def boards_finder
strong_memoize :boards_finder do
::Boards::EpicBoardsFinder.new(parent)
end
end
def board_finder
strong_memoize :board_finder do
::Boards::EpicBoardsFinder.new(parent, id: params[:id])
end
end
def board_create_service
strong_memoize :board_create_service do
::Boards::EpicBoards::CreateService.new(parent, current_user)
end
end
override :respond_with
def respond_with(resource)
# no JSON for epic boards
respond_to do |format|
format.html
end
end
def assign_endpoint_vars
@boards_endpoint = group_epic_boards_path(group)
@namespace_path = group.to_param
@labels_endpoint = group_labels_path(group)
end
def authorize_read_board! def authorize_read_board!
access_denied! unless Feature.enabled?(:epic_boards, group) && can?(current_user, :read_epic_board, group) access_denied! unless Feature.enabled?(:epic_boards, group) && can?(current_user, :read_epic_board, group)
......
...@@ -14,5 +14,61 @@ module Boards ...@@ -14,5 +14,61 @@ module Boards
def lists def lists
epic_lists epic_lists
end end
def self.to_type
name.demodulize
end
def to_type
self.class.to_type
end
def resource_parent
group
end
def group_board?
true
end
def scoped?
false
end
def milestone_id
nil
end
def milestone
nil
end
def iteration_id
nil
end
def iteration
nil
end
def assignee_id
nil
end
def assignee
nil
end
def label_ids
[]
end
def labels
[]
end
def weight
nil
end
end end
end end
= render "shared/boards/show", board: @boards.first
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Groups::EpicBoardsController do
let(:group) { create(:group) }
let(:user) { create(:user) }
before do
group.add_maintainer(user)
sign_in(user)
end
describe 'GET index' do
it 'creates a new board when group does not have one' do
expect { list_boards }.to change(group.epic_boards, :count).by(1)
end
context 'with unauthorized user' do
let(:other_user) { create(:user) }
before do
sign_in(other_user)
end
it 'returns a not found 404 response' do
list_boards
expect(response).to have_gitlab_http_status(:not_found)
end
end
context 'json request' do
it 'is not supported' do
list_boards(format: :json)
expect(response).to have_gitlab_http_status(:not_found)
end
end
it_behaves_like 'pushes wip limits to frontend' do
let(:params) { { group_id: group } }
let(:parent) { group }
end
def list_boards(format: :html)
get :index, params: { group_id: group }, format: format
end
end
end
...@@ -11523,6 +11523,9 @@ msgstr "" ...@@ -11523,6 +11523,9 @@ msgstr ""
msgid "Epic" msgid "Epic"
msgstr "" msgstr ""
msgid "Epic Boards"
msgstr ""
msgid "Epic cannot be found." msgid "Epic cannot be found."
msgstr "" msgstr ""
......
# frozen_string_literal: true # frozen_string_literal: true
RSpec.shared_examples 'boards list service' do RSpec.shared_examples 'boards list service' do
context 'when parent does not have a board' do it 'does not create a new board' do
it 'creates a new parent board' do expect { service.execute }.not_to change(parent.boards, :count)
expect { service.execute }.to change(parent.boards, :count).by(1)
end
it 'delegates the parent board creation to Boards::CreateService' do
expect_any_instance_of(Boards::CreateService).to receive(:execute).once
service.execute
end
context 'when create_default_board is false' do
it 'does not create a new parent board' do
expect { service.execute(create_default_board: false) }.not_to change(parent.boards, :count)
end
end
end
context 'when parent has a board' do
before do
create(:board, resource_parent: parent)
end
it 'does not create a new board' do
expect { service.execute }.not_to change(parent.boards, :count)
end
end end
it 'returns parent boards' do it 'returns parent boards' do
......
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