diff --git a/apps/dashboard/app/controllers/projects_controller.rb b/apps/dashboard/app/controllers/projects_controller.rb
index 0e65d7446c..cb77117e73 100644
--- a/apps/dashboard/app/controllers/projects_controller.rb
+++ b/apps/dashboard/app/controllers/projects_controller.rb
@@ -110,7 +110,54 @@ def job_details
hpc_job = project.job(job_details_params[:jobid].to_s, cluster_str)
- render(partial: 'job_details', locals: { job: hpc_job })
+ @project = project
+
+ render(partial: 'job_details', locals: { job: hpc_job, project: @project })
+ end
+
+ # DELETE /projects/:project_id/jobs/:cluster/:jobid
+ def delete_job
+ @project = Project.find(job_details_params[:project_id])
+
+ cluster_str = job_details_params[:cluster].to_s
+
+ jobid = job_details_params[:jobid]
+
+ if @project.remove_logged_job(jobid.to_s, cluster_str)
+ redirect_to(
+ project_path(job_details_params[:project_id]),
+ notice: I18n.t('dashboard.jobs_project_job_deleted', job_id: jobid)
+ )
+ else
+ redirect_to(
+ project_path(job_details_params[:project_id]),
+ alert: I18n.t('dashboard.jobs_project_job_not_deleted', jobid: jobid)
+ )
+ end
+ end
+
+ # POST /projects/:project_id/jobs/:cluster/:jobid/stop
+ def stop_job
+ @project = Project.find(job_details_params[:project_id])
+ cluster_str = job_details_params[:cluster].to_s
+ cluster = OodAppkit.clusters[cluster_str.to_sym]
+
+ jobid = job_details_params[:jobid]
+
+ hpc_job = @project.job(jobid.to_s, cluster_str)
+
+ begin
+ cluster.job_adapter.delete(jobid.to_s) unless hpc_job.status.to_s == 'completed'
+ redirect_to(
+ project_path(job_details_params[:project_id]),
+ notice: I18n.t('dashboard.jobs_project_job_stopped', job_id: jobid)
+ )
+ rescue StandardError => e
+ redirect_to(
+ project_path(job_details_params[:project_id]),
+ alert: I18n.t('dashboard.jobs_project_generic_error', error: e.message.to_s)
+ )
+ end
end
private
diff --git a/apps/dashboard/app/helpers/application_helper.rb b/apps/dashboard/app/helpers/application_helper.rb
index bb169ef07c..4e99aecb10 100644
--- a/apps/dashboard/app/helpers/application_helper.rb
+++ b/apps/dashboard/app/helpers/application_helper.rb
@@ -120,7 +120,7 @@ def status_text(status)
'Running'
when 'queued'
'Queued'
- when 'qued_held'
+ when 'queued_held'
'Hold'
when 'suspended'
'Suspend'
diff --git a/apps/dashboard/app/helpers/projects_helper.rb b/apps/dashboard/app/helpers/projects_helper.rb
index c725ac7b8b..87df4858d4 100644
--- a/apps/dashboard/app/helpers/projects_helper.rb
+++ b/apps/dashboard/app/helpers/projects_helper.rb
@@ -14,4 +14,21 @@ def render_readme(readme_location)
simple_format(file_content)
end
end
-end
\ No newline at end of file
+
+ def job_details_buttons(status, job, project)
+ locals = { project_id: project.id, id: job.id, cluster: job.cluster }
+ button_partial = button_category(status)
+ render(partial: "projects/buttons/#{button_category(status)}_buttons", locals: locals) unless button_partial.nil?
+ end
+
+ def button_category(status)
+ case status
+ when 'queued_held'
+ 'held'
+ when 'suspended'
+ 'held'
+ else
+ status
+ end
+ end
+end
diff --git a/apps/dashboard/app/models/concerns/job_logger.rb b/apps/dashboard/app/models/concerns/job_logger.rb
index e62d0d0c10..ba235dfae0 100644
--- a/apps/dashboard/app/models/concerns/job_logger.rb
+++ b/apps/dashboard/app/models/concerns/job_logger.rb
@@ -16,6 +16,19 @@ def upsert_job!(directory, job)
JobLoggerHelper.write_log(directory, new_jobs)
end
+ def delete_job!(directory, job)
+ existing_jobs = jobs(directory)
+ stored_job = existing_jobs.detect { |j| j.id == job.id && j.cluster == job.cluster }
+
+ return if stored_job.nil?
+
+ new_jobs = existing_jobs.map(&:to_h)
+ idx = existing_jobs.index(stored_job)
+ new_jobs.delete_at(idx)
+
+ JobLoggerHelper.write_log(directory, new_jobs)
+ end
+
# def write_job_log!(directory, jobs)
# JobLoggerHelper.write_log!(directory, jobs)
# endd
diff --git a/apps/dashboard/app/models/project.rb b/apps/dashboard/app/models/project.rb
index e29b7303cd..be2522091b 100644
--- a/apps/dashboard/app/models/project.rb
+++ b/apps/dashboard/app/models/project.rb
@@ -219,6 +219,13 @@ def job(job_id, cluster)
job
end
+ def remove_logged_job(job_id, cluster)
+ old_job = jobs.detect { |j| j.id == job_id && j.cluster == cluster }
+ Project.delete_job!(directory, old_job)
+
+ jobs.none? { |j| j.id == job_id && j.cluster == cluster }
+ end
+
def adapter(cluster_id)
cluster = OodAppkit.clusters[cluster_id] || raise(StandardError, "Job specifies nonexistent '#{cluster_id}' cluster id.")
cluster.job_adapter
@@ -230,7 +237,7 @@ def readme_path
end
private
-
+
def update_attrs(attributes)
[:name, :description, :icon].each do |attribute|
instance_variable_set("@#{attribute}".to_sym, attributes.fetch(attribute, ''))
diff --git a/apps/dashboard/app/views/projects/_job_details.turbo_stream.erb b/apps/dashboard/app/views/projects/_job_details.turbo_stream.erb
index b85c80f7b8..838f73339e 100644
--- a/apps/dashboard/app/views/projects/_job_details.turbo_stream.erb
+++ b/apps/dashboard/app/views/projects/_job_details.turbo_stream.erb
@@ -5,6 +5,6 @@