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

pulibrary / tigerdata-app / 481779a4-a529-439e-b7a5-c800cf24ea4a

13 Feb 2026 07:54PM UTC coverage: 90.979% (+0.03%) from 90.952%
481779a4-a529-439e-b7a5-c800cf24ea4a

Pull #2384

circleci

hectorcorrea
Make the name pattern optional in TestAssetGenerator
Pull Request #2384: File Explorer Proof of Concept

31 of 34 new or added lines in 3 files covered. (91.18%)

3096 of 3403 relevant lines covered (90.98%)

593.97 hits per line

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

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

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

7
  def details
2✔
8
    return if project.blank?
24✔
9

10
    add_breadcrumb(@presenter.title, project_path)
22✔
11
    add_breadcrumb("Details")
22✔
12

13
    project_metadata = @project.metadata
22✔
14
    storage_capacity = project_metadata[:storage_capacity]
22✔
15
    size = storage_capacity[:size]
22✔
16
    unit = storage_capacity[:unit]
22✔
17

18
    @requested_size = size[:requested]
22✔
19
    @requested_unit = unit[:requested]
22✔
20

21
    @approved_size = size[:approved]
22✔
22
    @approved_unit = unit[:approved]
22✔
23

24
    @project_session = "details"
22✔
25
    @show_quota_breakdown = params["quota"] == "true"
22✔
26

27
    respond_to do |format|
22✔
28
      format.html do
22✔
29
        render
19✔
30
      end
31
      format.json do
22✔
32
        render json: project.to_json
2✔
33
      end
34
      format.xml do
22✔
35
        render xml: @presenter.to_xml
1✔
36
      end
37
    end
38
  end
39

40
  def index
2✔
41
    if current_user.eligible_sysadmin?
10✔
42
      search_projects
6✔
43
    else
44
      flash[:alert] = I18n.t(:access_denied)
4✔
45
      redirect_to dashboard_path
4✔
46
    end
47
  end
48

49
  def show
2✔
50
    return if project.blank?
39✔
51

52
    add_breadcrumb(@presenter.title, project_path)
30✔
53
    add_breadcrumb("Contents")
30✔
54

55
    @latest_completed_download = current_user.inventory_requests.where(project_id: @project.id, state: "completed").order(:completion_time).last
30✔
56
    @storage_usage = project.storage_usage(session_id: current_user.mediaflux_session)
30✔
57
    @storage_capacity = project.storage_capacity(session_id: current_user.mediaflux_session)
30✔
58

59
    @num_files = project.asset_count(session_id: current_user.mediaflux_session)
30✔
60

61
    @file_list = project.file_list(session_id: current_user.mediaflux_session, size: 100)
30✔
62
    @files = @file_list[:files]
30✔
63
    @files.sort_by!(&:path)
30✔
64

65
    @project_session = "content"
30✔
66
    respond_to do |format|
30✔
67
      format.html { render }
54✔
68
      format.xml { render xml: ProjectShowPresenter.new(project, current_user).to_xml
36✔
69
    }
70
    end
71
  end
72

73
  # GET "projects/:id/file-explorer"
74
  # Used via an AJAX call to retrieve the list of files for a given path within a project
75
  def file_explorer
2✔
76
    project # force the presenter to be set
3✔
77

78
    if params["pathId"].to_i == 0
3✔
79
      path = @presenter.project_directory
1✔
80
      path_id = project.mediaflux_id
1✔
81
    else
82
      path = params["path"]
2✔
83
      path_id = params["pathId"].to_i
2✔
84
    end
85

86
    iterator_id = if params["iteratorId"].to_i == 0
3✔
87
      # setup a new iterator
88
      project.file_explorer_setup(session_id: current_user.mediaflux_session, path_id: path_id)
3✔
89
    else
90
      # use the existing iterator
NEW
91
      params["iteratorId"].to_i
×
92
    end
93

94
    mediaflux_data = project.file_explorer_iterate(session_id: current_user.mediaflux_session, iterator_id: iterator_id)
3✔
95
    if mediaflux_data[:error]
3✔
NEW
96
      render json: {}, status: 500
×
97
    else
98
      data = {
99
        fileListUrl: project_file_explorer_url,
3✔
100
        currentPath: path,
101
        currentPathId: path_id,
102
        iteratorId: iterator_id,
103
        files: mediaflux_data[:files],
104
        complete: mediaflux_data[:complete]
105
      }
106
      render json: data
3✔
107
    end
108
  end
109

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

127
  def list_contents
2✔
128
    return if project.blank?
4✔
129

130
    project_job_service.list_contents_job(user: current_user)
3✔
131

132
    json_response = {
133
      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✔
134
    }
135
    render json: json_response
3✔
136
  rescue => ex
137
    message = "Error producing document list (project id: #{project&.id}): #{ex.message}"
×
138
    Rails.logger.error(message)
×
139
    Honeybadger.notify(message)
×
140
    render json: { message: "Document list could not be generated." }
×
141
  end
142

143
  def file_list_download
2✔
144
    job_id = params[:job_id]
×
145
    file_inventory_request = FileInventoryRequest.where(job_id:job_id).first
×
146
    if file_inventory_request.nil?
×
147
      # TODO: handle error
148
      redirect_to "/"
×
149
    else
150
      filename = file_inventory_request.output_file
×
151
      send_data File.read(filename), type: "text/plain", filename: "filelist.csv", disposition: "attachment"
×
152
    end
153
  end
154

155
  private
2✔
156

157
    def project_job_service
2✔
158
      @project_job_service ||= ProjectJobService.new(project:)
3✔
159
    end
160

161
    def project
2✔
162
      @project ||= begin
211✔
163
        project = Project.find(params[:id])
70✔
164
        @presenter = ProjectShowPresenter.new(project, current_user)
70✔
165
        if project&.mediaflux_id != nil && @presenter.user_has_access?(user: current_user)
66✔
166
          project
58✔
167
        else
168
          flash[:alert] = I18n.t(:access_denied)
8✔
169
          redirect_to dashboard_path
8✔
170
          nil
8✔
171
        end
172
      end
173
    end
174

175
    def eligible_editor?
2✔
176
      return true if current_user.eligible_sponsor? or current_user.eligible_manager?
×
177
    end
178

179
    def set_breadcrumbs
2✔
180
      add_breadcrumb("Dashboard",dashboard_path)
90✔
181
    end
182

183
    def search_projects
2✔
184
      @title_query = if params[:title_query].present?
6✔
185
        params[:title_query]
4✔
186
      else
187
        "*" # default to all projects
2✔
188
      end
189
      result =  ProjectSearch.new.call(search_string: @title_query, requestor: current_user)
6✔
190
      if result.success?
6✔
191
        flash[:notice] = "Successful search in Mediaflux for #{@title_query}"
6✔
192
        @project_presenters = result.value!
6✔
193
      else
194
        flash[:notice] = "Error searching projects for #{@title_query}.  Error: #{result.failure}"
×
195
        @project_presenters = []
×
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

© 2026 Coveralls, Inc