diff options
Diffstat (limited to 'app')
-rw-r--r-- | app/controllers/boards/lists_controller.rb | 24 | ||||
-rw-r--r-- | app/models/list.rb | 54 | ||||
-rw-r--r-- | app/models/list_user_preference.rb | 10 | ||||
-rw-r--r-- | app/services/boards/lists/list_service.rb | 2 | ||||
-rw-r--r-- | app/services/boards/lists/update_service.rb | 56 |
5 files changed, 133 insertions, 13 deletions
diff --git a/app/controllers/boards/lists_controller.rb b/app/controllers/boards/lists_controller.rb index ccd02144671..08b4748d7e1 100644 --- a/app/controllers/boards/lists_controller.rb +++ b/app/controllers/boards/lists_controller.rb @@ -4,7 +4,7 @@ module Boards class ListsController < Boards::ApplicationController include BoardsResponses - before_action :authorize_admin_list, only: [:create, :update, :destroy, :generate] + before_action :authorize_admin_list, only: [:create, :destroy, :generate] before_action :authorize_read_list, only: [:index] skip_before_action :authenticate_user!, only: [:index] @@ -15,7 +15,7 @@ module Boards end def create - list = Boards::Lists::CreateService.new(board.parent, current_user, list_params).execute(board) + list = Boards::Lists::CreateService.new(board.parent, current_user, create_list_params).execute(board) if list.valid? render json: serialize_as_json(list) @@ -26,12 +26,13 @@ module Boards def update list = board.lists.movable.find(params[:id]) - service = Boards::Lists::MoveService.new(board_parent, current_user, move_params) + service = Boards::Lists::UpdateService.new(board_parent, current_user, update_list_params) + result = service.execute(list) - if service.execute(list) + if result[:status] == :success head :ok else - head :unprocessable_entity + head result[:http_status] end end @@ -50,7 +51,8 @@ module Boards service = Boards::Lists::GenerateService.new(board_parent, current_user) if service.execute(board) - render json: serialize_as_json(board.lists.movable) + lists = board.lists.movable.preload_associations(current_user) + render json: serialize_as_json(lists) else head :unprocessable_entity end @@ -62,12 +64,12 @@ module Boards %i[label_id] end - def list_params + def create_list_params params.require(:list).permit(list_creation_attrs) end - def move_params - params.require(:list).permit(:position) + def update_list_params + params.require(:list).permit(:collapsed, :position) end def serialize_as_json(resource) @@ -78,7 +80,9 @@ module Boards { only: [:id, :list_type, :position], methods: [:title], - label: true + label: true, + collapsed: true, + current_user: current_user } end end diff --git a/app/models/list.rb b/app/models/list.rb index ccadd39bda2..ae7085f05a7 100644 --- a/app/models/list.rb +++ b/app/models/list.rb @@ -1,9 +1,11 @@ # frozen_string_literal: true class List < ApplicationRecord + include Importable + belongs_to :board belongs_to :label - include Importable + has_many :list_user_preferences enum list_type: { backlog: 0, label: 1, closed: 2, assignee: 3, milestone: 4 } @@ -16,9 +18,24 @@ class List < ApplicationRecord scope :destroyable, -> { where(list_type: list_types.slice(*destroyable_types).values) } scope :movable, -> { where(list_type: list_types.slice(*movable_types).values) } - scope :preload_associations, -> { preload(:board, :label) } + + scope :preload_associations, -> (user) do + preload(:board, label: :priorities) + .with_preferences_for(user) + end + scope :ordered, -> { order(:list_type, :position) } + # Loads list with preferences for given user + # if preferences exists for user or not + scope :with_preferences_for, -> (user) do + return unless user + + includes(:list_user_preferences).where(list_user_preferences: { user_id: [user.id, nil] }) + end + + alias_method :preferences, :list_user_preferences + class << self def destroyable_types [:label] @@ -29,6 +46,31 @@ class List < ApplicationRecord end end + def preferences_for(user) + return preferences.build unless user + + if preferences.loaded? + preloaded_preferences_for(user) + else + preferences.find_or_initialize_by(user: user) + end + end + + def preloaded_preferences_for(user) + user_preferences = + preferences.find do |preference| + preference.user_id == user.id + end + + user_preferences || preferences.build(user: user) + end + + def update_preferences_for(user, preferences = {}) + return unless user + + preferences_for(user).update(preferences) + end + def destroyable? self.class.destroyable_types.include?(list_type&.to_sym) end @@ -43,6 +85,14 @@ class List < ApplicationRecord def as_json(options = {}) super(options).tap do |json| + json[:collapsed] = false + + if options.key?(:collapsed) + preferences = preferences_for(options[:current_user]) + + json[:collapsed] = preferences.collapsed? + end + if options.key?(:label) json[:label] = label.as_json( project: board.project, diff --git a/app/models/list_user_preference.rb b/app/models/list_user_preference.rb new file mode 100644 index 00000000000..fe1cc7d5425 --- /dev/null +++ b/app/models/list_user_preference.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +class ListUserPreference < ApplicationRecord + belongs_to :user + belongs_to :list + + validates :user, presence: true + validates :list, presence: true + validates :user_id, uniqueness: { scope: :list_id, message: "should have only one list preference per user" } +end diff --git a/app/services/boards/lists/list_service.rb b/app/services/boards/lists/list_service.rb index 5cf5f14a55b..1f20ec8df9e 100644 --- a/app/services/boards/lists/list_service.rb +++ b/app/services/boards/lists/list_service.rb @@ -6,7 +6,7 @@ module Boards def execute(board) board.lists.create(list_type: :backlog) unless board.lists.backlog.exists? - board.lists.preload_associations + board.lists.preload_associations(current_user) end end end diff --git a/app/services/boards/lists/update_service.rb b/app/services/boards/lists/update_service.rb new file mode 100644 index 00000000000..2ddeb6f0bd8 --- /dev/null +++ b/app/services/boards/lists/update_service.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +module Boards + module Lists + class UpdateService < Boards::BaseService + def execute(list) + return not_authorized if preferences? && !can_read?(list) + return not_authorized if position? && !can_admin?(list) + + if update_preferences(list) || update_position(list) + success(list: list) + else + error(list.errors.messages, 422) + end + end + + def update_preferences(list) + return unless preferences? + + list.update_preferences_for(current_user, preferences) + end + + def update_position(list) + return unless position? + + move_service = Boards::Lists::MoveService.new(parent, current_user, params) + + move_service.execute(list) + end + + def preferences + { collapsed: Gitlab::Utils.to_boolean(params[:collapsed]) } + end + + def not_authorized + error("Not authorized", 403) + end + + def preferences? + params.has_key?(:collapsed) + end + + def position? + params.has_key?(:position) + end + + def can_read?(list) + Ability.allowed?(current_user, :read_list, parent) + end + + def can_admin?(list) + Ability.allowed?(current_user, :admin_list, parent) + end + end + end +end |