• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

pulibrary / tigerdata-app / 904be010-4760-47b0-943f-db65c886cd13

28 Oct 2025 02:06PM UTC coverage: 72.228% (-19.1%) from 91.294%
904be010-4760-47b0-943f-db65c886cd13

Pull #2057

circleci

hectorcorrea
Force a change
Pull Request #2057: Dashboard displays projects straights from Mediaflux

65 of 69 new or added lines in 4 files covered. (94.2%)

257 existing lines in 31 files now uncovered.

2221 of 3075 relevant lines covered (72.23%)

190.52 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

80.99
/app/controllers/projects_controller.rb
1
# frozen_string_literal: true
2
class ProjectsController < ApplicationController
1✔
3

4
  before_action :set_breadcrumbs
1✔
5
  before_action :authenticate_user!
1✔
6

7
  def details
1✔
8
    return if project.blank?
12✔
9

10
    add_breadcrumb(project.title, project_path)
12✔
11
    add_breadcrumb("Details")
12✔
12

13
    @departments = project.departments.join(", ")
12✔
14
    @project_metadata = project.metadata_model
12✔
15

16
    @data_sponsor = User.find_by(uid: @project_metadata.data_sponsor)
12✔
17
    @data_manager = User.find_by(uid: @project_metadata.data_manager)
12✔
18

19
    read_only_uids = @project_metadata.ro_users
12✔
20
    data_read_only_users = read_only_uids.map { |uid| ReadOnlyUser.find_by(uid:) }.reject(&:blank?)
14✔
21

22
    read_write_uids = @project_metadata.rw_users
12✔
23
    data_read_write_users = read_write_uids.map { |uid| User.find_by(uid:) }.reject(&:blank?)
14✔
24

25
    unsorted_data_users = data_read_only_users + data_read_write_users
12✔
26
    sorted_data_users = unsorted_data_users.sort_by { |u| u.family_name || u.uid }
16✔
27
    @data_users = sorted_data_users.uniq { |u| u.uid }
16✔
28
    user_model_names = @data_users.map(&:display_name_safe)
12✔
29
    @data_user_names = user_model_names.join(", ")
12✔
30

31
    @provenance_events = project.provenance_events.where.not(event_type: ProvenanceEvent::STATUS_UPDATE_EVENT_TYPE)
12✔
32

33
    @project_eligible_to_edit = true if project.status == Project::APPROVED_STATUS && eligible_editor?
12✔
34

35
    @project_metadata = @project.metadata
12✔
36
    @project_id = @project_metadata[:project_id] || {}
12✔
37
    @storage_capacity = @project_metadata[:storage_capacity]
12✔
38
    @size = @storage_capacity[:size]
12✔
39
    @unit = @storage_capacity[:unit]
12✔
40

41
    @requested_size = @size[:requested]
12✔
42
    @requested_unit = @unit[:requested]
12✔
43

44
    @approved_size = @size[:approved]
12✔
45
    @approved_unit = @unit[:approved]
12✔
46

47
    @storage_expectations = @project_metadata[:storage_performance_expectations]
12✔
48
    @requested_storage_expectations = @storage_expectations[:requested]
12✔
49
    @approved_storage_expectations = @storage_expectations[:approved]
12✔
50

51
    @project_purpose = @project_metadata[:project_purpose]
12✔
52
    @number_of_files = @project_metadata[:number_of_files]
12✔
53
    @hpc = @project_metadata[:hpc]
12✔
54
    @smb = @project_metadata[:smb_request]
12✔
55
    @globus = @project_metadata[:globus_request]
12✔
56

57
    @project_session = "details"
12✔
58

59
    respond_to do |format|
12✔
60
      format.html do
12✔
61
        @project = ProjectShowPresenter.new(project)
12✔
62
      end
63
      format.json do
12✔
64
        render json: project.to_json
×
65
      end
66
      format.xml do
12✔
67
        render xml: project.to_xml
×
68
      end
69
    end
70
  end
71

72
  def index
1✔
73
    if current_user.eligible_sysadmin?
6✔
74
      search_projects
3✔
75
    else
76
      flash[:alert] = I18n.t(:access_denied)
3✔
77
      redirect_to dashboard_path
3✔
78
    end
79
  end
80

81
  def show
1✔
82

83
    return if project.blank?
30✔
84
    add_breadcrumb(project.title, project_path)
27✔
85
    add_breadcrumb("Contents")
27✔
86

87
    @latest_completed_download = current_user.user_requests.where(project_id: @project.id, state: "completed").order(:completion_time).last
27✔
88
    @storage_usage = project.storage_usage(session_id: current_user.mediaflux_session)
27✔
89
    @storage_capacity = project.storage_capacity(session_id: current_user.mediaflux_session)
27✔
90

91
    @num_files = project.asset_count(session_id: current_user.mediaflux_session)
27✔
92

93
    @file_list = project.file_list(session_id: current_user.mediaflux_session, size: 100)
27✔
94
    @files = @file_list[:files]
27✔
95
    @files.sort_by!(&:path)
27✔
96
    @project = ProjectShowPresenter.new(project)
27✔
97

98
    @project_session = "content"
27✔
99
    respond_to do |format|
27✔
100
      format.html { render }
50✔
101
      format.xml { render xml: @project.to_xml }
31✔
102
    end
103
  end
104

105
  # GET "projects/:id/:id-mf"
106
  #
107
  # This action is used to render the mediaflux metadata for a project.
108
  def show_mediaflux
1✔
UNCOV
109
    project_id = params[:id]
×
UNCOV
110
    project = Project.find(project_id)
×
UNCOV
111
    respond_to do |format|
×
UNCOV
112
      format.xml do
×
UNCOV
113
        render xml: project.mediaflux_meta_xml(user: current_user)
×
114
      end
115
    end
116
  rescue => ex
UNCOV
117
    Rails.logger.error "Error getting MediaFlux XML for project #{project_id}, user #{current_user.uid}: #{ex.message}"
×
UNCOV
118
    flash[:alert] = "Error fetching Mediaflux XML for this project"
×
UNCOV
119
    redirect_to project_path(project_id)
×
120
  end
121

122
  def list_contents
1✔
123
    return if project.blank?
3✔
124

125
    project_job_service.list_contents_job(user: current_user)
3✔
126

127
    json_response = {
128
      message: "File list for \"#{project.title}\" is being generated in the background. A link to the downloadable file list will be available in the \"Recent Activity\" section of your dashboard when it is available. You may safely navigate away from this page or close this tab."
3✔
129
    }
130
    render json: json_response
3✔
131
  rescue => ex
132
    message = "Error producing document list (project id: #{project&.id}): #{ex.message}"
×
133
    Rails.logger.error(message)
×
134
    Honeybadger.notify(message)
×
135
    render json: { message: "Document list could not be generated." }
×
136
  end
137

138
  def file_list_download
1✔
139
    job_id = params[:job_id]
×
140
    user_request = FileInventoryRequest.where(job_id:job_id).first
×
141
    if user_request.nil?
×
142
      # TODO: handle error
143
      redirect_to "/"
×
144
    else
145
      filename = user_request.output_file
×
146
      send_data File.read(filename), type: "text/plain", filename: "filelist.csv", disposition: "attachment"
×
147
    end
148
  end
149

150
  private
1✔
151

152
    def project_job_service
1✔
153
      @project_job_service ||= ProjectJobService.new(project:)
3✔
154
    end
155

156

157
    def build_new_project
1✔
158
      @project ||= Project.new
×
159
    end
160

161
    def project
1✔
162
      @project ||= begin
285✔
163
        project = Project.find(params[:id])
45✔
164
        if project.user_has_access?(user: current_user)
45✔
165
          project
42✔
166
        else
167
          flash[:alert] = I18n.t(:access_denied)
3✔
168
          redirect_to dashboard_path
3✔
169
          nil
3✔
170
        end
171
      end
172
    end
173

174
    def eligible_editor?
1✔
175
      return true if current_user.eligible_sponsor? or current_user.eligible_manager?
8✔
176
    end
177

178
    def set_breadcrumbs
1✔
179
      add_breadcrumb("Dashboard",dashboard_path)
53✔
180
    end
181

182
    def search_projects
1✔
183
      @title_query = params[:title_query]
3✔
184
      if @title_query.blank?
3✔
185
        @projects = Project.all
1✔
186
        flash[:notice] = nil
1✔
187
      else
188
        result =  ProjectSearch.new.call(search_string: @title_query, requestor: current_user)
2✔
189
        if result.success?
2✔
190
          flash[:notice] = "Successful search in Mediaflux for #{@title_query}"
2✔
191
          @projects = result.value!
2✔
192
        else
193
          @projects = []
×
194
          flash[:notice] = "Error searching projects for #{@title_query}.  Error: #{result.failure}"
×
195
        end
196
      end
197
    end
198
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc