Skip to content

Commit e52ca16

Browse files
committed
Patched the UI with backend
Added feature to restore from backend metadata and check authenticity based upon when it was saved Added zoom to metadata, tested rigorously
1 parent 98365e1 commit e52ca16

File tree

7 files changed

+358
-103
lines changed

7 files changed

+358
-103
lines changed

apps/dashboard/app/assets/stylesheets/workflows.scss

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ html, body {
3838

3939
.toolbar {
4040
display: flex;
41+
flex-wrap: wrap;
4142
gap: .5rem;
4243
align-items: center;
4344
padding: .5rem .75rem;
@@ -48,6 +49,14 @@ html, body {
4849
z-index: 5;
4950
}
5051

52+
.toolbar .workflow-actions {
53+
display: flex;
54+
flex-basis: 100%;
55+
gap: .5rem;
56+
margin-top: .5rem;
57+
justify-content: flex-start;
58+
}
59+
5160
.toolbar button {
5261
border: 1.5px solid #d5d8e0;
5362
background: #fff;

apps/dashboard/app/controllers/workflows_controller.rb

Lines changed: 97 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22

33
# The controller for apps pages /dashboard/projects/:project_id/workflows/:workflow_id
44
class WorkflowsController < ApplicationController
5-
5+
wrap_parameters false
6+
67
# GET /projects/:id/workflows/:id
78
def show
8-
@project = Project.find(project_id)
9-
@workflow = Workflow.find(workflow_id, project_directory)
9+
return unless load_project_and_workflow_objects
1010
launcher_ids = @workflow.launcher_ids
1111

1212
@launchers = Launcher.all(project_directory).select { |l| launcher_ids.include?(l.id) }
@@ -20,33 +20,19 @@ def new
2020

2121
# GET /projects/:id/workflows/edit
2222
def edit
23-
@workflow = Workflow.find(workflow_id, project_directory)
23+
return unless load_project_and_workflow_objects
2424
@launchers = Launcher.all(project_directory)
25-
26-
return unless @workflow.nil?
27-
redirect_to project_path(project_id), notice: I18n.t('dashboard.jobs_workflow_not_found', workflow_id: workflow_id)
2825
end
2926

27+
# TODO to remove this with launcher_ids as we will need them after new UI
3028
# PATCH /projects/:id/workflows/patch
3129
def update
32-
@workflow = Workflow.find(workflow_id, project_directory)
30+
return unless load_project_and_workflow_objects
3331

34-
if @workflow.nil?
35-
redirect_to project_path(project_id), notice: I18n.t('dashboard.jobs_workflow_not_found', workflow_id: workflow_id)
36-
return
37-
end
38-
39-
if @workflow.update(update_params)
32+
if @workflow.update(update_params, true)
4033
redirect_to project_path(project_id), notice: I18n.t('dashboard.jobs_workflow_manifest_updated')
4134
else
42-
# TODO: Rename "jobs_project_*"" to "jobs_*" to generalize
43-
message = if @workflow.errors[:save].empty?
44-
I18n.t('dashboard.jobs_project_validation_error')
45-
else
46-
I18n.t('dashboard.jobs_project_generic_error', error: @workflow.collect_errors)
47-
end
48-
flash.now[:alert] = message
49-
render :edit
35+
handle_workflow_error(:update)
5036
end
5137
end
5238

@@ -57,25 +43,13 @@ def create
5743
if @workflow.save
5844
redirect_to project_path(project_id), notice: I18n.t('dashboard.jobs_workflow_created')
5945
else
60-
# TODO: Rename "jobs_project_*"" to "jobs_*" to generalize
61-
message = if @workflow.errors[:save].empty?
62-
I18n.t('dashboard.jobs_project_validation_error')
63-
else
64-
I18n.t('dashboard.jobs_project_generic_error', error: @workflow.collect_errors)
65-
end
66-
flash.now[:alert] = message
67-
render :new
46+
handle_workflow_error(:create)
6847
end
6948
end
7049

7150
# DELETE /projects/:id/workflows/:id
7251
def destroy
73-
@workflow = Workflow.find(workflow_id, project_directory)
74-
75-
if @workflow.nil?
76-
redirect_to project_path(project_id), notice: I18n.t('dashboard.jobs_workflow_not_found', workflow_id: workflow_id)
77-
return
78-
end
52+
return unless load_project_and_workflow_objects
7953

8054
if @workflow.destroy!
8155
redirect_to project_path(project_id), notice: I18n.t('dashboard.jobs_workflow_deleted')
@@ -84,22 +58,66 @@ def destroy
8458
end
8559
end
8660

61+
# POST /projects/:project_id/workflows/:id/save
62+
def save
63+
return unless load_project_and_workflow_objects(render_json: true)
64+
status = @workflow.update(metadata_params(permit_json_data))
65+
if status
66+
render json: { status: "ok", message: "Workflow saved successfully" }
67+
else
68+
render json: { status: "error", message: @workflow.collect_errors }, status: :unprocessable_entity
69+
end
70+
end
71+
72+
# GET /projects/:project_id/workflows/:id/load
73+
def load
74+
return unless load_project_and_workflow_objects(render_json: true)
75+
manifest_path = @workflow.manifest_file
76+
unless File.exist?(manifest_path)
77+
return render json: { status: 'error', message: 'No saved workflow manifest found.' }, status: :not_found
78+
end
79+
80+
data = YAML.load_file(manifest_path)
81+
metadata = data['metadata'] || {}
82+
render json: {
83+
status: 'ok',
84+
boxes: metadata['boxes'] || [],
85+
edges: metadata['edges'] || [],
86+
zoom: metadata['zoom'] || 1.0,
87+
saved_at: metadata['saved_at'] || nil
88+
}
89+
end
90+
91+
8792
# POST /projects/:project_id/workflows/:id/submit
8893
def submit
89-
@project = Project.find(project_id)
90-
@workflow = Workflow.find(workflow_id, project_directory)
91-
92-
result = @workflow.submit(submit_params)
94+
return unless load_project_and_workflow_objects(render_json: true)
95+
metadata = metadata_params(permit_json_data)
96+
@workflow.update(metadata)
97+
result = @workflow.submit(submit_params(metadata))
9398
if result
94-
redirect_to project_workflow_path(@project.id, @workflow.id), notice: I18n.t('dashboard.jobs_workflow_submitted')
99+
render json: { status: "ok", message: "Workflow submitted successfully" }
95100
else
96-
message = I18n.t('dashboard.jobs_workflow_failed', error: @workflow.collect_errors)
97-
redirect_to project_workflow_path(@project.id, @workflow.id), alert: message
101+
msg = I18n.t('dashboard.jobs_workflow_failed', error: @workflow.collect_errors)
102+
render json: { status: "ok", message: msg }, status: :unprocessable_entity
98103
end
99104
end
100105

101106
private
102107

108+
def load_project_and_workflow_objects(render_json: false)
109+
@project = Project.find(project_id)
110+
@workflow = Workflow.find(workflow_id, project_directory)
111+
return true if @workflow.present?
112+
113+
if render_json
114+
render json: { status: 'error', message: I18n.t('dashboard.jobs_workflow_not_found', workflow_id: workflow_id) }, status: :not_found
115+
else
116+
redirect_to project_path(project_id), notice: I18n.t('dashboard.jobs_workflow_not_found', workflow_id: workflow_id)
117+
end
118+
false
119+
end
120+
103121
def index_params
104122
params.permit(:project_id).to_h.symbolize_keys
105123
end
@@ -125,15 +143,46 @@ def update_params
125143
.permit(:name, :description, :id, launcher_ids: [])
126144
end
127145

128-
def submit_params
129-
params
130-
.require(:workflow)
131-
.permit(:name, :description, :id, launcher_ids: [], source_ids: [], target_ids: [])
132-
.merge(project_dir: project_directory)
146+
def submit_params(metadata)
147+
meta = metadata[:metadata] || {}
148+
{
149+
launcher_ids: meta[:boxes].map { |b| b["id"] },
150+
source_ids: meta[:edges].map { |e| e["from"] },
151+
target_ids: meta[:edges].map { |e| e["to"] },
152+
project_dir: project_directory
153+
}
133154
end
134155

135156
def project_directory
136157
Project.find(params[:project_id]).directory
137158
end
138159

160+
def permit_json_data
161+
params.permit(:project_id, :id, :zoom, :saved_at, boxes: [:id, :title, :row, :col], edges: [:from, :to]).to_h
162+
end
163+
164+
def metadata_params(json)
165+
{
166+
metadata:
167+
{
168+
boxes: json["boxes"] || [],
169+
edges: json["edges"] || [],
170+
zoom: json["zoom"] || 1.0,
171+
saved_at: json["saved_at"] || Time.now.to_i
172+
}
173+
}
174+
end
175+
176+
def handle_workflow_error(operation)
177+
# TODO: Rename "jobs_project_*"" to "jobs_*" to generalize
178+
message =
179+
if @workflow.errors[:save].empty?
180+
I18n.t('dashboard.jobs_project_validation_error')
181+
else
182+
I18n.t('dashboard.jobs_project_generic_error', error: @workflow.collect_errors)
183+
end
184+
185+
flash.now[:alert] = message
186+
render operation == :create ? :new : :edit
187+
end
139188
end

apps/dashboard/app/javascript/dag.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ export class DAG {
1414
this.#adjacency_list = {};
1515
}
1616

17+
reset() {
18+
this.#launcher_list = new Set();
19+
this.#adjacency_list = {};
20+
}
21+
1722
addEdge(fromId, toId) {
1823
if (!this.#launcher_list.has(fromId)) {
1924
this.#launcher_list.add(fromId);

0 commit comments

Comments
 (0)