From 4b677110015eefe5ab3695bdc0089326e6d0b9a4 Mon Sep 17 00:00:00 2001 From: Greg Buchanan Date: Thu, 21 Nov 2024 10:49:32 -0500 Subject: [PATCH 01/13] 3944 - add file browser to project show page. --- .../app/controllers/concerns/pathable.rb | 47 ++++++++++++++++ .../app/controllers/files_controller.rb | 46 ++++------------ .../app/controllers/projects_controller.rb | 34 ++++++++++++ apps/dashboard/app/javascript/application.js | 1 + .../app/views/layouts/application.html.erb | 1 + .../app/views/projects/_directory.html.erb | 21 ++++++++ .../app/views/projects/_files.html.erb | 54 +++++++++++++++++++ .../app/views/projects/show.html.erb | 6 ++- apps/dashboard/config/routes.rb | 3 ++ apps/dashboard/package.json | 1 + apps/dashboard/yarn.lock | 18 +++++++ 11 files changed, 196 insertions(+), 36 deletions(-) create mode 100644 apps/dashboard/app/controllers/concerns/pathable.rb create mode 100644 apps/dashboard/app/views/projects/_directory.html.erb create mode 100644 apps/dashboard/app/views/projects/_files.html.erb diff --git a/apps/dashboard/app/controllers/concerns/pathable.rb b/apps/dashboard/app/controllers/concerns/pathable.rb new file mode 100644 index 0000000000..57947dceab --- /dev/null +++ b/apps/dashboard/app/controllers/concerns/pathable.rb @@ -0,0 +1,47 @@ +module Pathable + extend ActiveSupport::Concern + + def normalized_path(path) + Pathname.new("/#{path.to_s.chomp('/').delete_prefix('/')}") + end + + def parse_path(path = nil, filesystem = nil) + normal_path = normalized_path(path || resolved_path) + filesystem ||= resolved_fs + if filesystem == 'fs' + @path = PosixFile.new(normal_path) + @filesystem = 'fs' + elsif ::Configuration.remote_files_enabled? && filesystem != 'fs' + @path = RemoteFile.new(normal_path, filesystem) + @filesystem = filesystem + else + @path = PosixFile.new(normal_path) + @filesystem = filesystem + raise StandardError, I18n.t('dashboard.files_remote_disabled') + end + end + + def validate_path! + if posix_file? + AllowlistPolicy.default.validate!(@path) + elsif @path.remote_type.nil? + raise StandardError, "Remote #{@path.remote} does not exist" + elsif ::Configuration.allowlist_paths.present? && (@path.remote_type == 'local' || @path.remote_type == 'alias') + # local and alias remotes would allow bypassing the AllowListPolicy + # TODO: Attempt to evaluate the path of them and validate? + raise StandardError, "Remotes of type #{@path.remote_type} are not allowed due to ALLOWLIST_PATH" + end + end + + def posix_file? + @path.is_a?(PosixFile) + end + + def resolved_path + raise NoMethodError, "Must implement resolved_path in #{self.class.to_s} to use Pathable concern" + end + + def resolved_fs + raise NoMethodError, "Must implement resolved_fs in #{self.class.to_s} to use Pathable concern" + end +end diff --git a/apps/dashboard/app/controllers/files_controller.rb b/apps/dashboard/app/controllers/files_controller.rb index 72dbd662e5..502a9ed40c 100644 --- a/apps/dashboard/app/controllers/files_controller.rb +++ b/apps/dashboard/app/controllers/files_controller.rb @@ -3,6 +3,7 @@ # The controller for all the files pages /dashboard/files class FilesController < ApplicationController include ActionController::Live + include Pathable before_action :strip_sendfile_headers, only: [:fs] @@ -39,8 +40,8 @@ def fs end end - # FIXME: below is a large block that should be moved to a model - # if moved to a model the exceptions can be handled there and + # FIXME: below is a large block that should be moved to a concern (Zipable, perhaps?) + # if moved to a concern the exceptions can be handled there and # then this code will be simpler to read # and we can avoid rescuing in a block so we can reintroduce # the block braces which is the Rails convention with the respond_to formats. @@ -192,41 +193,16 @@ def strip_sendfile_headers request.headers['HTTP_X_ACCEL_MAPPING'] = nil end - def normalized_path(path = params[:filepath]) - Pathname.new("/#{path.to_s.chomp('/').delete_prefix('/')}") + # Required for use with Pathable concern (app/controllers/concerns/pathable.rb) + def resolved_path + params[:filepath] end - - def parse_path(path = params[:filepath], filesystem = params[:fs]) - normal_path = normalized_path(path) - if filesystem == 'fs' - @path = PosixFile.new(normal_path) - @filesystem = 'fs' - elsif ::Configuration.remote_files_enabled? && filesystem != 'fs' - @path = RemoteFile.new(normal_path, filesystem) - @filesystem = filesystem - else - @path = PosixFile.new(normal_path) - @filesystem = filesystem - raise StandardError, I18n.t('dashboard.files_remote_disabled') - end - end - - def validate_path! - if posix_file? - AllowlistPolicy.default.validate!(@path) - elsif @path.remote_type.nil? - raise StandardError, "Remote #{@path.remote} does not exist" - elsif ::Configuration.allowlist_paths.present? && (@path.remote_type == 'local' || @path.remote_type == 'alias') - # local and alias remotes would allow bypassing the AllowListPolicy - # TODO: Attempt to evaluate the path of them and validate? - raise StandardError, "Remotes of type #{@path.remote_type} are not allowed due to ALLOWLIST_PATH" - end + + # Required for use with Pathable concern (app/controllers/concerns/pathable.rb) + def resolved_fs + params[:fs] end - - def posix_file? - @path.is_a?(PosixFile) - end - + def download? params[:download] end diff --git a/apps/dashboard/app/controllers/projects_controller.rb b/apps/dashboard/app/controllers/projects_controller.rb index cb77117e73..958186913a 100644 --- a/apps/dashboard/app/controllers/projects_controller.rb +++ b/apps/dashboard/app/controllers/projects_controller.rb @@ -2,10 +2,17 @@ # The controller for project pages /dashboard/projects. class ProjectsController < ApplicationController + include Pathable + # GET /projects/:id def show project_id = show_project_params[:id] @project = Project.find(project_id) + + parse_path + validate_path! + @files = @path.ls + if @project.nil? respond_to do |format| message = I18n.t('dashboard.jobs_project_not_found', project_id: project_id) @@ -27,6 +34,19 @@ def show end end end + + # GET /projects/:project_id/files/*filepath + def files + @project = Project.find(files_params[:project_id]) + parse_path(files_params[:filepath]) + validate_path! + Rails.logger.debug("\n\n\n==============================================================") + Rails.logger.debug("ProjectsController#files: request: #{request.methods.sort}") + Rails.logger.debug("==============================================================\n\n\n") + @files = @path.ls + + render(partial: 'projects/directory', locals: { project_id: @project.id, path: @path, files: @files }) + end # GET /projects def index @@ -162,6 +182,16 @@ def stop_job private + # Required for use with Pathable concern (app/controllers/concerns/pathable.rb) + def resolved_path + @project&.directory.to_s + end + + # Required for use with Pathable concern (app/controllers/concerns/pathable.rb) + def resolved_fs + 'fs' + end + def templates Project.templates.map do |project| label = project.title @@ -179,6 +209,10 @@ def project_params .permit(:name, :directory, :description, :icon, :id, :template) end + def files_params + params.permit(:project_id, :filepath) + end + def show_project_params params.permit(:id) end diff --git a/apps/dashboard/app/javascript/application.js b/apps/dashboard/app/javascript/application.js index b8639950eb..3b3fc068e6 100644 --- a/apps/dashboard/app/javascript/application.js +++ b/apps/dashboard/app/javascript/application.js @@ -20,6 +20,7 @@ import 'datatables.net'; import 'datatables.net-bs4/js/dataTables.bootstrap4'; import 'datatables.net-select/js/dataTables.select'; import 'datatables.net-plugins/api/processing().mjs'; +import "@hotwired/turbo-rails" import Rails from '@rails/ujs'; diff --git a/apps/dashboard/app/views/layouts/application.html.erb b/apps/dashboard/app/views/layouts/application.html.erb index 531b92fe86..613e185fb8 100644 --- a/apps/dashboard/app/views/layouts/application.html.erb +++ b/apps/dashboard/app/views/layouts/application.html.erb @@ -1,3 +1,4 @@ +<%= return "turbo_rails/frame" if turbo_frame_request? %> diff --git a/apps/dashboard/app/views/projects/_directory.html.erb b/apps/dashboard/app/views/projects/_directory.html.erb new file mode 100644 index 0000000000..6e719b1aef --- /dev/null +++ b/apps/dashboard/app/views/projects/_directory.html.erb @@ -0,0 +1,21 @@ +<%= turbo_frame_tag "project_files" do %> + + + + + + + + + + + + + + + <%= render partial: "files", locals: { project_id: project.id, path: path, files: files } %> + +
+ + TypeNameActionsSizeModified atOwnerMode
+<% end %> \ No newline at end of file diff --git a/apps/dashboard/app/views/projects/_files.html.erb b/apps/dashboard/app/views/projects/_files.html.erb new file mode 100644 index 0000000000..14c39c432d --- /dev/null +++ b/apps/dashboard/app/views/projects/_files.html.erb @@ -0,0 +1,54 @@ + + + + + + + + <%= link_to("..", project_files_path(project_id: project_id, filepath: sanitize("#{path}/..")), data: { turbo_frame: "project_files" }) %> + + + + + + + + <% files.each do |file| %> + + + + + + <%= file[:type] %> + + + <%= link_to(file[:name], project_files_path(project_id: project_id, filepath: sanitize("#{path}/#{file[:name]}")), data: { turbo_frame: "project_files" }) %> + + + Actions +
+ + + +
+ + + <%= file[:size] %> + + + <%= file[:modified_at] %> + + + <%= file[:owner] %> + + + <%= file[:mode] %> + + + <%- end -%> \ No newline at end of file diff --git a/apps/dashboard/app/views/projects/show.html.erb b/apps/dashboard/app/views/projects/show.html.erb index 29d1522dc9..c5f2380a79 100644 --- a/apps/dashboard/app/views/projects/show.html.erb +++ b/apps/dashboard/app/views/projects/show.html.erb @@ -60,7 +60,7 @@ -
+

Active Jobs

<%= render(partial: 'job_details', collection: @project.active_jobs, as: :job, locals: { project: @project }) %> @@ -77,6 +77,10 @@
+
+

<%= "#{@project.name} (Project ID: #{@project.id})" %>

+ <%= render partial: 'directory', locals: { project: @project, path: @path, files: @files } %> +
<% unless @project.readme_path.nil? %> diff --git a/apps/dashboard/config/routes.rb b/apps/dashboard/config/routes.rb index 54c639252c..d5e93352d8 100644 --- a/apps/dashboard/config/routes.rb +++ b/apps/dashboard/config/routes.rb @@ -15,6 +15,9 @@ post 'save', on: :member end end + if Configuration.can_access_files? + get 'projects/:project_id/files/*filepath' => 'projects#files', as: 'project_files' + end end # in production, if the user doesn't have access to the files app directory, we hide the routes diff --git a/apps/dashboard/package.json b/apps/dashboard/package.json index 51f03c7e74..7eb1d7cead 100644 --- a/apps/dashboard/package.json +++ b/apps/dashboard/package.json @@ -2,6 +2,7 @@ "name": "openondemand-dashboard", "dependencies": { "@fortawesome/fontawesome-free": "^5.15.4", + "@hotwired/turbo-rails": "^8.0.12", "@popperjs/core": "^2.11.8", "@rails/ujs": "^7.0.1", "@uppy/core": "^4.0", diff --git a/apps/dashboard/yarn.lock b/apps/dashboard/yarn.lock index 19cee67424..4b49dde273 100644 --- a/apps/dashboard/yarn.lock +++ b/apps/dashboard/yarn.lock @@ -12,11 +12,29 @@ resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-5.15.4.tgz#ecda5712b61ac852c760d8b3c79c96adca5554e5" integrity sha512-eYm8vijH/hpzr/6/1CJ/V/Eb1xQFW2nnUKArb3z+yUWv7HTwj6M7SP957oMjfZjAHU6qpoNc2wQvIxBLWYa/Jg== +"@hotwired/turbo-rails@^8.0.12": + version "8.0.12" + resolved "https://registry.yarnpkg.com/@hotwired/turbo-rails/-/turbo-rails-8.0.12.tgz#6f1a2661122c0a2bf717f3bc68b5106638798c89" + integrity sha512-ZXwu9ez+Gd4RQNeHIitqOQgi/LyqY8J4JqsUN0nnYiZDBRq7IreeFdMbz29VdJpIsmYqwooE4cFzPU7QvJkQkA== + dependencies: + "@hotwired/turbo" "^8.0.12" + "@rails/actioncable" "^7.0" + +"@hotwired/turbo@^8.0.12": + version "8.0.12" + resolved "https://registry.yarnpkg.com/@hotwired/turbo/-/turbo-8.0.12.tgz#50aa8345d7f62402680c6d2d9814660761837001" + integrity sha512-l3BiQRkD7qrnQv6ms6sqPLczvwbQpXt5iAVwjDvX0iumrz6yEonQkNAzNjeDX25/OJMFDTxpHjkJZHGpM9ikWw== + "@popperjs/core@^2.11.8": version "2.11.8" resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.8.tgz#6b79032e760a0899cd4204710beede972a3a185f" integrity sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A== +"@rails/actioncable@^7.0": + version "7.2.200" + resolved "https://registry.yarnpkg.com/@rails/actioncable/-/actioncable-7.2.200.tgz#7f56b3313762dbb85b64490aa33c5f431419aafd" + integrity sha512-gVmi3MabEa+Bkatvw0/k1Y3WTidcIf3qNbb9L8qc+AmT2UmkVqUZhJpSLvKmH10twCYIGzn7yySW/lOpg81Duw== + "@rails/ujs@^7.0.1": version "7.1.500" resolved "https://registry.yarnpkg.com/@rails/ujs/-/ujs-7.1.500.tgz#84bb037b6a823ec7fb7782a2ac03452deb505128" From 1ec386d9af8dfa34dcbaa9c095718dab46ef8c3d Mon Sep 17 00:00:00 2001 From: Greg Buchanan Date: Wed, 27 Nov 2024 15:52:45 -0500 Subject: [PATCH 02/13] projects#show directory browser using turbo_frames. --- ...pathable.rb => directory_utils_concern.rb} | 43 ++++++- .../app/controllers/files_controller.rb | 2 +- .../app/controllers/projects_controller.rb | 60 +++++++--- apps/dashboard/app/helpers/projects_helper.rb | 89 +++++++++++++++ apps/dashboard/app/javascript/application.js | 2 + .../app/views/projects/_directory.html.erb | 46 ++++---- .../app/views/projects/_file.html.erb | 26 +++++ .../app/views/projects/_files.html.erb | 107 +++++++++++------- .../projects/_files_column_head.html.erb | 14 +++ .../app/views/projects/show.html.erb | 14 +-- apps/dashboard/config/locales/en.yml | 6 + apps/dashboard/config/locales/ja_JP.yml | 9 ++ apps/dashboard/config/locales/zh-CN.yml | 9 ++ apps/dashboard/config/routes.rb | 3 +- 14 files changed, 335 insertions(+), 95 deletions(-) rename apps/dashboard/app/controllers/concerns/{pathable.rb => directory_utils_concern.rb} (59%) create mode 100644 apps/dashboard/app/views/projects/_file.html.erb create mode 100644 apps/dashboard/app/views/projects/_files_column_head.html.erb diff --git a/apps/dashboard/app/controllers/concerns/pathable.rb b/apps/dashboard/app/controllers/concerns/directory_utils_concern.rb similarity index 59% rename from apps/dashboard/app/controllers/concerns/pathable.rb rename to apps/dashboard/app/controllers/concerns/directory_utils_concern.rb index 57947dceab..834d2bb8f1 100644 --- a/apps/dashboard/app/controllers/concerns/pathable.rb +++ b/apps/dashboard/app/controllers/concerns/directory_utils_concern.rb @@ -1,4 +1,12 @@ -module Pathable +module DirectoryUtilsConcern + # Constants for sorting + ASCENDING = true + DESCENDING = false + # Constants for grouping + DIRECTORIES = true + FILES = false + DEFAULT_SORTING_PARAMS = { col: 'name', direction: ASCENDING, grouped?: true } + extend ActiveSupport::Concern def normalized_path(path) @@ -33,10 +41,41 @@ def validate_path! end end + def set_sorting_params(parameters) + @sorting_params = { + col: parameters[:col], + direction: parameters[:direction], + grouped?: parameters[:grouped?] + } + end + + def set_files + @files = @path.ls + @files = sort_by_column(@files, @sorting_params[:col], @sorting_params[:direction]) + @files = group_by_type(@files) if @sorting_params[:grouped?] + end + + def group_by_type(files) + directories = files.select { |file| file[:directory] } + files.select { |file| !file[:directory] } + end + + def sort_by_column(files, column, direction) + col = column.to_sym + sorted_files = files.sort_by do |file| + if col == :size + file[col].to_i + else + file[col].to_s.downcase + end + end + return sorted_files if direction == ASCENDING + return sorted_files.reverse + end + def posix_file? @path.is_a?(PosixFile) end - + def resolved_path raise NoMethodError, "Must implement resolved_path in #{self.class.to_s} to use Pathable concern" end diff --git a/apps/dashboard/app/controllers/files_controller.rb b/apps/dashboard/app/controllers/files_controller.rb index 502a9ed40c..3edde290d4 100644 --- a/apps/dashboard/app/controllers/files_controller.rb +++ b/apps/dashboard/app/controllers/files_controller.rb @@ -3,7 +3,7 @@ # The controller for all the files pages /dashboard/files class FilesController < ApplicationController include ActionController::Live - include Pathable + include DirectoryUtilsConcern before_action :strip_sendfile_headers, only: [:fs] diff --git a/apps/dashboard/app/controllers/projects_controller.rb b/apps/dashboard/app/controllers/projects_controller.rb index 958186913a..5ae3ba77c6 100644 --- a/apps/dashboard/app/controllers/projects_controller.rb +++ b/apps/dashboard/app/controllers/projects_controller.rb @@ -2,7 +2,7 @@ # The controller for project pages /dashboard/projects. class ProjectsController < ApplicationController - include Pathable + include DirectoryUtilsConcern # GET /projects/:id def show @@ -11,8 +11,9 @@ def show parse_path validate_path! - @files = @path.ls - + set_sorting_params(show_project_params[:sorting_params] || default_sorting_params) + set_files + if @project.nil? respond_to do |format| message = I18n.t('dashboard.jobs_project_not_found', project_id: project_id) @@ -34,20 +35,41 @@ def show end end end - + # GET /projects/:project_id/files/*filepath - def files - @project = Project.find(files_params[:project_id]) - parse_path(files_params[:filepath]) + def directory + @project = Project.find(directory_params[:project_id]) + parse_path("#{directory_params[:dir_path]}") validate_path! - Rails.logger.debug("\n\n\n==============================================================") - Rails.logger.debug("ProjectsController#files: request: #{request.methods.sort}") - Rails.logger.debug("==============================================================\n\n\n") - @files = @path.ls - - render(partial: 'projects/directory', locals: { project_id: @project.id, path: @path, files: @files }) + set_sorting_params(directory_params[:sorting_params] || DEFAULT_SORTING_PARAMS) + set_files + render( partial: 'projects/directory', + locals: { project: @project, + path: @path, + files: @files, + sorting_params: @sorting_params + } + ) end + def file + @project = Project.find(file_params[:project_id]) + parse_path(file_params[:path]) + validate_path! + @file = File.open(@path.to_s, "r") do |file| + file.read + end + + render( partial: 'projects/file', + locals: { + project: @project, + path: @path, + file: @file, + sorting_params: file_params[:sorting_params] + } + ) + end + # GET /projects def index @projects = Project.all @@ -192,6 +214,10 @@ def resolved_fs 'fs' end + def default_sorting_params + DEFAULT_SORTING_PARAMS + end + def templates Project.templates.map do |project| label = project.title @@ -209,8 +235,12 @@ def project_params .permit(:name, :directory, :description, :icon, :id, :template) end - def files_params - params.permit(:project_id, :filepath) + def directory_params + params.permit(:project_id, :format, :dir_path, sorting_params: [:col, :direction, :grouped?]) + end + + def file_params + params.permit(:project_id, :format, :path, :sorting_params) end def show_project_params diff --git a/apps/dashboard/app/helpers/projects_helper.rb b/apps/dashboard/app/helpers/projects_helper.rb index 87df4858d4..7241a4f8fa 100644 --- a/apps/dashboard/app/helpers/projects_helper.rb +++ b/apps/dashboard/app/helpers/projects_helper.rb @@ -31,4 +31,93 @@ def button_category(status) status end end + + def files_button + link_to( + ".../projects#{@path.to_s.split('projects')[1]}", + files_path(fs: 'fs', filepath: @path), + target: '_top', + class: 'link-light' + ).html_safe + end + + # + # + # <%= "Go To Files: .../projects#{@path.to_s.split('projects')[1]}" %> + # <%- if Configuration.project_size_enabled -%> + # + # <%- end -%> + # + + def project_size + + end + + # DRAFT: Remove if not needed + # def group_by_type_link + # group_link_text = "#{@sorting_params[:grouped?] ? 'Ungroup' : 'Group'}" + # group_link_title = @sorting_params[:grouped?] ? 'Ungroup results by type' : 'Group results by type' + # link_to( + # "Group", + # target_path(@sorting_params[:col], !@sorting_params[:grouped?]), + # title: "Group results by type", + # class: "btn btn-1 btn-primary btn-hover btn-sm align-self-end ml-auto", + # data: data_attributes + # ) + # end + + def column_head_link(column) + link_to( + link_text(column), + target_path(column), + title: tool_tip, + class: "text-dark", + data: data_attributes + ) + end + + def direction(column) + if column.to_s == @sorting_params[:col] + @sorting_params[:direction] == ascending ? descending : ascending + else + DirectoryUtilsConcern::ASCENDING + end + end + + def link_text(column) + col_title = t("dashboard.#{column.to_s}") + if column.to_s == @sorting_params[:col] + "#{col_title} #{fa_icon( direction(column) == ascending ? 'sort-up' : 'sort-down', classes: 'fa-md')}".html_safe + else + "#{col_title} #{fa_icon('sort', classes: 'fa-md')}".html_safe + end + end + + def target_path(column, grouped = @sorting_params[:grouped?]) + project_directory_path( + { project_id: @project.id, + dir_path: @path.to_s, + sorting_params: { col: column, + direction: direction(column), + grouped?: grouped + } + } + ) + end + + def tool_tip + "Show #{@path.basename} directory" + end + + def data_attributes + { turbo_frame: 'project_directory' } + end + + def ascending + DirectoryUtilsConcern::ASCENDING + end + + def descending + DirectoryUtilsConcern::DESCENDING + end end diff --git a/apps/dashboard/app/javascript/application.js b/apps/dashboard/app/javascript/application.js index 3b3fc068e6..77caf0877d 100644 --- a/apps/dashboard/app/javascript/application.js +++ b/apps/dashboard/app/javascript/application.js @@ -21,6 +21,8 @@ import 'datatables.net-bs4/js/dataTables.bootstrap4'; import 'datatables.net-select/js/dataTables.select'; import 'datatables.net-plugins/api/processing().mjs'; import "@hotwired/turbo-rails" +import { Turbo } from "@hotwired/turbo-rails" +Turbo.session.drive = false import Rails from '@rails/ujs'; diff --git a/apps/dashboard/app/views/projects/_directory.html.erb b/apps/dashboard/app/views/projects/_directory.html.erb index 6e719b1aef..7263a15e42 100644 --- a/apps/dashboard/app/views/projects/_directory.html.erb +++ b/apps/dashboard/app/views/projects/_directory.html.erb @@ -1,21 +1,27 @@ -<%= turbo_frame_tag "project_files" do %> - - - - - - - - - - - - - - - <%= render partial: "files", locals: { project_id: project.id, path: path, files: files } %> - -
- - TypeNameActionsSizeModified atOwnerMode
+<%= turbo_frame_tag "project_directory" do %> +
+
+ .../projects<%= @path.to_s.split('projects')[1] %> +
+ + + + + + + + + + + + + + <%= render partial: "files", locals: { project: project, path: path, files: files, sorting_params: sorting_params } %> + +
+
+  <%= files_button %> +
+
<%= t('dashboard.type') %><%= column_head_link(:name) %><%= column_head_link(:size) %><%= column_head_link(:date) %><%= column_head_link(:owner) %>Mode
+
<% end %> \ No newline at end of file diff --git a/apps/dashboard/app/views/projects/_file.html.erb b/apps/dashboard/app/views/projects/_file.html.erb new file mode 100644 index 0000000000..939ab5f015 --- /dev/null +++ b/apps/dashboard/app/views/projects/_file.html.erb @@ -0,0 +1,26 @@ +<%= turbo_frame_tag "project_directory" do %> + +
+
+
+
+ <%= link_to("", + project_directory_path(project_id: @project.id, dir_path: "#{@path.parent}", sorting_params: @sorting_params), + class: 'fa fa-window-close align-self-start button buttom-sm text-danger', + data: { turbo_frame: "project_directory" } + ) + %>  + .../projects<%= @path.to_s.split('projects')[1] %> +
+
+
+
+
<%= @file %>
+
+
+
+  <%= files_button %> +
+
+
+<%- end -%> \ No newline at end of file diff --git a/apps/dashboard/app/views/projects/_files.html.erb b/apps/dashboard/app/views/projects/_files.html.erb index 14c39c432d..e05f320e0e 100644 --- a/apps/dashboard/app/views/projects/_files.html.erb +++ b/apps/dashboard/app/views/projects/_files.html.erb @@ -1,54 +1,73 @@ + +<%- unless path.to_s == project.directory.to_s -%> - + + + <%= link_to( + "..", + project_directory_path( + project_id: project.id, + dir_path: "#{path.parent}", + sorting_params: sorting_params + ), + title: 'Show parent directory', + data: { turbo_frame: "project_directory" } + ) + %> + - - <%= link_to("..", project_files_path(project_id: project_id, filepath: sanitize("#{path}/..")), data: { turbo_frame: "project_files" }) %> - - - <% files.each do |file| %> - - - - - - <%= file[:type] %> - - - <%= link_to(file[:name], project_files_path(project_id: project_id, filepath: sanitize("#{path}/#{file[:name]}")), data: { turbo_frame: "project_files" }) %> - - - Actions -
- - - -
- - - <%= file[:size] %> - - - <%= file[:modified_at] %> - - - <%= file[:owner] %> - - - <%= file[:mode] %> - - - <%- end -%> \ No newline at end of file +<%- end -%> +<% files.each do |file| %> + + + + + + <%- if file[:directory] -%> + <%= link_to( + file[:name], + project_directory_path( + project_id: project.id, + dir_path: "#{path}/#{file[:name]}", + sorting_params: sorting_params + ), + title: "Show #{file[:name]} directory", + data: { turbo_frame: "project_directory" } + ) + %> + <%- else -%> + <%= link_to( + file[:name], + project_file_path( + project_id: project.id, + path: "#{path}/#{file[:name]}", + sorting_params: sorting_params + ), + title: "Show #{file[:name]}", + data: { turbo_frame: "project_directory" } + ) + %> + <%- end -%> + + + <%= file[:size] %> + + + <%= DateTime.parse(Time.at(file[:date]).to_s).strftime("%F %r") %> + + + <%= file[:owner] %> + + + <%= file[:mode] %> + + +<%- end -%> \ No newline at end of file diff --git a/apps/dashboard/app/views/projects/_files_column_head.html.erb b/apps/dashboard/app/views/projects/_files_column_head.html.erb new file mode 100644 index 0000000000..8b320d785f --- /dev/null +++ b/apps/dashboard/app/views/projects/_files_column_head.html.erb @@ -0,0 +1,14 @@ +<%= link_to( + "Name #{fa_icon( sorting_params["direction"] == controller.class::ASCENDING ? 'caret-up' : 'caret-down', classes: nil)}".html_safe, + project_directory_path( + project_id: project.id, + dir_path: path, + sorting_params: { col: 'name', + direction: sorting_params[:col] == 'name' ? sorting_params[:direction] : controller.class::ASCENDING, + grouped?: sorting_params[:grouped?] + } + ), + title: "Show #{path.basename} directory", + data: { turbo_frame: "project_directory" }, + class: "text-dark" +)%> \ No newline at end of file diff --git a/apps/dashboard/app/views/projects/show.html.erb b/apps/dashboard/app/views/projects/show.html.erb index c5f2380a79..f16de0bc1b 100644 --- a/apps/dashboard/app/views/projects/show.html.erb +++ b/apps/dashboard/app/views/projects/show.html.erb @@ -20,16 +20,6 @@ - -
@@ -78,8 +68,8 @@
-

<%= "#{@project.name} (Project ID: #{@project.id})" %>

- <%= render partial: 'directory', locals: { project: @project, path: @path, files: @files } %> +

<%= "#{t('dashboard.project')} #{t('dashboard.directory')}" %>:  <%= @project.id %>

+ <%= render partial: 'directory', locals: { project: @project, path: @path, files: @files, sorting_params: @sorting_params } %>
diff --git a/apps/dashboard/config/locales/en.yml b/apps/dashboard/config/locales/en.yml index cbe6599f2f..c1cd5f866f 100644 --- a/apps/dashboard/config/locales/en.yml +++ b/apps/dashboard/config/locales/en.yml @@ -322,3 +322,9 @@ en: project: "Project" directory: "Directory" close: "Close" + type: "Type" + name: "Name" + size: "Size" + owner: "Owner" + date: "Date" + mode: "Mode" diff --git a/apps/dashboard/config/locales/ja_JP.yml b/apps/dashboard/config/locales/ja_JP.yml index e3b3282fdf..09c1c8df51 100644 --- a/apps/dashboard/config/locales/ja_JP.yml +++ b/apps/dashboard/config/locales/ja_JP.yml @@ -10,6 +10,15 @@ ja_JP: edit: "編集する" show: "見せる" launch: "起動する" + type: 'タイプ' + name: '名前' + size: "サイズ" + owner: "所有者" + date: "日付" + mode: "モード" + project: "プロジェクト" + directory: "ディレクトリ" + # project: "Project" # directory: "Directory" auto_log_location_title: "ログの場所" \ No newline at end of file diff --git a/apps/dashboard/config/locales/zh-CN.yml b/apps/dashboard/config/locales/zh-CN.yml index bb3c798bdb..48e5f99a49 100644 --- a/apps/dashboard/config/locales/zh-CN.yml +++ b/apps/dashboard/config/locales/zh-CN.yml @@ -151,4 +151,13 @@ zh-CN: edit: "编辑" show: "显示" launch: "启动" + type: "类型" + name: "名称" + size: "大小" + owner: "所有者" + date: "日期" + mode: "模式" + project: "项目" + directory: "目录" + # development_apps_caption: "Sandbox App" diff --git a/apps/dashboard/config/routes.rb b/apps/dashboard/config/routes.rb index d5e93352d8..00c478ae97 100644 --- a/apps/dashboard/config/routes.rb +++ b/apps/dashboard/config/routes.rb @@ -16,7 +16,8 @@ end end if Configuration.can_access_files? - get 'projects/:project_id/files/*filepath' => 'projects#files', as: 'project_files' + get 'projects/:project_id/directory' => 'projects#directory', as: 'project_directory' + get 'projects/:project_id/file' => 'projects#file', as: 'project_file' end end From 08c28a2fdf0192e6ece577e98b0898bafc0ce064 Mon Sep 17 00:00:00 2001 From: Greg Buchanan Date: Thu, 5 Dec 2024 11:44:05 -0500 Subject: [PATCH 03/13] Sorting tweaks and tests. --- .../concerns/directory_utils_concern.rb | 10 +- .../app/controllers/projects_controller.rb | 13 +- apps/dashboard/app/helpers/projects_helper.rb | 43 ++++-- .../app/views/projects/_directory.html.erb | 44 +++--- .../app/views/projects/_file.html.erb | 38 +++-- .../projects/_files_column_head.html.erb | 14 -- .../app/views/projects/show.html.erb | 51 ++++--- apps/dashboard/config/routes.rb | 5 + .../concerns/directory_utils_concern_test.rb | 133 ++++++++++++++++++ 9 files changed, 247 insertions(+), 104 deletions(-) delete mode 100644 apps/dashboard/app/views/projects/_files_column_head.html.erb create mode 100644 apps/dashboard/test/controllers/concerns/directory_utils_concern_test.rb diff --git a/apps/dashboard/app/controllers/concerns/directory_utils_concern.rb b/apps/dashboard/app/controllers/concerns/directory_utils_concern.rb index 834d2bb8f1..126be49445 100644 --- a/apps/dashboard/app/controllers/concerns/directory_utils_concern.rb +++ b/apps/dashboard/app/controllers/concerns/directory_utils_concern.rb @@ -2,9 +2,6 @@ module DirectoryUtilsConcern # Constants for sorting ASCENDING = true DESCENDING = false - # Constants for grouping - DIRECTORIES = true - FILES = false DEFAULT_SORTING_PARAMS = { col: 'name', direction: ASCENDING, grouped?: true } extend ActiveSupport::Concern @@ -42,10 +39,11 @@ def validate_path! end def set_sorting_params(parameters) + Rails.logger.debug("Sorting params: #{parameters}") @sorting_params = { - col: parameters[:col], - direction: parameters[:direction], - grouped?: parameters[:grouped?] + col: parameters&.[](:col), + direction: !parameters&.[](:direction), + grouped?: parameters&.[](:grouped?) } end diff --git a/apps/dashboard/app/controllers/projects_controller.rb b/apps/dashboard/app/controllers/projects_controller.rb index 5ae3ba77c6..81b3fe9068 100644 --- a/apps/dashboard/app/controllers/projects_controller.rb +++ b/apps/dashboard/app/controllers/projects_controller.rb @@ -8,11 +8,8 @@ class ProjectsController < ApplicationController def show project_id = show_project_params[:id] @project = Project.find(project_id) - parse_path validate_path! - set_sorting_params(show_project_params[:sorting_params] || default_sorting_params) - set_files if @project.nil? respond_to do |format| @@ -41,7 +38,9 @@ def directory @project = Project.find(directory_params[:project_id]) parse_path("#{directory_params[:dir_path]}") validate_path! - set_sorting_params(directory_params[:sorting_params] || DEFAULT_SORTING_PARAMS) + + Rails.logger.debug("Sorting params: #{@sorting_params}") + set_sorting_params(directory_params[:sorting_params] || DEFAULT_SORTING_PARAMS ) set_files render( partial: 'projects/directory', locals: { project: @project, @@ -214,10 +213,6 @@ def resolved_fs 'fs' end - def default_sorting_params - DEFAULT_SORTING_PARAMS - end - def templates Project.templates.map do |project| label = project.title @@ -240,7 +235,7 @@ def directory_params end def file_params - params.permit(:project_id, :format, :path, :sorting_params) + params.permit(:project_id, :format, :path, sorting_params: [:col, :direction, :grouped?]) end def show_project_params diff --git a/apps/dashboard/app/helpers/projects_helper.rb b/apps/dashboard/app/helpers/projects_helper.rb index 7241a4f8fa..5abfe103c9 100644 --- a/apps/dashboard/app/helpers/projects_helper.rb +++ b/apps/dashboard/app/helpers/projects_helper.rb @@ -66,40 +66,53 @@ def project_size # ) # end - def column_head_link(column) - link_to( - link_text(column), - target_path(column), + def column_head_link(column, sorting_params) + a = link_to( + link_text(column, sorting_params), + target_path(column, sorting_params), title: tool_tip, class: "text-dark", data: data_attributes ) + + Rails.logger.debug("\n\n\n\n\n============== #{column} ===================") + Rails.logger.debug("Column head link: #{a}") + Rails.logger.debug("========================================\n\n\n\n\n") + a end - def direction(column) - if column.to_s == @sorting_params[:col] - @sorting_params[:direction] == ascending ? descending : ascending - else - DirectoryUtilsConcern::ASCENDING + def direction(column, sorting_params) + if column.to_s == sorting_params[:col].to_s + Rails.logger.debug("\n\n\n\n\n______________--------============-----------______________") + Rails.logger.debug(" COLUMN: #{column}") + Rails.logger.debug(" is #{column.to_s == sorting_params[:col] ? 'EQUAL' : 'NOT EQUAL'} to") + Rails.logger.debug(" SP COL: #{sorting_params[:col]}") + Rails.logger.debug(" RETURNING: descending") if column.to_s == sorting_params[:col].to_s && sorting_params[:direction] == ascending + + Rails.logger.debug("--------------========____________===========--------------\n\n\n\n\n") + end + if column.to_s == sorting_params[:col].to_s + !sorting_params[:direction] end + ascending end - def link_text(column) + def link_text(column, sorting_params) col_title = t("dashboard.#{column.to_s}") - if column.to_s == @sorting_params[:col] - "#{col_title} #{fa_icon( direction(column) == ascending ? 'sort-up' : 'sort-down', classes: 'fa-md')}".html_safe + if column.to_s == sorting_params[:col] + "#{col_title} #{fa_icon( direction(column, sorting_params) == ascending ? 'sort-up' : 'sort-down', classes: 'fa-md')}".html_safe else "#{col_title} #{fa_icon('sort', classes: 'fa-md')}".html_safe end end - def target_path(column, grouped = @sorting_params[:grouped?]) + def target_path(column, sorting_params) project_directory_path( { project_id: @project.id, dir_path: @path.to_s, sorting_params: { col: column, - direction: direction(column), - grouped?: grouped + direction: direction(column, sorting_params), + grouped?: sorting_params[:grouped] } } ) diff --git a/apps/dashboard/app/views/projects/_directory.html.erb b/apps/dashboard/app/views/projects/_directory.html.erb index 7263a15e42..cba371a5d2 100644 --- a/apps/dashboard/app/views/projects/_directory.html.erb +++ b/apps/dashboard/app/views/projects/_directory.html.erb @@ -1,27 +1,25 @@ <%= turbo_frame_tag "project_directory" do %> -
-
- .../projects<%= @path.to_s.split('projects')[1] %> +
+ .../projects<%= @path.to_s.split('projects')[1] %> +
+ + + + + + + + + + + + + <%= render partial: "files", locals: { project: project, path: path, files: files, sorting_params: sorting_params } %> + +
<%= t('dashboard.type') %><%= column_head_link(:name, sorting_params) %><%= column_head_link(:size, sorting_params) %><%= column_head_link(:date, sorting_params) %><%= column_head_link(:owner, sorting_params) %>Mode
+
+
+  <%= files_button %>
- - - - - - - - - - - - - - <%= render partial: "files", locals: { project: project, path: path, files: files, sorting_params: sorting_params } %> - -
-
-  <%= files_button %> -
-
<%= t('dashboard.type') %><%= column_head_link(:name) %><%= column_head_link(:size) %><%= column_head_link(:date) %><%= column_head_link(:owner) %>Mode
<% end %> \ No newline at end of file diff --git a/apps/dashboard/app/views/projects/_file.html.erb b/apps/dashboard/app/views/projects/_file.html.erb index 939ab5f015..d6fdb34331 100644 --- a/apps/dashboard/app/views/projects/_file.html.erb +++ b/apps/dashboard/app/views/projects/_file.html.erb @@ -1,26 +1,24 @@ <%= turbo_frame_tag "project_directory" do %> - -
-
-
-
- <%= link_to("", - project_directory_path(project_id: @project.id, dir_path: "#{@path.parent}", sorting_params: @sorting_params), - class: 'fa fa-window-close align-self-start button buttom-sm text-danger', - data: { turbo_frame: "project_directory" } - ) - %>  - .../projects<%= @path.to_s.split('projects')[1] %> -
+
+
+
+ <%= link_to("", + project_directory_path(project_id: @project.id, dir_path: "#{@path.parent}", sorting_params: @sorting_params), + class: 'fa fa-window-close align-self-start button buttom-sm text-danger', + data: { turbo_frame: "project_directory" } + ) + %>  + .../projects<%= @path.to_s.split('projects')[1] %>
-
-
<%= @file %>
-
-
-
-  <%= files_button %> -
+
+
+
<%= @file %>
+
+
+
+
+  <%= files_button %>
<%- end -%> \ No newline at end of file diff --git a/apps/dashboard/app/views/projects/_files_column_head.html.erb b/apps/dashboard/app/views/projects/_files_column_head.html.erb deleted file mode 100644 index 8b320d785f..0000000000 --- a/apps/dashboard/app/views/projects/_files_column_head.html.erb +++ /dev/null @@ -1,14 +0,0 @@ -<%= link_to( - "Name #{fa_icon( sorting_params["direction"] == controller.class::ASCENDING ? 'caret-up' : 'caret-down', classes: nil)}".html_safe, - project_directory_path( - project_id: project.id, - dir_path: path, - sorting_params: { col: 'name', - direction: sorting_params[:col] == 'name' ? sorting_params[:direction] : controller.class::ASCENDING, - grouped?: sorting_params[:grouped?] - } - ), - title: "Show #{path.basename} directory", - data: { turbo_frame: "project_directory" }, - class: "text-dark" -)%> \ No newline at end of file diff --git a/apps/dashboard/app/views/projects/show.html.erb b/apps/dashboard/app/views/projects/show.html.erb index f16de0bc1b..54b1e6a292 100644 --- a/apps/dashboard/app/views/projects/show.html.erb +++ b/apps/dashboard/app/views/projects/show.html.erb @@ -8,7 +8,7 @@
-
+
<%= link_to 'Back', projects_path, class: 'btn btn-default align-self-start', title: 'Return to projects page' %>
@@ -21,12 +21,12 @@
-
-
+
+
- <%= t('dashboard.jobs_launchers') %> + <%= t('dashboard.jobs_launchers') %>
@@ -51,25 +51,42 @@
-
-

Active Jobs

- <%= render(partial: 'job_details', collection: @project.active_jobs, as: :job, locals: { project: @project }) %> -
+
+
+

Active Jobs

+ <%= render(partial: 'job_details', collection: @project.active_jobs, as: :job, locals: { project: @project }) %> +
-
-

Completed Jobs

-
- <%- @project.completed_jobs.each do |job| -%> -
"> - <%= render(partial: 'job_details_content', locals: { job: job, project: @project }) %> +
+

Completed Jobs

+
+ <%- @project.completed_jobs.each do |job| -%> +
"> + <%= render(partial: 'job_details_content', locals: { job: job, project: @project }) %> +
+ <%- end -%>
- <%- end -%>
-

<%= "#{t('dashboard.project')} #{t('dashboard.directory')}" %>:  <%= @project.id %>

- <%= render partial: 'directory', locals: { project: @project, path: @path, files: @files, sorting_params: @sorting_params } %> +
+

<%= "#{t('dashboard.project')} #{t('dashboard.directory')}" %>:  <%= @project.id %>

+
+ <%= turbo_frame_tag "project_directory", + src: project_directory_path( + project_id: @project.id, + dir_path: @path, + sorting_params: @sorting_params + ) do + %> +
+
+ Loading... +
+
+ <%- end -%> +
diff --git a/apps/dashboard/config/routes.rb b/apps/dashboard/config/routes.rb index 00c478ae97..12a35cdcf5 100644 --- a/apps/dashboard/config/routes.rb +++ b/apps/dashboard/config/routes.rb @@ -35,6 +35,11 @@ :format => false put 'files/api/v1/:fs/*filepath' => 'files#update', :format => false, :defaults => { :fs => 'fs', :format => 'json' } + + if Configuration.can_access_files? + get 'files/directory' => 'files#directory', as: 'files_directory' + get 'files/file' => 'files#file', as: 'files_display_file' + end end post 'files/upload/:fs' => 'files#upload', :defaults => { :fs => 'fs' } if Configuration.upload_enabled? diff --git a/apps/dashboard/test/controllers/concerns/directory_utils_concern_test.rb b/apps/dashboard/test/controllers/concerns/directory_utils_concern_test.rb new file mode 100644 index 0000000000..dd2096e90e --- /dev/null +++ b/apps/dashboard/test/controllers/concerns/directory_utils_concern_test.rb @@ -0,0 +1,133 @@ +require 'test_helper' + +class DirectoryUtilsConcernTest < ActiveSupport::TestCase + class DummyController + include DirectoryUtilsConcern + + attr_accessor :resolved_path_value, :resolved_fs_value + + def resolved_path + resolved_path_value + end + + def resolved_fs + resolved_fs_value + end + end + + def setup + @controller = DummyController.new + end + + test 'parse_path with filesystem fs' do + @controller.resolved_path_value = '/some/path' + @controller.resolved_fs_value = 'fs' + + @controller.parse_path + + assert_instance_of PosixFile, @controller.instance_variable_get(:@path) + assert_equal 'fs', @controller.instance_variable_get(:@filesystem) + end + + test 'parse_path with remote filesystem when enabled' do + @controller.resolved_path_value = '/remote/path' + @controller.resolved_fs_value = 'remote_fs' + Configuration.stubs(:remote_files_enabled?).returns(true) + + @controller.parse_path + + assert_instance_of RemoteFile, @controller.instance_variable_get(:@path) + assert_equal 'remote_fs', @controller.instance_variable_get(:@filesystem) + end + + test 'parse_path raises error when remote files are disabled' do + @controller.resolved_path_value = '/remote/path' + @controller.resolved_fs_value = 'remote_fs' + Configuration.stubs(:remote_files_enabled?).returns(false) + + assert_raises(StandardError, 'Remote files are disabled') do + @controller.parse_path + end + end + + test 'validate_path! calls AllowlistPolicy when posix_file?' do + @controller.stubs(:posix_file?).returns(true) + @controller.instance_variable_set(:@path, mock('PosixFile')) + AllowlistPolicy.default.expects(:validate!).with(@controller.instance_variable_get(:@path)) + + @controller.validate_path! + end + + test 'validate_path! raises error when remote_type is nil' do + @controller.stubs(:posix_file?).returns(false) + remote_path = mock('RemoteFile') + remote_path.stubs(:remote_type).returns(nil) + remote_path.stubs(:remote).returns('nonexistent_remote') + @controller.instance_variable_set(:@path, remote_path) + + error = assert_raises(StandardError) { @controller.validate_path! } + assert_equal 'Remote nonexistent_remote does not exist', error.message + end + + test 'validate_path! raises error when allowlist_paths is present and remote_type is local' do + @controller.stubs(:posix_file?).returns(false) + remote_path = mock('RemoteFile') + remote_path.stubs(:remote_type).returns('local') + @controller.instance_variable_set(:@path, remote_path) + Configuration.stubs(:allowlist_paths).returns(['/some/path']) + + error = assert_raises(StandardError) { @controller.validate_path! } + assert_equal 'Remotes of type local are not allowed due to ALLOWLIST_PATH', error.message + end + + test 'validate_path! raises error when allowlist_paths is present and remote_type is alias' do + @controller.stubs(:posix_file?).returns(false) + remote_path = mock('RemoteFile') + remote_path.stubs(:remote_type).returns('alias') + @controller.instance_variable_set(:@path, remote_path) + Configuration.stubs(:allowlist_paths).returns(['/some/path']) + + error = assert_raises(StandardError) { @controller.validate_path! } + assert_equal 'Remotes of type alias are not allowed due to ALLOWLIST_PATH', error.message + end + + test 'validate_path! passes when allowlist_paths is not present and remote_type is acceptable' do + @controller.stubs(:posix_file?).returns(false) + remote_path = mock('RemoteFile') + remote_path.stubs(:remote_type).returns('sshfs') + @controller.instance_variable_set(:@path, remote_path) + Configuration.stubs(:allowlist_paths).returns([]) + + assert_nothing_raised { @controller.validate_path! } + end + + test 'set_sorting_params sets @sorting_params correctly with valid parameters' do + parameters = { col: 'name', direction: DirectoryUtilsConcern::ASCENDING, grouped?: true } + @controller.set_sorting_params(parameters) + expected_params = { col: 'name', direction: DirectoryUtilsConcern::ASCENDING, grouped?: true } + assert_equal expected_params, @controller.instance_variable_get(:@sorting_params) + end + + test 'set_sorting_params sets @sorting_params with missing grouped? parameter' do + parameters = { col: 'size', direction: DirectoryUtilsConcern::DESCENDING } + @controller.set_sorting_params(parameters) + expected_params = { col: 'size', direction: DirectoryUtilsConcern::DESCENDING, grouped?: true } + assert_equal expected_params, @controller.instance_variable_get(:@sorting_params) + end + + test 'set_sorting_params sets @sorting_params with missing direction parameter' do + parameters = { col: 'modified_at', grouped?: false } + @controller.set_sorting_params(parameters) + expected_params = { col: 'modified_at', direction: true, grouped?: false } + assert_equal expected_params, @controller.instance_variable_get(:@sorting_params) + end + + test 'set_sorting_params sets @sorting_params with empty parameters' do + parameters = {} + @controller.set_sorting_params(parameters) + expected_params = { col: "name", direction: true, grouped?: true } + assert_equal expected_params, @controller.instance_variable_get(:@sorting_params) + end + + +end \ No newline at end of file From e5a7f86dd21876d94d8bb269465154fc312d2839 Mon Sep 17 00:00:00 2001 From: Greg Buchanan Date: Thu, 5 Dec 2024 13:02:30 -0500 Subject: [PATCH 04/13] remove debug logging --- .../concerns/directory_utils_concern.rb | 7 +++--- .../app/controllers/projects_controller.rb | 1 - apps/dashboard/app/helpers/projects_helper.rb | 24 ++++--------------- 3 files changed, 7 insertions(+), 25 deletions(-) diff --git a/apps/dashboard/app/controllers/concerns/directory_utils_concern.rb b/apps/dashboard/app/controllers/concerns/directory_utils_concern.rb index 126be49445..87bdb932e3 100644 --- a/apps/dashboard/app/controllers/concerns/directory_utils_concern.rb +++ b/apps/dashboard/app/controllers/concerns/directory_utils_concern.rb @@ -39,11 +39,10 @@ def validate_path! end def set_sorting_params(parameters) - Rails.logger.debug("Sorting params: #{parameters}") @sorting_params = { - col: parameters&.[](:col), - direction: !parameters&.[](:direction), - grouped?: parameters&.[](:grouped?) + col: parameters&.[](:col) || DEFAULT_SORTING_PARAMS[:col], + direction: !parameters&.[](:direction) || DEFAULT_SORTING_PARAMS[:direction], + grouped?: parameters&.[](:grouped?) || DEFAULT_SORTING_PARAMS[:grouped?] } end diff --git a/apps/dashboard/app/controllers/projects_controller.rb b/apps/dashboard/app/controllers/projects_controller.rb index 9786a4e669..5cbd8a67fa 100644 --- a/apps/dashboard/app/controllers/projects_controller.rb +++ b/apps/dashboard/app/controllers/projects_controller.rb @@ -39,7 +39,6 @@ def directory parse_path("#{directory_params[:dir_path]}") validate_path! - Rails.logger.debug("Sorting params: #{@sorting_params}") set_sorting_params(directory_params[:sorting_params] || DEFAULT_SORTING_PARAMS ) set_files render( partial: 'projects/directory', diff --git a/apps/dashboard/app/helpers/projects_helper.rb b/apps/dashboard/app/helpers/projects_helper.rb index 5abfe103c9..1610b583e1 100644 --- a/apps/dashboard/app/helpers/projects_helper.rb +++ b/apps/dashboard/app/helpers/projects_helper.rb @@ -67,42 +67,26 @@ def project_size # end def column_head_link(column, sorting_params) - a = link_to( + link_to( link_text(column, sorting_params), target_path(column, sorting_params), title: tool_tip, class: "text-dark", data: data_attributes ) - - Rails.logger.debug("\n\n\n\n\n============== #{column} ===================") - Rails.logger.debug("Column head link: #{a}") - Rails.logger.debug("========================================\n\n\n\n\n") - a end def direction(column, sorting_params) - if column.to_s == sorting_params[:col].to_s - Rails.logger.debug("\n\n\n\n\n______________--------============-----------______________") - Rails.logger.debug(" COLUMN: #{column}") - Rails.logger.debug(" is #{column.to_s == sorting_params[:col] ? 'EQUAL' : 'NOT EQUAL'} to") - Rails.logger.debug(" SP COL: #{sorting_params[:col]}") - Rails.logger.debug(" RETURNING: descending") if column.to_s == sorting_params[:col].to_s && sorting_params[:direction] == ascending - - Rails.logger.debug("--------------========____________===========--------------\n\n\n\n\n") - end - if column.to_s == sorting_params[:col].to_s - !sorting_params[:direction] - end + return !sorting_params[:direction] if column.to_s == sorting_params[:col].to_s ascending end def link_text(column, sorting_params) col_title = t("dashboard.#{column.to_s}") if column.to_s == sorting_params[:col] - "#{col_title} #{fa_icon( direction(column, sorting_params) == ascending ? 'sort-up' : 'sort-down', classes: 'fa-md')}".html_safe + "#{col_title} #{ fa_icon(direction(column, sorting_params) == ascending ? 'sort-up' : 'sort-down', classes: 'fa-md') }".html_safe else - "#{col_title} #{fa_icon('sort', classes: 'fa-md')}".html_safe + "#{col_title} #{ fa_icon('sort', classes: 'fa-md') }".html_safe end end From 9b5c0bd5f346c30f59811d6b9aa92726323cb47a Mon Sep 17 00:00:00 2001 From: Greg Buchanan Date: Thu, 5 Dec 2024 17:18:51 -0500 Subject: [PATCH 05/13] More tests --- .../concerns/directory_utils_concern.rb | 8 +- apps/dashboard/app/helpers/projects_helper.rb | 4 +- .../concerns/directory_utils_concern_test.rb | 195 +++++++++++++++++- 3 files changed, 192 insertions(+), 15 deletions(-) diff --git a/apps/dashboard/app/controllers/concerns/directory_utils_concern.rb b/apps/dashboard/app/controllers/concerns/directory_utils_concern.rb index 87bdb932e3..fa12c88ffd 100644 --- a/apps/dashboard/app/controllers/concerns/directory_utils_concern.rb +++ b/apps/dashboard/app/controllers/concerns/directory_utils_concern.rb @@ -40,9 +40,9 @@ def validate_path! def set_sorting_params(parameters) @sorting_params = { - col: parameters&.[](:col) || DEFAULT_SORTING_PARAMS[:col], - direction: !parameters&.[](:direction) || DEFAULT_SORTING_PARAMS[:direction], - grouped?: parameters&.[](:grouped?) || DEFAULT_SORTING_PARAMS[:grouped?] + col: parameters&.[](:col).nil? ? DEFAULT_SORTING_PARAMS[:col] : parameters[:col], + direction: parameters&.[](:direction).nil? ? DEFAULT_SORTING_PARAMS[:direction] : parameters[:direction], + grouped?: parameters&.[](:grouped?).nil? ? DEFAULT_SORTING_PARAMS[:grouped?] : parameters[:grouped?] } end @@ -59,7 +59,7 @@ def group_by_type(files) def sort_by_column(files, column, direction) col = column.to_sym sorted_files = files.sort_by do |file| - if col == :size + if col == :size || col == :date file[col].to_i else file[col].to_s.downcase diff --git a/apps/dashboard/app/helpers/projects_helper.rb b/apps/dashboard/app/helpers/projects_helper.rb index 1610b583e1..b249a017ca 100644 --- a/apps/dashboard/app/helpers/projects_helper.rb +++ b/apps/dashboard/app/helpers/projects_helper.rb @@ -84,7 +84,7 @@ def direction(column, sorting_params) def link_text(column, sorting_params) col_title = t("dashboard.#{column.to_s}") if column.to_s == sorting_params[:col] - "#{col_title} #{ fa_icon(direction(column, sorting_params) == ascending ? 'sort-up' : 'sort-down', classes: 'fa-md') }".html_safe + "#{col_title} #{ fa_icon(sorting_params[:direction] == ascending ? 'sort-up' : 'sort-down', classes: 'fa-md') }".html_safe else "#{col_title} #{ fa_icon('sort', classes: 'fa-md') }".html_safe end @@ -96,7 +96,7 @@ def target_path(column, sorting_params) dir_path: @path.to_s, sorting_params: { col: column, direction: direction(column, sorting_params), - grouped?: sorting_params[:grouped] + grouped?: sorting_params[:grouped] || ascending } } ) diff --git a/apps/dashboard/test/controllers/concerns/directory_utils_concern_test.rb b/apps/dashboard/test/controllers/concerns/directory_utils_concern_test.rb index dd2096e90e..d18fe86565 100644 --- a/apps/dashboard/test/controllers/concerns/directory_utils_concern_test.rb +++ b/apps/dashboard/test/controllers/concerns/directory_utils_concern_test.rb @@ -17,6 +17,83 @@ def resolved_fs def setup @controller = DummyController.new + @date4 = 2.hours.ago.to_i.to_s + @date3 = 2.days.ago.to_i.to_s + @date2 = 2.weeks.ago.to_i.to_s + @date1 = 2.months.ago.to_i.to_s + end + + # Tests for DirectoryUtilsConcern#normalized_path + test 'normalized_path with empty path' do + path = @controller.normalized_path('') + assert_equal '/', path.to_s + end + + test 'normalized_path with root path' do + path = @controller.normalized_path('/') + assert_equal '/', path.to_s + end + + test 'normalized_path with posix path' do + path = @controller.normalized_path('/foo/bar/file.txt') + assert_equal '/foo/bar/file.txt', path.to_s + end + + test 'normalized_path with posix path without slash' do + path = @controller.normalized_path('foo/bar') + assert_equal '/foo/bar', path.to_s + end + + # Tests for DirectoryUtilsConcern#parse_path + test 'parse_path with empty path' do + @controller.resolved_path_value = '' + @controller.resolved_fs_value = 'fs' + + @controller.parse_path + + assert_instance_of PosixFile, @controller.instance_variable_get(:@path) + assert_equal 'fs', @controller.instance_variable_get(:@filesystem) + end + + test 'parse_path with root path' do + @controller.resolved_path_value = '/' + @controller.resolved_fs_value = 'fs' + + @controller.parse_path + + assert_instance_of PosixFile, @controller.instance_variable_get(:@path) + assert_equal 'fs', @controller.instance_variable_get(:@filesystem) + end + + test 'parse_path with posix path' do + @controller.resolved_path_value = '/foo/bar/file.txt' + @controller.resolved_fs_value = 'fs' + + @controller.parse_path + + assert_instance_of PosixFile, @controller.instance_variable_get(:@path) + assert_equal 'fs', @controller.instance_variable_get(:@filesystem) + end + + test 'parse_path with posix path without slash' do + @controller.resolved_path_value = 'foo/bar' + @controller.resolved_fs_value = 'fs' + + @controller.parse_path + + assert_instance_of PosixFile, @controller.instance_variable_get(:@path) + assert_equal 'fs', @controller.instance_variable_get(:@filesystem) + end + + test 'parse_path with empty remote path' do + @controller.resolved_path_value = '' + @controller.resolved_fs_value = 'remote_fs' + Configuration.stubs(:remote_files_enabled?).returns(true) + + @controller.parse_path + + assert_instance_of RemoteFile, @controller.instance_variable_get(:@path) + assert_equal 'remote_fs', @controller.instance_variable_get(:@filesystem) end test 'parse_path with filesystem fs' do @@ -50,14 +127,7 @@ def setup end end - test 'validate_path! calls AllowlistPolicy when posix_file?' do - @controller.stubs(:posix_file?).returns(true) - @controller.instance_variable_set(:@path, mock('PosixFile')) - AllowlistPolicy.default.expects(:validate!).with(@controller.instance_variable_get(:@path)) - - @controller.validate_path! - end - + # Tests for DirectoryUtilsConcern#validate_path! test 'validate_path! raises error when remote_type is nil' do @controller.stubs(:posix_file?).returns(false) remote_path = mock('RemoteFile') @@ -101,6 +171,7 @@ def setup assert_nothing_raised { @controller.validate_path! } end + # Tests for DirectoryUtilsConcern#sort_by_column test 'set_sorting_params sets @sorting_params correctly with valid parameters' do parameters = { col: 'name', direction: DirectoryUtilsConcern::ASCENDING, grouped?: true } @controller.set_sorting_params(parameters) @@ -108,6 +179,13 @@ def setup assert_equal expected_params, @controller.instance_variable_get(:@sorting_params) end + test 'set_sorting_params sets @sorting_params correctly with descending sort direction' do + parameters = { col: 'name', direction: DirectoryUtilsConcern::DESCENDING, grouped?: true } + @controller.set_sorting_params(parameters) + expected_params = { col: 'name', direction: DirectoryUtilsConcern::DESCENDING, grouped?: true } + assert_equal expected_params, @controller.instance_variable_get(:@sorting_params) + end + test 'set_sorting_params sets @sorting_params with missing grouped? parameter' do parameters = { col: 'size', direction: DirectoryUtilsConcern::DESCENDING } @controller.set_sorting_params(parameters) @@ -122,12 +200,111 @@ def setup assert_equal expected_params, @controller.instance_variable_get(:@sorting_params) end - test 'set_sorting_params sets @sorting_params with empty parameters' do + test 'set_sorting_params sets @sorting_params with empty parameters' do parameters = {} @controller.set_sorting_params(parameters) expected_params = { col: "name", direction: true, grouped?: true } assert_equal expected_params, @controller.instance_variable_get(:@sorting_params) end + # Tests for DirectoryUtilsConcern#set_files + test 'set_files sets @files correctly' do + path = mock('PosixFile') + path.stubs(:ls).returns([{ name: 'file1', directory: false }, { name: 'dir1', directory: true }]) + @controller.instance_variable_set(:@path, path) + @controller.instance_variable_set(:@sorting_params, { col: 'name', direction: true, grouped?: true }) + + @controller.set_files + + files = @controller.instance_variable_get(:@files) + assert_equal [{ name: 'dir1', directory: true }, { name: 'file1', directory: false }], files + end + + # Tests for DirectoryUtilsConcern#group_by_type + test 'group_by_type groups directories and files' do + files = [ + { name: 'file1', directory: false }, + { name: 'dir1', directory: true }, + { name: 'file2', directory: false }, + { name: 'dir2', directory: true } + ] + + grouped_files = @controller.group_by_type(files) + assert_equal [ + { name: 'dir1', directory: true }, + { name: 'dir2', directory: true }, + { name: 'file1', directory: false }, + { name: 'file2', directory: false } + ], grouped_files + end + + # Tests for DirectoryUtilsConcern#sort_by_column + test 'sort_by_column sorts files by size' do + files = [ + { name: 'file2', size: 100, owner: 'user1', date: @date1 }, + { name: 'file3', size: 25, owner: 'user2', date: @date2 }, + { name: 'file1', size: 50, owner: 'user2', date: @date3 }, + { name: 'file4', size: 75, owner: 'user3', date: @date4 } + ] + + sorted_files = @controller.sort_by_column(files, 'size', DirectoryUtilsConcern::ASCENDING) + assert_equal [ + { name: 'file3', size: 25, owner: 'user2', date: @date2 }, + { name: 'file1', size: 50, owner: 'user2', date: @date3 }, + { name: 'file4', size: 75, owner: 'user3', date: @date4 }, + { name: 'file2', size: 100, owner: 'user1', date: @date1 } + ], sorted_files + end + + test 'sort_by_column sorts files by owner' do + files = [ + { name: 'file3', size: 25, owner: 'user2', date: @date2 }, + { name: 'file4', size: 75, owner: 'user3', date: @date4 }, + { name: 'file2', size: 100, owner: 'user1', date: @date1 }, + { name: 'file1', size: 50, owner: 'user2', date: @date3 } + ] + + sorted_files = @controller.sort_by_column(files, 'owner', DirectoryUtilsConcern::ASCENDING) + assert_equal [ + { name: 'file2', size: 100, owner: 'user1', date: @date1 }, + { name: 'file3', size: 25, owner: 'user2', date: @date2 }, + { name: 'file1', size: 50, owner: 'user2', date: @date3 }, + { name: 'file4', size: 75, owner: 'user3', date: @date4 } + ], sorted_files + end + + test 'sort_by_column sorts files by date' do + files = [ + { name: 'file3', size: 75, owner: 'user3', date: @date3 }, + { name: 'file4', size: 50, owner: 'user2', date: @date4 }, + { name: 'file2', size: 100, owner: 'user1', date: @date2 }, + { name: 'file1', size: 25, owner: 'user2', date: @date1 } + ] + + sorted_files = @controller.sort_by_column(files, 'date', DirectoryUtilsConcern::ASCENDING) + assert_equal [ + { name: 'file1', size: 25, owner: 'user2', date: @date1 }, + { name: 'file2', size: 100, owner: 'user1', date: @date2 }, + { name: 'file3', size: 75, owner: 'user3', date: @date3 }, + { name: 'file4', size: 50, owner: 'user2', date: @date4 } + ], sorted_files + end + + test 'sort_by_column sorts files by name' do + files = [ + { name: 'file3', size: 25, owner: 'user2', date: @date1 }, + { name: 'file1', size: 50, owner: 'user2', date: @date3 }, + { name: 'file4', size: 75, owner: 'user3', date: @date4 }, + { name: 'file2', size: 100, owner: 'user1', date: @date2 } + ] + + sorted_files = @controller.sort_by_column(files, 'name', DirectoryUtilsConcern::ASCENDING) + assert_equal [ + { name: 'file1', size: 50, owner: 'user2', date: @date3 }, + { name: 'file2', size: 100, owner: 'user1', date: @date2 }, + { name: 'file3', size: 25, owner: 'user2', date: @date1 }, + { name: 'file4', size: 75, owner: 'user3', date: @date4 } + ], sorted_files + end end \ No newline at end of file From ad5a854a2c66a2b907d053bf991ddce1551778b0 Mon Sep 17 00:00:00 2001 From: Greg Buchanan Date: Thu, 5 Dec 2024 17:26:52 -0500 Subject: [PATCH 06/13] More tests --- .../concerns/directory_utils_concern_test.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/apps/dashboard/test/controllers/concerns/directory_utils_concern_test.rb b/apps/dashboard/test/controllers/concerns/directory_utils_concern_test.rb index d18fe86565..3e16dc7297 100644 --- a/apps/dashboard/test/controllers/concerns/directory_utils_concern_test.rb +++ b/apps/dashboard/test/controllers/concerns/directory_utils_concern_test.rb @@ -307,4 +307,16 @@ def setup ], sorted_files end + # Tests for DirectoryUtilsConcern#posix_file? + test 'posix_file? returns true when @path is a PosixFile' do + path = PosixFile.new('/some/path') + @controller.instance_variable_set(:@path, path) + assert @controller.posix_file? + end + + test 'posix_file? returns false when @path is a RemoteFile' do + path = RemoteFile.new('/some/path', 'remote_fs') + @controller.instance_variable_set(:@path, path) + refute @controller.posix_file? + end end \ No newline at end of file From 733fc7ed7c992873bb7de4d7ca2366b9b760bc00 Mon Sep 17 00:00:00 2001 From: Greg Buchanan Date: Tue, 10 Dec 2024 12:17:38 -0500 Subject: [PATCH 07/13] Simplify sorting --- .../concerns/directory_utils_concern.rb | 36 +--- .../app/controllers/projects_controller.rb | 13 +- apps/dashboard/app/helpers/projects_helper.rb | 81 ++------- .../app/views/projects/_directory.html.erb | 14 +- .../app/views/projects/_file.html.erb | 2 +- .../app/views/projects/_files.html.erb | 6 +- .../app/views/projects/show.html.erb | 2 +- .../concerns/directory_utils_concern_test.rb | 166 ++++++------------ 8 files changed, 102 insertions(+), 218 deletions(-) diff --git a/apps/dashboard/app/controllers/concerns/directory_utils_concern.rb b/apps/dashboard/app/controllers/concerns/directory_utils_concern.rb index fa12c88ffd..e707714c43 100644 --- a/apps/dashboard/app/controllers/concerns/directory_utils_concern.rb +++ b/apps/dashboard/app/controllers/concerns/directory_utils_concern.rb @@ -1,9 +1,4 @@ module DirectoryUtilsConcern - # Constants for sorting - ASCENDING = true - DESCENDING = false - DEFAULT_SORTING_PARAMS = { col: 'name', direction: ASCENDING, grouped?: true } - extend ActiveSupport::Concern def normalized_path(path) @@ -38,35 +33,22 @@ def validate_path! end end - def set_sorting_params(parameters) - @sorting_params = { - col: parameters&.[](:col).nil? ? DEFAULT_SORTING_PARAMS[:col] : parameters[:col], - direction: parameters&.[](:direction).nil? ? DEFAULT_SORTING_PARAMS[:direction] : parameters[:direction], - grouped?: parameters&.[](:grouped?).nil? ? DEFAULT_SORTING_PARAMS[:grouped?] : parameters[:grouped?] - } - end - - def set_files - @files = @path.ls - @files = sort_by_column(@files, @sorting_params[:col], @sorting_params[:direction]) - @files = group_by_type(@files) if @sorting_params[:grouped?] - end - - def group_by_type(files) - directories = files.select { |file| file[:directory] } + files.select { |file| !file[:directory] } + def set_files(sort_by) + @files = sort_by_column(@path.ls, sort_by) end - def sort_by_column(files, column, direction) + def sort_by_column(files, column) col = column.to_sym sorted_files = files.sort_by do |file| - if col == :size || col == :date - file[col].to_i - else + case col + when :name, :owner file[col].to_s.downcase + when :type + file[:directory] ? 0 : 1 + else + file[col].to_i end end - return sorted_files if direction == ASCENDING - return sorted_files.reverse end def posix_file? diff --git a/apps/dashboard/app/controllers/projects_controller.rb b/apps/dashboard/app/controllers/projects_controller.rb index 5cbd8a67fa..b355eef268 100644 --- a/apps/dashboard/app/controllers/projects_controller.rb +++ b/apps/dashboard/app/controllers/projects_controller.rb @@ -36,16 +36,15 @@ def show # GET /projects/:project_id/files/*filepath def directory @project = Project.find(directory_params[:project_id]) + sort_by = directory_params[:sort_by] || :name parse_path("#{directory_params[:dir_path]}") validate_path! - - set_sorting_params(directory_params[:sorting_params] || DEFAULT_SORTING_PARAMS ) - set_files + set_files(sort_by) render( partial: 'projects/directory', locals: { project: @project, path: @path, files: @files, - sorting_params: @sorting_params + sort_by: sort_by } ) end @@ -63,7 +62,7 @@ def file project: @project, path: @path, file: @file, - sorting_params: file_params[:sorting_params] + sort_by: file_params[:sort_by] } ) end @@ -230,11 +229,11 @@ def project_params end def directory_params - params.permit(:project_id, :format, :dir_path, sorting_params: [:col, :direction, :grouped?]) + params.permit(:project_id, :format, :dir_path, :sort_by) end def file_params - params.permit(:project_id, :format, :path, sorting_params: [:col, :direction, :grouped?]) + params.permit(:project_id, :format, :path, :sort_by) end def show_project_params diff --git a/apps/dashboard/app/helpers/projects_helper.rb b/apps/dashboard/app/helpers/projects_helper.rb index b249a017ca..9a22843025 100644 --- a/apps/dashboard/app/helpers/projects_helper.rb +++ b/apps/dashboard/app/helpers/projects_helper.rb @@ -41,80 +41,33 @@ def files_button ).html_safe end - # - # - # <%= "Go To Files: .../projects#{@path.to_s.split('projects')[1]}" %> - # <%- if Configuration.project_size_enabled -%> - # - # <%- end -%> - # - - def project_size - - end - - # DRAFT: Remove if not needed - # def group_by_type_link - # group_link_text = "#{@sorting_params[:grouped?] ? 'Ungroup' : 'Group'}" - # group_link_title = @sorting_params[:grouped?] ? 'Ungroup results by type' : 'Group results by type' - # link_to( - # "Group", - # target_path(@sorting_params[:col], !@sorting_params[:grouped?]), - # title: "Group results by type", - # class: "btn btn-1 btn-primary btn-hover btn-sm align-self-end ml-auto", - # data: data_attributes - # ) - # end - - def column_head_link(column, sorting_params) + def column_head_link(column, sort_by, path, project_id) link_to( - link_text(column, sorting_params), - target_path(column, sorting_params), - title: tool_tip, - class: "text-dark", - data: data_attributes + header_text(column, sort_by), + target_path(column, path, project_id), + title: "Show #{path.basename} directory", + class: classes(column, sort_by), + data: { turbo_frame: 'project_directory' } ) end - def direction(column, sorting_params) - return !sorting_params[:direction] if column.to_s == sorting_params[:col].to_s - ascending + def header_text(column, sort_by) + "#{t("dashboard.#{column.to_s}")} #{fa_icon(column.to_s == sort_by.to_s ? 'sort-down' : 'sort', classes: 'fa-md')}".html_safe end - def link_text(column, sorting_params) - col_title = t("dashboard.#{column.to_s}") - if column.to_s == sorting_params[:col] - "#{col_title} #{ fa_icon(sorting_params[:direction] == ascending ? 'sort-up' : 'sort-down', classes: 'fa-md') }".html_safe - else - "#{col_title} #{ fa_icon('sort', classes: 'fa-md') }".html_safe - end - end - - def target_path(column, sorting_params) + def target_path(column, path, project_id) project_directory_path( - { project_id: @project.id, - dir_path: @path.to_s, - sorting_params: { col: column, - direction: direction(column, sorting_params), - grouped?: sorting_params[:grouped] || ascending - } + { project_id: project_id, + dir_path: path.to_s, + sort_by: column } ) end - def tool_tip - "Show #{@path.basename} directory" - end - - def data_attributes - { turbo_frame: 'project_directory' } - end - - def ascending - DirectoryUtilsConcern::ASCENDING - end - - def descending - DirectoryUtilsConcern::DESCENDING + def classes(column, sort_by) + Rails.logger.debug("column: #{column.to_s} == sort_by: #{sort_by.to_s} ? #{column.to_s == sort_by.to_s}") + classes = ['btn', 'btn-xs', 'btn-hover'] + classes << (column.to_s == sort_by.to_s ? ['btn-primary'] : ['btn-outline-primary']) + classes.join(' ') end end diff --git a/apps/dashboard/app/views/projects/_directory.html.erb b/apps/dashboard/app/views/projects/_directory.html.erb index cba371a5d2..cad91f8523 100644 --- a/apps/dashboard/app/views/projects/_directory.html.erb +++ b/apps/dashboard/app/views/projects/_directory.html.erb @@ -5,16 +5,16 @@ - - - - - - + + + + + + - <%= render partial: "files", locals: { project: project, path: path, files: files, sorting_params: sorting_params } %> + <%= render partial: "files", locals: { project: project, path: path, files: files, sort_by: sort_by } %>
<%= t('dashboard.type') %><%= column_head_link(:name, sorting_params) %><%= column_head_link(:size, sorting_params) %><%= column_head_link(:date, sorting_params) %><%= column_head_link(:owner, sorting_params) %>Mode<%= column_head_link(:type, sort_by, path, project.id) %><%= column_head_link(:name, sort_by, path, project.id) %><%= column_head_link(:size, sort_by, path, project.id) %><%= column_head_link(:date, sort_by, path, project.id) %><%= column_head_link(:owner, sort_by, path, project.id) %><%= column_head_link(:mode, sort_by, path, project.id) %>
diff --git a/apps/dashboard/app/views/projects/_file.html.erb b/apps/dashboard/app/views/projects/_file.html.erb index d6fdb34331..713f91fb1e 100644 --- a/apps/dashboard/app/views/projects/_file.html.erb +++ b/apps/dashboard/app/views/projects/_file.html.erb @@ -3,7 +3,7 @@
<%= link_to("", - project_directory_path(project_id: @project.id, dir_path: "#{@path.parent}", sorting_params: @sorting_params), + project_directory_path(project_id: @project.id, dir_path: "#{@path.parent}", sort_by: @sort_by), class: 'fa fa-window-close align-self-start button buttom-sm text-danger', data: { turbo_frame: "project_directory" } ) diff --git a/apps/dashboard/app/views/projects/_files.html.erb b/apps/dashboard/app/views/projects/_files.html.erb index e05f320e0e..7ac454a5e3 100644 --- a/apps/dashboard/app/views/projects/_files.html.erb +++ b/apps/dashboard/app/views/projects/_files.html.erb @@ -11,7 +11,7 @@ project_directory_path( project_id: project.id, dir_path: "#{path.parent}", - sorting_params: sorting_params + sort_by: sort_by ), title: 'Show parent directory', data: { turbo_frame: "project_directory" } @@ -37,7 +37,7 @@ project_directory_path( project_id: project.id, dir_path: "#{path}/#{file[:name]}", - sorting_params: sorting_params + sort_by: sort_by ), title: "Show #{file[:name]} directory", data: { turbo_frame: "project_directory" } @@ -49,7 +49,7 @@ project_file_path( project_id: project.id, path: "#{path}/#{file[:name]}", - sorting_params: sorting_params + sort_by: sort_by ), title: "Show #{file[:name]}", data: { turbo_frame: "project_directory" } diff --git a/apps/dashboard/app/views/projects/show.html.erb b/apps/dashboard/app/views/projects/show.html.erb index c48951c7ab..07b9b762ce 100644 --- a/apps/dashboard/app/views/projects/show.html.erb +++ b/apps/dashboard/app/views/projects/show.html.erb @@ -77,7 +77,7 @@ src: project_directory_path( project_id: @project.id, dir_path: @path, - sorting_params: @sorting_params + sort_by: @sort_by ) do %>
diff --git a/apps/dashboard/test/controllers/concerns/directory_utils_concern_test.rb b/apps/dashboard/test/controllers/concerns/directory_utils_concern_test.rb index 3e16dc7297..50a6143c1f 100644 --- a/apps/dashboard/test/controllers/concerns/directory_utils_concern_test.rb +++ b/apps/dashboard/test/controllers/concerns/directory_utils_concern_test.rb @@ -17,10 +17,16 @@ def resolved_fs def setup @controller = DummyController.new - @date4 = 2.hours.ago.to_i.to_s - @date3 = 2.days.ago.to_i.to_s - @date2 = 2.weeks.ago.to_i.to_s @date1 = 2.months.ago.to_i.to_s + @date2 = 2.weeks.ago.to_i.to_s + @date3 = 2.days.ago.to_i.to_s + @date4 = 2.hours.ago.to_i.to_s + @files = files = [ + { id: 'abcd1234', name: 'file1', size: 8166357, directory: false, date: @date2, owner: 'msmith', mode: 33188 }, + { id: 'bcde2345', name: 'dir2', size: nil, directory: true, date: @date4, owner: 'dtenant', mode: 16877 }, + { id: 'cdef3456', name: 'file2', size: 816, directory: false, date: @date3, owner: 'tbaker', mode: 33188 }, + { id: 'defg4567', name: 'dir1', size: nil, directory: true, date: @date1, owner: 'pcapaldi', mode: 16877 } + ] end # Tests for DirectoryUtilsConcern#normalized_path @@ -171,142 +177,86 @@ def setup assert_nothing_raised { @controller.validate_path! } end - # Tests for DirectoryUtilsConcern#sort_by_column - test 'set_sorting_params sets @sorting_params correctly with valid parameters' do - parameters = { col: 'name', direction: DirectoryUtilsConcern::ASCENDING, grouped?: true } - @controller.set_sorting_params(parameters) - expected_params = { col: 'name', direction: DirectoryUtilsConcern::ASCENDING, grouped?: true } - assert_equal expected_params, @controller.instance_variable_get(:@sorting_params) - end - - test 'set_sorting_params sets @sorting_params correctly with descending sort direction' do - parameters = { col: 'name', direction: DirectoryUtilsConcern::DESCENDING, grouped?: true } - @controller.set_sorting_params(parameters) - expected_params = { col: 'name', direction: DirectoryUtilsConcern::DESCENDING, grouped?: true } - assert_equal expected_params, @controller.instance_variable_get(:@sorting_params) - end - - test 'set_sorting_params sets @sorting_params with missing grouped? parameter' do - parameters = { col: 'size', direction: DirectoryUtilsConcern::DESCENDING } - @controller.set_sorting_params(parameters) - expected_params = { col: 'size', direction: DirectoryUtilsConcern::DESCENDING, grouped?: true } - assert_equal expected_params, @controller.instance_variable_get(:@sorting_params) - end - - test 'set_sorting_params sets @sorting_params with missing direction parameter' do - parameters = { col: 'modified_at', grouped?: false } - @controller.set_sorting_params(parameters) - expected_params = { col: 'modified_at', direction: true, grouped?: false } - assert_equal expected_params, @controller.instance_variable_get(:@sorting_params) - end - - test 'set_sorting_params sets @sorting_params with empty parameters' do - parameters = {} - @controller.set_sorting_params(parameters) - expected_params = { col: "name", direction: true, grouped?: true } - assert_equal expected_params, @controller.instance_variable_get(:@sorting_params) - end - # Tests for DirectoryUtilsConcern#set_files test 'set_files sets @files correctly' do path = mock('PosixFile') path.stubs(:ls).returns([{ name: 'file1', directory: false }, { name: 'dir1', directory: true }]) @controller.instance_variable_set(:@path, path) - @controller.instance_variable_set(:@sorting_params, { col: 'name', direction: true, grouped?: true }) + @controller.instance_variable_set(:@sory_by, 'name') - @controller.set_files + @controller.set_files('name') files = @controller.instance_variable_get(:@files) assert_equal [{ name: 'dir1', directory: true }, { name: 'file1', directory: false }], files end - # Tests for DirectoryUtilsConcern#group_by_type - test 'group_by_type groups directories and files' do - files = [ - { name: 'file1', directory: false }, - { name: 'dir1', directory: true }, - { name: 'file2', directory: false }, - { name: 'dir2', directory: true } - ] - - grouped_files = @controller.group_by_type(files) + # Tests for DirectoryUtilsConcern#sort_by_column + test 'sort_by_column sorts by type' do + @files + sorted_files = @controller.sort_by_column(@files, 'type') assert_equal [ - { name: 'dir1', directory: true }, - { name: 'dir2', directory: true }, - { name: 'file1', directory: false }, - { name: 'file2', directory: false } - ], grouped_files + { id: 'bcde2345', name: 'dir2', size: nil, directory: true, date: @date4, owner: 'dtenant', mode: 16877 }, + { id: 'defg4567', name: 'dir1', size: nil, directory: true, date: @date1, owner: 'pcapaldi', mode: 16877 }, + { id: 'abcd1234', name: 'file1', size: 8166357, directory: false, date: @date2, owner: 'msmith', mode: 33188 }, + { id: 'cdef3456', name: 'file2', size: 816, directory: false, date: @date3, owner: 'tbaker', mode: 33188 } + ], sorted_files end - # Tests for DirectoryUtilsConcern#sort_by_column - test 'sort_by_column sorts files by size' do - files = [ - { name: 'file2', size: 100, owner: 'user1', date: @date1 }, - { name: 'file3', size: 25, owner: 'user2', date: @date2 }, - { name: 'file1', size: 50, owner: 'user2', date: @date3 }, - { name: 'file4', size: 75, owner: 'user3', date: @date4 } - ] - - sorted_files = @controller.sort_by_column(files, 'size', DirectoryUtilsConcern::ASCENDING) + test 'sort_by_column sorts by name' do + @files + sorted_files = @controller.sort_by_column(@files, 'name') assert_equal [ - { name: 'file3', size: 25, owner: 'user2', date: @date2 }, - { name: 'file1', size: 50, owner: 'user2', date: @date3 }, - { name: 'file4', size: 75, owner: 'user3', date: @date4 }, - { name: 'file2', size: 100, owner: 'user1', date: @date1 } + { id: 'defg4567', name: 'dir1', size: nil, directory: true, date: @date1, owner: 'pcapaldi', mode: 16877 }, + { id: 'bcde2345', name: 'dir2', size: nil, directory: true, date: @date4, owner: 'dtenant', mode: 16877 }, + { id: 'abcd1234', name: 'file1', size: 8166357, directory: false, date: @date2, owner: 'msmith', mode: 33188 }, + { id: 'cdef3456', name: 'file2', size: 816, directory: false, date: @date3, owner: 'tbaker', mode: 33188 } ], sorted_files end - test 'sort_by_column sorts files by owner' do - files = [ - { name: 'file3', size: 25, owner: 'user2', date: @date2 }, - { name: 'file4', size: 75, owner: 'user3', date: @date4 }, - { name: 'file2', size: 100, owner: 'user1', date: @date1 }, - { name: 'file1', size: 50, owner: 'user2', date: @date3 } - ] - - sorted_files = @controller.sort_by_column(files, 'owner', DirectoryUtilsConcern::ASCENDING) + test 'sort_by_column sorts by size' do + @files + sorted_files = @controller.sort_by_column(@files, 'size') assert_equal [ - { name: 'file2', size: 100, owner: 'user1', date: @date1 }, - { name: 'file3', size: 25, owner: 'user2', date: @date2 }, - { name: 'file1', size: 50, owner: 'user2', date: @date3 }, - { name: 'file4', size: 75, owner: 'user3', date: @date4 } + { id: 'bcde2345', name: 'dir2', size: nil, directory: true, date: @date4, owner: 'dtenant', mode: 16877 }, + { id: 'defg4567', name: 'dir1', size: nil, directory: true, date: @date1, owner: 'pcapaldi', mode: 16877 }, + { id: 'cdef3456', name: 'file2', size: 816, directory: false, date: @date3, owner: 'tbaker', mode: 33188 }, + { id: 'abcd1234', name: 'file1', size: 8166357, directory: false, date: @date2, owner: 'msmith', mode: 33188 } ], sorted_files end - test 'sort_by_column sorts files by date' do - files = [ - { name: 'file3', size: 75, owner: 'user3', date: @date3 }, - { name: 'file4', size: 50, owner: 'user2', date: @date4 }, - { name: 'file2', size: 100, owner: 'user1', date: @date2 }, - { name: 'file1', size: 25, owner: 'user2', date: @date1 } - ] - - sorted_files = @controller.sort_by_column(files, 'date', DirectoryUtilsConcern::ASCENDING) + test 'sort_by_column sorts by date' do + @files + sorted_files = @controller.sort_by_column(@files, 'date') assert_equal [ - { name: 'file1', size: 25, owner: 'user2', date: @date1 }, - { name: 'file2', size: 100, owner: 'user1', date: @date2 }, - { name: 'file3', size: 75, owner: 'user3', date: @date3 }, - { name: 'file4', size: 50, owner: 'user2', date: @date4 } + { id: 'defg4567', name: 'dir1', size: nil, directory: true, date: @date1, owner: 'pcapaldi', mode: 16877 }, + { id: 'abcd1234', name: 'file1', size: 8166357, directory: false, date: @date2, owner: 'msmith', mode: 33188 }, + { id: 'cdef3456', name: 'file2', size: 816, directory: false, date: @date3, owner: 'tbaker', mode: 33188 }, + { id: 'bcde2345', name: 'dir2', size: nil, directory: true, date: @date4, owner: 'dtenant', mode: 16877 } ], sorted_files end - test 'sort_by_column sorts files by name' do - files = [ - { name: 'file3', size: 25, owner: 'user2', date: @date1 }, - { name: 'file1', size: 50, owner: 'user2', date: @date3 }, - { name: 'file4', size: 75, owner: 'user3', date: @date4 }, - { name: 'file2', size: 100, owner: 'user1', date: @date2 } - ] + test 'sort_by_column sorts by owner' do + @files + sorted_files = @controller.sort_by_column(@files, 'owner') + assert_equal [ + { id: 'bcde2345', name: 'dir2', size: nil, directory: true, date: @date4, owner: 'dtenant', mode: 16877 }, + { id: 'abcd1234', name: 'file1', size: 8166357, directory: false, date: @date2, owner: 'msmith', mode: 33188 }, + { id: 'defg4567', name: 'dir1', size: nil, directory: true, date: @date1, owner: 'pcapaldi', mode: 16877 }, + { id: 'cdef3456', name: 'file2', size: 816, directory: false, date: @date3, owner: 'tbaker', mode: 33188 } + ], sorted_files + end - sorted_files = @controller.sort_by_column(files, 'name', DirectoryUtilsConcern::ASCENDING) + test 'sort_by_column sorts by mode' do + sorted_files = @controller.sort_by_column(@files, 'mode') assert_equal [ - { name: 'file1', size: 50, owner: 'user2', date: @date3 }, - { name: 'file2', size: 100, owner: 'user1', date: @date2 }, - { name: 'file3', size: 25, owner: 'user2', date: @date1 }, - { name: 'file4', size: 75, owner: 'user3', date: @date4 } + { id: 'bcde2345', name: 'dir2', size: nil, directory: true, date: @date4, owner: 'dtenant', mode: 16877 }, + { id: 'defg4567', name: 'dir1', size: nil, directory: true, date: @date1, owner: 'pcapaldi', mode: 16877 }, + { id: 'abcd1234', name: 'file1', size: 8166357, directory: false, date: @date2, owner: 'msmith', mode: 33188 }, + { id: 'cdef3456', name: 'file2', size: 816, directory: false, date: @date3, owner: 'tbaker', mode: 33188 } ], sorted_files end + # Tests for DirectoryUtilsConcern#posix_file? test 'posix_file? returns true when @path is a PosixFile' do path = PosixFile.new('/some/path') From 11fed663be48dfc834c05cbcd379011fb76bbe4c Mon Sep 17 00:00:00 2001 From: Greg Buchanan Date: Tue, 10 Dec 2024 12:41:39 -0500 Subject: [PATCH 08/13] Test fix --- apps/dashboard/app/views/projects/_directory.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/dashboard/app/views/projects/_directory.html.erb b/apps/dashboard/app/views/projects/_directory.html.erb index cad91f8523..c552bf2b85 100644 --- a/apps/dashboard/app/views/projects/_directory.html.erb +++ b/apps/dashboard/app/views/projects/_directory.html.erb @@ -19,7 +19,7 @@
-  <%= files_button %> +  <%= files_button %>
<% end %> \ No newline at end of file From 7155c7e266aff4fe61e120f39e972f2c64fec9c4 Mon Sep 17 00:00:00 2001 From: Greg Buchanan Date: Tue, 10 Dec 2024 14:28:26 -0500 Subject: [PATCH 09/13] fix broken test --- apps/dashboard/test/system/project_manager_test.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/dashboard/test/system/project_manager_test.rb b/apps/dashboard/test/system/project_manager_test.rb index 296decab31..b4ecbd72e7 100644 --- a/apps/dashboard/test/system/project_manager_test.rb +++ b/apps/dashboard/test/system/project_manager_test.rb @@ -141,8 +141,6 @@ def add_auto_environment_variable(project_id, launcher_id, save: true) find("[href='/projects/#{project_id}']").click assert_selector 'h1', text: 'Test Project' assert_selector '.btn.btn-default', text: 'Back' - # project size is hardcoded to 2MB with stub_du - assert_selector '#new-dir-btn', text: 'Project Directory (2 MB)' end end @@ -163,6 +161,7 @@ def add_auto_environment_variable(project_id, launcher_id, save: true) end end + test 'edit a project' do Dir.mktmpdir do |dir| project_id = setup_project(dir) From b877d6338d088343ad8ffea59405f5bd5b806765 Mon Sep 17 00:00:00 2001 From: Greg Buchanan Date: Tue, 17 Dec 2024 12:34:10 -0500 Subject: [PATCH 10/13] Complete testing. --- .../app/controllers/files_controller.rb | 6 +- .../app/controllers/projects_controller.rb | 6 +- apps/dashboard/app/helpers/projects_helper.rb | 10 +- apps/dashboard/app/javascript/application.js | 4 + .../app/views/layouts/application.html.erb | 3 + .../app/views/projects/_directory.html.erb | 4 +- .../app/views/projects/_file.html.erb | 10 +- .../app/views/projects/show.html.erb | 2 +- apps/dashboard/lib/current_user.rb | 1 - apps/dashboard/test/fixtures/files/README.md | 1 + apps/dashboard/test/fixtures/files/README.txt | 1 + .../test/helpers/projects_helper_test.rb | 127 ++++++++++++++++++ 12 files changed, 157 insertions(+), 18 deletions(-) create mode 100644 apps/dashboard/test/fixtures/files/README.md create mode 100644 apps/dashboard/test/fixtures/files/README.txt create mode 100644 apps/dashboard/test/helpers/projects_helper_test.rb diff --git a/apps/dashboard/app/controllers/files_controller.rb b/apps/dashboard/app/controllers/files_controller.rb index ec2f471f8e..87d85fe0aa 100644 --- a/apps/dashboard/app/controllers/files_controller.rb +++ b/apps/dashboard/app/controllers/files_controller.rb @@ -195,12 +195,14 @@ def strip_sendfile_headers request.headers['HTTP_X_ACCEL_MAPPING'] = nil end - # Required for use with Pathable concern (app/controllers/concerns/pathable.rb) + # Required for use with directory_utils_concern (app/controllers/concerns/DirectoryUtilsConcern.rb) + # This should represent a default value. def resolved_path params[:filepath] end - # Required for use with Pathable concern (app/controllers/concerns/pathable.rb) + # Required for use with directory_utils_concern (app/controllers/concerns/DirectoryUtilsConcern.rb) + # This should represent a default value. def resolved_fs params[:fs] end diff --git a/apps/dashboard/app/controllers/projects_controller.rb b/apps/dashboard/app/controllers/projects_controller.rb index b355eef268..106fab1e4f 100644 --- a/apps/dashboard/app/controllers/projects_controller.rb +++ b/apps/dashboard/app/controllers/projects_controller.rb @@ -201,12 +201,14 @@ def stop_job private - # Required for use with Pathable concern (app/controllers/concerns/pathable.rb) + # Required for use with directory_utils_concern (app/controllers/concerns/DirectoryUtilsConcern.rb) + # This should represent a default value. def resolved_path @project&.directory.to_s end - # Required for use with Pathable concern (app/controllers/concerns/pathable.rb) + # Required for use with directory_utils_concern (app/controllers/concerns/DirectoryUtilsConcern.rb) + # This should represent a default value. def resolved_fs 'fs' end diff --git a/apps/dashboard/app/helpers/projects_helper.rb b/apps/dashboard/app/helpers/projects_helper.rb index 9a22843025..5ee59a6cfe 100644 --- a/apps/dashboard/app/helpers/projects_helper.rb +++ b/apps/dashboard/app/helpers/projects_helper.rb @@ -2,9 +2,10 @@ # Helpers for the projects page module ProjectsHelper + include ApplicationHelper + def render_readme(readme_location) file_content = File.read(readme_location) - if File.extname(readme_location) == '.md' markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML) markdown_html = markdown.render(file_content).html_safe @@ -32,10 +33,10 @@ def button_category(status) end end - def files_button + def files_button(path) link_to( - ".../projects#{@path.to_s.split('projects')[1]}", - files_path(fs: 'fs', filepath: @path), + ".../projects#{path.to_s.split('projects')[1]}", + files_path(fs: 'fs', filepath: path), target: '_top', class: 'link-light' ).html_safe @@ -65,7 +66,6 @@ def target_path(column, path, project_id) end def classes(column, sort_by) - Rails.logger.debug("column: #{column.to_s} == sort_by: #{sort_by.to_s} ? #{column.to_s == sort_by.to_s}") classes = ['btn', 'btn-xs', 'btn-hover'] classes << (column.to_s == sort_by.to_s ? ['btn-primary'] : ['btn-outline-primary']) classes.join(' ') diff --git a/apps/dashboard/app/javascript/application.js b/apps/dashboard/app/javascript/application.js index 77caf0877d..fe57a661d2 100644 --- a/apps/dashboard/app/javascript/application.js +++ b/apps/dashboard/app/javascript/application.js @@ -20,8 +20,12 @@ import 'datatables.net'; import 'datatables.net-bs4/js/dataTables.bootstrap4'; import 'datatables.net-select/js/dataTables.select'; import 'datatables.net-plugins/api/processing().mjs'; + +// Enables hotwire Turbo Streams/Frames import "@hotwired/turbo-rails" import { Turbo } from "@hotwired/turbo-rails" +// Disables Turbo Drive on an app-wide basis to prevent eager-loading links on mouse-over (which is annoying) +// Any links within a or tag will be eager-loaded as expected. Turbo.session.drive = false import Rails from '@rails/ujs'; diff --git a/apps/dashboard/app/views/layouts/application.html.erb b/apps/dashboard/app/views/layouts/application.html.erb index 613e185fb8..5f20b15c21 100644 --- a/apps/dashboard/app/views/layouts/application.html.erb +++ b/apps/dashboard/app/views/layouts/application.html.erb @@ -1,4 +1,7 @@ +<%- # Short circuits the loading of layouts, js, css, etc only when hotwire turbo-frames are requested -%> +<%- # Consider adding similar return statement for turbo-streams after looking into our needs around this -%> <%= return "turbo_rails/frame" if turbo_frame_request? %> + diff --git a/apps/dashboard/app/views/projects/_directory.html.erb b/apps/dashboard/app/views/projects/_directory.html.erb index c552bf2b85..3668dd115d 100644 --- a/apps/dashboard/app/views/projects/_directory.html.erb +++ b/apps/dashboard/app/views/projects/_directory.html.erb @@ -1,6 +1,6 @@ <%= turbo_frame_tag "project_directory" do %>
- .../projects<%= @path.to_s.split('projects')[1] %> + .../projects<%= path.to_s.split('projects')[1] %>
@@ -19,7 +19,7 @@
-  <%= files_button %> +  <%= files_button(path) %>
<% end %> \ No newline at end of file diff --git a/apps/dashboard/app/views/projects/_file.html.erb b/apps/dashboard/app/views/projects/_file.html.erb index 713f91fb1e..e71b082804 100644 --- a/apps/dashboard/app/views/projects/_file.html.erb +++ b/apps/dashboard/app/views/projects/_file.html.erb @@ -3,22 +3,22 @@
<%= link_to("", - project_directory_path(project_id: @project.id, dir_path: "#{@path.parent}", sort_by: @sort_by), + project_directory_path(project_id: project.id, dir_path: "#{path.parent}", sort_by: sort_by), class: 'fa fa-window-close align-self-start button buttom-sm text-danger', data: { turbo_frame: "project_directory" } ) %>  - .../projects<%= @path.to_s.split('projects')[1] %> + .../projects<%= path.to_s.split('projects')[1] %>
-
<%= @file %>
+
<%= file %>

-  <%= files_button %> +  <%= files_button(path) %>
-<%- end -%> \ No newline at end of file +<%- end -%> diff --git a/apps/dashboard/app/views/projects/show.html.erb b/apps/dashboard/app/views/projects/show.html.erb index 07b9b762ce..b488ed227b 100644 --- a/apps/dashboard/app/views/projects/show.html.erb +++ b/apps/dashboard/app/views/projects/show.html.erb @@ -70,7 +70,7 @@
-
+

<%= "#{t('dashboard.project')} #{t('dashboard.directory')}" %>:  <%= @project.id %>


<%= turbo_frame_tag "project_directory", diff --git a/apps/dashboard/lib/current_user.rb b/apps/dashboard/lib/current_user.rb index 47e16a4b82..f56ac43c1e 100644 --- a/apps/dashboard/lib/current_user.rb +++ b/apps/dashboard/lib/current_user.rb @@ -20,7 +20,6 @@ class << self alias_method :home, :dir end - attr_reader :pwuid delegate :name, :uid, :gid, :gecos, :dir, :shell, to: :pwuid diff --git a/apps/dashboard/test/fixtures/files/README.md b/apps/dashboard/test/fixtures/files/README.md new file mode 100644 index 0000000000..0235d4dd62 --- /dev/null +++ b/apps/dashboard/test/fixtures/files/README.md @@ -0,0 +1 @@ +# Test markdown README \ No newline at end of file diff --git a/apps/dashboard/test/fixtures/files/README.txt b/apps/dashboard/test/fixtures/files/README.txt new file mode 100644 index 0000000000..05e24765b4 --- /dev/null +++ b/apps/dashboard/test/fixtures/files/README.txt @@ -0,0 +1 @@ +Test text README \ No newline at end of file diff --git a/apps/dashboard/test/helpers/projects_helper_test.rb b/apps/dashboard/test/helpers/projects_helper_test.rb new file mode 100644 index 0000000000..065aa9dd6d --- /dev/null +++ b/apps/dashboard/test/helpers/projects_helper_test.rb @@ -0,0 +1,127 @@ +require 'test_helper' + +class ProjectsHelperTest < ActionView::TestCase + include ProjectsHelper + + # Test the render_readme method + test 'render_readme should render markdown' do + readme_location = 'test/fixtures/files/README.md' + assert_match(/

Test markdown README<\/h1>/, render_readme(readme_location)) + end + + test 'render_readme should render text' do + readme_location = 'test/fixtures/files/README.txt' + assert_match(/Test text README/, render_readme(readme_location)) + end + + # Test the job_details_buttons method + test 'job_details_buttons should render correctly when status is "queued"' do + expected_buttons = '