1# frozen_string_literal: true 2 3# Provides an action which fetches a metrics dashboard according 4# to the parameters specified by the controller. 5module MetricsDashboard 6 include RenderServiceResults 7 include ChecksCollaboration 8 include EnvironmentsHelper 9 10 extend ActiveSupport::Concern 11 12 def metrics_dashboard 13 result = dashboard_finder.find( 14 project_for_dashboard, 15 current_user, 16 decoded_params 17 ) 18 19 if result 20 result[:all_dashboards] = all_dashboards if include_all_dashboards? 21 result[:metrics_data] = metrics_data(project_for_dashboard, environment_for_dashboard) 22 end 23 24 respond_to do |format| 25 if result.nil? 26 format.json { continue_polling_response } 27 elsif result[:status] == :success 28 format.json { render dashboard_success_response(result) } 29 else 30 format.json { render dashboard_error_response(result) } 31 end 32 end 33 end 34 35 private 36 37 def all_dashboards 38 dashboard_finder 39 .find_all_paths(project_for_dashboard) 40 .map(&method(:amend_dashboard)) 41 end 42 43 def amend_dashboard(dashboard) 44 project_dashboard = project_for_dashboard && !dashboard[:out_of_the_box_dashboard] 45 46 dashboard[:can_edit] = project_dashboard ? can_edit?(dashboard) : false 47 dashboard[:project_blob_path] = project_dashboard ? dashboard_project_blob_path(dashboard) : nil 48 dashboard[:starred] = starred_dashboards.include?(dashboard[:path]) 49 dashboard[:user_starred_path] = project_for_dashboard ? user_starred_path(project_for_dashboard, dashboard[:path]) : nil 50 51 dashboard 52 end 53 54 def user_starred_path(project, path) 55 expose_path(api_v4_projects_metrics_user_starred_dashboards_path(id: project.id, params: { dashboard_path: path })) 56 end 57 58 def dashboard_project_blob_path(dashboard) 59 project_blob_path(project_for_dashboard, File.join(project_for_dashboard.default_branch, dashboard.fetch(:path, ""))) 60 end 61 62 def can_edit?(dashboard) 63 can_collaborate_with_project?(project_for_dashboard, ref: project_for_dashboard.default_branch) 64 end 65 66 # Override in class to provide arguments to the finder. 67 def metrics_dashboard_params 68 {} 69 end 70 71 # Override in class if response requires complete list of 72 # dashboards in addition to requested dashboard body. 73 def include_all_dashboards? 74 false 75 end 76 77 def dashboard_finder 78 ::Gitlab::Metrics::Dashboard::Finder 79 end 80 81 def starred_dashboards 82 @starred_dashboards ||= begin 83 if project_for_dashboard.present? 84 ::Metrics::UsersStarredDashboardsFinder 85 .new(user: current_user, project: project_for_dashboard) 86 .execute 87 .map(&:dashboard_path) 88 .to_set 89 else 90 Set.new 91 end 92 end 93 end 94 95 # Project is not defined for group and admin level clusters. 96 def project_for_dashboard 97 defined?(project) ? project : nil 98 end 99 100 def environment_for_dashboard 101 defined?(environment) ? environment : nil 102 end 103 104 def dashboard_success_response(result) 105 { 106 status: :ok, 107 json: result.slice(:all_dashboards, :dashboard, :status, :metrics_data) 108 } 109 end 110 111 def dashboard_error_response(result) 112 { 113 status: result[:http_status] || :bad_request, 114 json: result.slice(:all_dashboards, :message, :status) 115 } 116 end 117 118 def decoded_params 119 params = metrics_dashboard_params 120 121 if params[:dashboard_path] 122 params[:dashboard_path] = CGI.unescape(params[:dashboard_path]) 123 end 124 125 params 126 end 127end 128