Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Detailed discussion and complete code for "Discover shared projects" #4153

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions apps/dashboard/app/controllers/projects_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ def new
@project = Project.new
end

# GET /projects/import
def import
@templates = []
@project = Project.new
end

# GET /projects/:id/edit
def edit
project_id = show_project_params[:id]
Expand Down Expand Up @@ -84,6 +90,16 @@ def create
end
end

# POST /projects/import
def import_save
success = Project.import_to_lookup(params[:project][:directory])
if success
redirect_to projects_path, notice: I18n.t('dashboard.jobs_project_imported')
else
redirect_to project_import_path, alert: I18n.t('dashboard.jobs_project_generic_error')
end
end

# DELETE /projects/:id
def destroy
project_id = params[:id]
Expand Down
36 changes: 35 additions & 1 deletion apps/dashboard/app/models/project.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,29 @@ def next_id
end

def all
lookup_table.map do |id, directory|
projects = lookup_table.map do |id, directory|
Project.new({ id: id, directory: directory })
end

# TODO: Move this out of here
Configuration.shared_projects_root.each do |path|
if path.exist?
CurrentUser.group_names.each do |group|
dir_path = path.join(group)
# {shared_projects_path}/<UNIX group ID>/<project>/.ondemand
if dir_path.exist? && dir_path.directory?
Dir.each_child(dir_path) do |child|
if File.directory?(File.join(dir_path, child, '.ondemand'))
projects << Project.new({ id: child, directory: File.join(dir_path, child) })
end
end
end

end
end
end

projects
end

def find(id)
Expand Down Expand Up @@ -66,6 +86,20 @@ def templates
Project.new(**opts)
end
end

def import_to_lookup(dir)
# fetch _id by opening .ondemand/manifest.yml
manifest_path = Pathname("#{dir.to_s}/.ondemand/manifest.yml")
contents = File.read(manifest_path)
raw_opts = YAML.safe_load(contents)
id = raw_opts["id"]
new_table = Project.lookup_table.merge(Hash[id, dir.to_s])
File.write(Project.lookup_file, new_table.to_yaml)
true
rescue StandardError => e
Rails.logger.warn("Cannot import project #{dir} to lookup file due to error #{e}")
false
end
end

attr_reader :id, :name, :description, :icon, :directory, :template
Expand Down
43 changes: 25 additions & 18 deletions apps/dashboard/app/views/projects/_form.html.erb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<%
edit_project_action = action_name != "new" && action_name != "create"

edit_project_action = action_name != "new" && action_name != "create" && action_name != "import"
import_project_action = action_name == "import"
path_selector_id = "project_directory_path_selector"

path_selector_locals = {
Expand All @@ -27,10 +27,13 @@
<div class='card'>
<div class='card-body'>
<div class="col">

<% if !import_project_action %>
<div class="field">
<%= form.text_field :name, placeholder: I18n.t('dashboard.jobs_project_name_placeholder'),
help: I18n.t('dashboard.jobs_project_name_validation') %>
</div>
<% end %>

<div class="field">
<%= form.text_field(:directory, placeholder: I18n.t('dashboard.jobs_project_directory_placeholder'),
Expand All @@ -46,31 +49,35 @@
<%= render(partial: 'shared/path_selector_table', locals: path_selector_locals ) %>
</div>

<% if !import_project_action %>
<div class="field">
<%= form.text_area :description, placeholder: I18n.t('dashboard.jobs_project_description_placeholder') %>
</div>
<% end %>
</div>
</div>
</div>
<div class="card">
<div class='card-body'>
<div class="col">
<div class="field">
<%= javascript_include_tag('icon_picker', nonce: true, type: 'module') %>
<%= form.text_field :icon, placeholder: "cog", id: "product_icon_select", value: @project.icon_class %>
<% if @project.icon =~ /(fa[bsrl]?):\/\/(.*)/ %>
<% icon = $2; style = $1 %>
<p class="text-center">
<%= fa_icon(icon, fa_style: style, id: "product_icon") %>
</p>
<% else %>
<p class="text-center">
<%= fa_icon("cog", fa_style: "fas", id: "product_icon") %>
</p>
<% end %>
<ul id="icon_picker_list">
</ul>
</div>
<% if !import_project_action %>
<div class="field">
<%= javascript_include_tag('icon_picker', nonce: true, type: 'module') %>
<%= form.text_field :icon, placeholder: "cog", id: "product_icon_select", value: @project.icon_class %>
<% if @project.icon =~ /(fa[bsrl]?):\/\/(.*)/ %>
<% icon = $2; style = $1 %>
<p class="text-center">
<%= fa_icon(icon, fa_style: style, id: "product_icon") %>
</p>
<% else %>
<p class="text-center">
<%= fa_icon("cog", fa_style: "fas", id: "product_icon") %>
</p>
<% end %>
<ul id="icon_picker_list">
</ul>
</div>
<% end %>
</div>
</div>
</div>
Expand Down
9 changes: 9 additions & 0 deletions apps/dashboard/app/views/projects/import.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<div class='page-header text-center pb-3'>
<h1>
Import a Shared Project
</h1>
</div>

<%= bootstrap_form_for(@project, url: project_import_save_path, method: :post) do |form| %>
<%= render partial: "form", locals: { form: form }%>
<% end %>
14 changes: 14 additions & 0 deletions apps/dashboard/app/views/projects/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,19 @@
</div>
<%- end -%>

<div class="mt-5 justify-content-center text-center project-icon">
<%= link_to(project_import_path,
title: I18n.t('dashboard.jobs_import_shared_project'),
class: 'text-dark btn btn-link') do
%>
<div class="text-center d-flex justify-content-center">
<strong>
<%= icon_tag(URI.parse("fas://file-import")) %><br>
<%= I18n.t('dashboard.jobs_import_shared_project') %>
</strong>
</div>
<% end %>
</div>

</div>
</div>
16 changes: 16 additions & 0 deletions apps/dashboard/config/configuration_singleton.rb
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,22 @@ def rails_env_production?
rails_env == 'production'
end

def shared_projects_root
# This environment varible will support ':' colon separated paths
vendor_path = ENV['VENDOR_SHARED_FILESYSTEM'] || ''
path_list = vendor_path.split(":")

paths = []
path_list.each do |path|
temp_path = Pathname.new(path)
if temp_path.exists?
paths.append(temp_path)
end
end

return paths
end

private

def can_access_core_app?(name)
Expand Down
2 changes: 2 additions & 0 deletions apps/dashboard/config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ en:
files_remote_error_listing_remotes: 'Error listing Rclone remotes: %{error}'
jobs_create_blank_project: Create a new project
jobs_create_template_project: Create a new project from a template
jobs_import_shared_project: Import a shared project
jobs_launchers: Launchers
jobs_launchers_created: Launcher successfully created!
jobs_launchers_default_created: A 'hello_world.sh' was also added to this project.
Expand All @@ -156,6 +157,7 @@ en:
jobs_launchers_updated: Launcher manifest updated!
jobs_new_launcher: New Launcher
jobs_project_created: Project successfully created!
jobs_project_imported: Project successfully imported!
jobs_project_delete_project_confirmation: Delete all contents of project directory?
jobs_project_deleted: Project successfully deleted!
jobs_project_description_placeholder: Project description
Expand Down
1 change: 1 addition & 0 deletions apps/dashboard/config/locales/ja_JP.yml
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ ja_JP:
files_remote_error_listing_remotes: 'Error listing Rclone remotes: %{error}'
jobs_create_blank_project: Create a new project
jobs_create_template_project: Create a new project from a template
jobs_import_shared_project: Import a shared project
jobs_launchers: Launchers
jobs_launchers_created: Launcher successfully created!
jobs_launchers_default_created: A 'hello_world.sh' was also added to this project.
Expand Down
1 change: 1 addition & 0 deletions apps/dashboard/config/locales/zh-CN.yml
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ zh-CN:
files_remote_error_listing_remotes: 'Error listing Rclone remotes: %{error}'
jobs_create_blank_project: Create a new project
jobs_create_template_project: Create a new project from a template
jobs_import_shared_project: Import a shared project
jobs_launchers: Launchers
jobs_launchers_created: Launcher successfully created!
jobs_launchers_default_created: A 'hello_world.sh' was also added to this project.
Expand Down
3 changes: 3 additions & 0 deletions apps/dashboard/config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

Rails.application.routes.draw do
if Configuration.can_access_projects?
get 'projects/import' => 'projects#import', :as => 'project_import'
post 'projects/import' => 'projects#import_save', :as => 'project_import_save'

resources :projects do
root 'projects#index'
get '/jobs/:cluster/:jobid' => 'projects#job_details', :defaults => { :format => 'turbo_stream' }, :as => 'job_details'
Expand Down