1# frozen_string_literal: true 2 3class Projects::MilestonesController < Projects::ApplicationController 4 include Gitlab::Utils::StrongMemoize 5 include MilestoneActions 6 7 before_action :check_issuables_available! 8 before_action :milestone, only: [:edit, :update, :destroy, :show, :issues, :merge_requests, :participants, :labels, :promote] 9 10 # Allow read any milestone 11 before_action :authorize_read_milestone! 12 13 # Allow admin milestone 14 before_action :authorize_admin_milestone!, except: [:index, :show, :issues, :merge_requests, :participants, :labels] 15 16 # Allow to promote milestone 17 before_action :authorize_promote_milestone!, only: :promote 18 19 respond_to :html 20 21 feature_category :team_planning 22 23 def index 24 @sort = params[:sort] || 'due_date_asc' 25 @milestones = milestones.sort_by_attribute(@sort) 26 27 respond_to do |format| 28 format.html do 29 # We need to show group milestones in the JSON response 30 # so that people can filter by and assign group milestones, 31 # but we don't need to show them on the project milestones page itself. 32 @milestones = @milestones.for_projects 33 @milestones = @milestones.page(params[:page]) 34 end 35 format.json do 36 render json: @milestones.to_json(only: [:id, :title, :due_date], methods: :name) 37 end 38 end 39 end 40 41 def new 42 @noteable = @milestone = @project.milestones.new 43 respond_with(@milestone) 44 end 45 46 def edit 47 respond_with(@milestone) 48 end 49 50 def show 51 respond_to do |format| 52 format.html 53 end 54 end 55 56 def create 57 @milestone = Milestones::CreateService.new(project, current_user, milestone_params).execute 58 59 if @milestone.valid? 60 redirect_to project_milestone_path(@project, @milestone) 61 else 62 render "new" 63 end 64 end 65 66 def update 67 @milestone = Milestones::UpdateService.new(project, current_user, milestone_params).execute(milestone) 68 69 respond_to do |format| 70 format.js 71 format.html do 72 if @milestone.valid? 73 redirect_to project_milestone_path(@project, @milestone) 74 else 75 render :edit 76 end 77 end 78 end 79 end 80 81 def promote 82 promoted_milestone = Milestones::PromoteService.new(project, current_user).execute(milestone) 83 flash[:notice] = flash_notice_for(promoted_milestone, project_group) 84 85 respond_to do |format| 86 format.html do 87 redirect_to project_milestones_path(project) 88 end 89 format.json do 90 render json: { url: project_milestones_path(project) } 91 end 92 end 93 rescue Milestones::PromoteService::PromoteMilestoneError => error 94 redirect_to milestone, alert: error.message 95 end 96 97 def flash_notice_for(milestone, group) 98 ''.html_safe + "#{milestone.title} promoted to " + view_context.link_to('<u>group milestone</u>'.html_safe, group_milestone_path(group, milestone.iid)) + '.' 99 end 100 101 def destroy 102 return access_denied! unless can?(current_user, :admin_milestone, @project) 103 104 Milestones::DestroyService.new(project, current_user).execute(milestone) 105 106 respond_to do |format| 107 format.html { redirect_to namespace_project_milestones_path, status: :see_other } 108 format.js { head :ok } 109 end 110 end 111 112 protected 113 114 def project_group 115 strong_memoize(:project_group) do 116 project.group 117 end 118 end 119 120 def milestones 121 strong_memoize(:milestones) do 122 MilestonesFinder.new(search_params).execute 123 end 124 end 125 126 # rubocop: disable CodeReuse/ActiveRecord 127 def milestone 128 @noteable = @milestone ||= @project.milestones.find_by!(iid: params[:id]) 129 end 130 # rubocop: enable CodeReuse/ActiveRecord 131 132 def authorize_admin_milestone! 133 return render_404 unless can?(current_user, :admin_milestone, @project) 134 end 135 136 def authorize_promote_milestone! 137 return render_404 unless can?(current_user, :admin_milestone, project_group) 138 end 139 140 def milestone_params 141 params.require(:milestone).permit(:title, :description, :start_date, :due_date, :state_event) 142 end 143 144 def search_params 145 if request.format.json? && project_group && can?(current_user, :read_group, project_group) 146 groups = project_group.self_and_ancestors.select(:id) 147 end 148 149 params.permit(:state, :search_title).merge(project_ids: @project.id, group_ids: groups) 150 end 151end 152