Skip to content

Commit

Permalink
Adding a table to display the contents of a project (#1097)
Browse files Browse the repository at this point in the history
  • Loading branch information
carolyncole authored Dec 10, 2024
1 parent dec6115 commit d83fd7d
Show file tree
Hide file tree
Showing 11 changed files with 161 additions and 95 deletions.
75 changes: 75 additions & 0 deletions app/assets/stylesheets/_project.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
@import "variables";
@import "typography";
@import "bootstrap";

#project-contents {
// table-layout: fixed;
border: 1px solid $gray-20;
border-radius: 3px;
padding: 0rem 0.75rem;
align-items: center;
gap: 16px;
color: $gray-100;
font-size: 12px;
font-style: normal;
font-weight: 400;
line-height: 18px;
width: 100%;

thead {
background-color: $gray-10;
overflow: hidden;
color: $gray-100;
text-overflow: ellipsis;

/* Body S Bold */
font-family: "Libre Franklin";
font-size: 1rem;
font-style: normal;
font-weight: 600;
line-height: 1.5rem; /* 150% */
}

tr {
border: 1px solid $gray-20;
overflow: hidden;
color: $gray-100;
text-overflow: ellipsis;
}

td, th {
padding: 0.5em 1em;
}
}

.contents-summary {
margin: 1rem 0px;
padding: 0.75rem 1.5rem;
background-color: $gray-10;

.file-inventory {
color: $gray-100;
font-weight: 600;
}

// Note, this can not be a variable
--bs-border-color: #717171;
}

.content-info {
color: $gray-100;
background-color: $status-info;
padding: 0.5em 1em;

.bi-info-circle {
padding-right: 1em;
}
}

#project-contents {
margin-bottom: 0.75rem;

.sorting:hover {
cursor: pointer;
}
}
1 change: 1 addition & 0 deletions app/assets/stylesheets/application.scss
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
@import "forms";
@import "header";
@import "projects";
@import "project";
@import "settings";
@import "styles_preview";
@import "typography";
Expand Down
6 changes: 3 additions & 3 deletions app/models/mediaflux/asset.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,15 @@ def name
end
end

# Returns the path to the asset but without the root namespace as part of it.
# Returns the path to the asset but without the root collection namespace as part of it.
#
# Example:
# path -> "/tigerdata/projectg/folder1/file-abc.txt"
# path_short -> "/projectg/folder1/file-abc.txt"
def path_short
return nil if path.nil?
if path.starts_with?(Mediaflux::Connection.root_namespace)
path[Mediaflux::Connection.root_namespace.length..-1]
if path.starts_with?(Mediaflux::Connection.root_collection_namespace)
path[Mediaflux::Connection.root_collection_namespace.length..-1]
else
path
end
Expand Down
9 changes: 9 additions & 0 deletions app/presenters/project_asset_presenter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# frozen_string_literal: true
class ProjectShowPresenter
delegate name, path_only, last_modified, size, to: asset

def initialize(project, asset)
@project = project
@asset = asset
end
end
6 changes: 6 additions & 0 deletions app/views/projects/_content_view.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<tr class="content">
<td><%= file.name %></td>
<td><%= file.path_only %></td>
<td><%= number_to_human_size(file.size)%></td>
<td><%= file.last_modified %></td>
</tr>
16 changes: 16 additions & 0 deletions app/views/projects/_contents.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<div class="content-info"><i class="bi bi-info-circle"></i>Showing the first 100 files due to preview limit.</div>
<div class="table project-files">
<table id="project-contents" >
<thead>
<tr class="content heading">
<th class="sorting">name</th>
<th>relative path</th>
<th>size</th>
<th>last updated</th>
</tr>
</thead>
<tbody>
<%= render :partial => "content_view", :collection => @files, :as => :file %>
</tbody>
</table>
</div>
122 changes: 40 additions & 82 deletions app/views/projects/contents.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -3,93 +3,51 @@
<content id= "content">

<h2>Contents Summary</h2>
<section class="container-fluid px-1 m-1 project-contents__summary">
<dl>
<dt>Storage Usage</dt> <dd id="storage-usage"><%= @storage_usage %> / <%= @storage_capacity %> </dd>
</dl>
<dl>
<dt>File Count</dt> <dd id="file_count"><%= @num_files %> </dd>
</dl>
</section>
<% if @files.present? %>
<section class="container-fluid px-1 mx-2 my-4 project-contents__preview">
<div>
<h2>Contents Preview</h2>
<p class="text-muted"> Please note that the contents preview feature is still under development and currently only displays world-readable files (not those with more limited permissions).
You can still find all of the contents you have access to through the project's mount point.</p>
<table id="file-list">
<tr>
<th>Path</th>
<th>Name</th>
<th class="numeric_column">Size</th>
<th class="numeric_column">Last modified</th>
</tr>
<% current_folder = nil %>
<% @files.each_with_index do |file, index| %>
<% @row_css = index < 10 ? "visible-row top-section" : "invisible-row bottom-section" %>

<% if current_folder != file.path_only %>
<!--
Print the folder information row.
Notice that depending how the data comes back from Mediaflux we might see the
collection record first or a _file_ under the collection first.
-->
<% current_folder = file.path_only %>
<tr class="<%= @row_css %>">
<td><b><%= current_folder %>/</b></td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
<% end %>

<% unless file.collection %>
<!-- Print the file information row -->
<tr class="<%= @row_css %>">
<td>&nbsp;</td>
<td><%= file.name %> </td>
<td class="numeric_column"><%= number_to_human_size(file.size) %></td>
<td class="numeric_column"><%= file.last_modified %></td>
</tr>
<% end %>
<% end %>
</table>
</div>
<form name="project-contents-preview">
<button id="show-more" type="button" class="btn btn-primary">Show More</button>
<button type="button" class="btn btn-secondary" data-bs-toggle="modal" data-bs-target="#list-contents-modal">List All Files</button>
<button type="button" class="btn btn-dark">Custom Query</button>
</form>
</section>
<% end %>
<section class="container-fluid px-1 mx-0 my-1 project-contents__navigate">
<a href="<%= project_path(@project) %>" class="btn btn-primary">Review Metadata</a>
<a href="<%= root_path %>" class="btn btn-secondary">Return to Dashboard</a>
</section>
<section class="project-alerts my-4">
<div class="row">
<div class="col">
<div id="project-alert" class="alert alert-primary d-none my-1" role="alert" ></div>
<div class="container">
<div class="row align-items-center contents-summary">
<div class="col-sm-2 file-inventory">File Inventory:</div>
<div class="col-sm-2 file-total-label">Total Files: <%= @num_files %></div>
<div class="col-sm-8 text-end divider">
<form name="project-contents-preview">
<button type="button" class="btn btn-secondary" data-bs-toggle="modal" data-bs-target="#list-contents-modal">Download Complete List</button>
</form>
</div>
</div>
</section>
</content>

<!-- Bootstrap Modal -->
<div class="modal fade" id="list-contents-modal" tabindex="-1" aria-labelledby="list the project contents" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="list-contents-modal-title">List Project Contents</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
This will generate a list of <%= @num_files %> files and their attributes in a downloadable CSV. Do you wish to continue?
<%= render partial: "contents", locals: { files: @files } %>
<section class="container-fluid px-1 mx-0 my-1 project-contents__navigate">
<a href="<%= project_path(@project) %>" class="btn btn-primary">Review Metadata</a>
<a href="<%= root_path %>" class="btn btn-secondary">Return to Dashboard</a>
</section>
<section class="project-alerts my-4">
<div class="row">
<div class="col">
<div id="project-alert" class="alert alert-primary d-none my-1" role="alert" ></div>
</div>
</div>
<div class="modal-footer">
<button type="button" id="request-list-contents" class="btn btn-success" data-list-contents-path="<%= project_list_contents_path %>" >Yes</button>
<button type="button" class="btn btn-danger" data-bs-dismiss="modal">No</button>
</section>
</content>

<!-- Bootstrap Modal -->
<div class="modal fade" id="list-contents-modal" tabindex="-1" aria-labelledby="list the project contents" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="list-contents-modal-title">List Project Contents</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
This will generate a list of <%= @num_files %> files and their attributes in a downloadable CSV. Do you wish to continue?
</div>
<div class="modal-footer">
<button type="button" id="request-list-contents" class="btn btn-success" data-list-contents-path="<%= project_list_contents_path %>" >Yes</button>
<button type="button" class="btn btn-danger" data-bs-dismiss="modal">No</button>
</div>
</div>
</div>
</div>
</div>
<script type="module">
// Setup the DataTables
setupTable('#project-contents');
</script>
4 changes: 2 additions & 2 deletions spec/models/mediaflux/asset_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
let(:file_asset) do
Mediaflux::Asset.new(
id: 123, name: "file.txt",
path: "#{Rails.configuration.mediaflux['api_root_ns']}/project-1/photos/sunset.jpg",
path: "#{Rails.configuration.mediaflux['api_root_collection_namespace']}/project-1/photos/sunset.jpg",
collection: false,
last_modified_mf: "08-Feb-2024 16:08:54"
)
end

let(:folder_asset) do
Mediaflux::Asset.new(id: 123, name: "photos", path: "#{Rails.configuration.mediaflux['api_root_ns']}/project-1/photos", collection: true)
Mediaflux::Asset.new(id: 123, name: "photos", path: "#{Rails.configuration.mediaflux['api_root_collection_namespace']}/project-1/photos", collection: true)
end

describe "#path" do
Expand Down
2 changes: 1 addition & 1 deletion spec/system/mediaflux_session_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
Mediaflux::LogoutRequest.new(session_token: original_session).resolve

expect { visit project_contents_path(project) }.not_to raise_error
expect(page).to have_content("File Count\n0")
expect(page).to have_content("Total Files: 0")

# a new session got automatically connected for the user in the application controller
expect(sponsor_user.mediaflux_session).not_to eq(original_session)
Expand Down
10 changes: 5 additions & 5 deletions spec/system/project_show_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,8 @@
expect(page).to have_selector(:link_or_button, "Review Contents")
click_on("Review Contents")
expect(page).to have_content("Contents Summary")
expect(page).to have_content("File Count")
expect(find(:css, "#file_count").text).to eq "16"
expect(page).to have_content("8 out of 22 shown")
# expect(find(:css, "#file_count").text).to eq "16"

# Be able to return to the dashboard
expect(page).to have_selector(:link_or_button, "Return to Dashboard")
Expand All @@ -188,7 +188,7 @@
click_on("Review Contents")

# Caveat message is displayed
expect(page).to have_content("Please note that the contents preview feature is still under development and currently only displays world-readable files")
expect(page).to have_content("Showing the first 100 files due to preview limit.")
end

it "displays the file list" do
Expand All @@ -203,8 +203,8 @@
expect(page).to have_content(second_file.name)
expect(page).not_to have_content(last_file.name)

# More files are displayed
click_on("Show More")
# files are paginated
find("a.paginate_button", text: 3).click
expect(page).to have_content(last_file.name)
end
end
Expand Down
5 changes: 3 additions & 2 deletions spec/system/project_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -490,8 +490,8 @@
it "enqueues a Sidekiq job for asynchronously requesting project files" do
visit project_contents_path(approved_project)

expect(page).to have_content("List All Files")
click_on "List All Files"
expect(page).to have_content("Download Complete List")
click_on "Download Complete List"
expect(page).to have_content("This will generate a list of 4 files and their attributes in a downloadable CSV. Do you wish to continue?")
expect(page).to have_content("Yes")
sleep 1
Expand All @@ -518,6 +518,7 @@

context "when the quota is allocated" do
it "renders the storage capacity in the show view" do
pending "this should not be on the project view page"
visit project_contents_path(approved_project)
expect(page).to have_content "400 bytes / 500 GB" # should be 300 GB which is the quota, instead of 500GB which is the requested capacity
expect(page).to be_axe_clean
Expand Down

0 comments on commit d83fd7d

Please sign in to comment.