diff --git a/app/components/inline_edit_component.html.erb b/app/components/inline_edit_component.html.erb new file mode 100644 index 0000000000..4c6dbff57f --- /dev/null +++ b/app/components/inline_edit_component.html.erb @@ -0,0 +1,9 @@ +<%= form_with( + url: url, + method: :get, + class: "w-full" + ) do |form| %> + + <%= form.text_field input_name.to_sym, value: value, class: "form-control" %> + <%= form.hidden_field :format, value: "turbo_stream" %> +<% end %> diff --git a/app/components/inline_edit_component.rb b/app/components/inline_edit_component.rb new file mode 100644 index 0000000000..3f387417d1 --- /dev/null +++ b/app/components/inline_edit_component.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +# Component to render activity +class InlineEditComponent < Component + attr_accessor :url, :input_name, :value + + def initialize(url:, input_name:, value:) + @url = url + @input_name = input_name + @value = value + end +end diff --git a/app/components/workflow_executions/table_component.html.erb b/app/components/workflow_executions/table_component.html.erb index c3b8de6c68..02a8d4e9f9 100644 --- a/app/components/workflow_executions/table_component.html.erb +++ b/app/components/workflow_executions/table_component.html.erb @@ -134,7 +134,7 @@ @search_params[:name_or_id_cont], highlighter: '\1', ) %> - + <% else %> <%= workflow_execution[column.to_sym] %> <% end %> diff --git a/app/controllers/concerns/workflow_execution_actions.rb b/app/controllers/concerns/workflow_execution_actions.rb index 667e061035..a610b2bc8f 100644 --- a/app/controllers/concerns/workflow_execution_actions.rb +++ b/app/controllers/concerns/workflow_execution_actions.rb @@ -23,18 +23,30 @@ def index end def edit - authorize! @namespace + authorize! @workflow_execution + + respond_to do |format| + format.turbo_stream do + render status: :ok + end + end end - def update + def update # rubocop:disable Metrics/MethodLength respond_to do |format| format.turbo_stream do @updated = WorkflowExecutions::UpdateService.new(@workflow_execution, current_user, workflow_execution_update_params).execute if @updated - render status: :ok + render status: :ok, + locals: { type: 'success', + message: t('concerns.workflow_execution_actions.update.success', + workflow_name: @workflow_execution.metadata['workflow_name']) } else - render status: :unprocessable_entity + render status: :unprocessable_entity, locals: { + type: 'alert', message: t('concerns.workflow_execution_actions.update.error', + workflow_name: @workflow_execution.metadata['workflow_name']) + } end end end diff --git a/app/policies/workflow_execution_policy.rb b/app/policies/workflow_execution_policy.rb index 3adb434c00..60914957e0 100644 --- a/app/policies/workflow_execution_policy.rb +++ b/app/policies/workflow_execution_policy.rb @@ -82,6 +82,14 @@ def cancel? # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity false end + def edit? + return true if record.submitter.id == user.id + return true if effective_access_level >= Member::AccessLevel::ANALYST + + details[:id] = record.id + false + end + def update? return true if record.submitter.id == user.id return true if effective_access_level >= Member::AccessLevel::ANALYST diff --git a/app/views/projects/workflow_executions/_edit_dialog.html.erb b/app/views/projects/workflow_executions/_edit_dialog.html.erb new file mode 100644 index 0000000000..1eb4da5a70 --- /dev/null +++ b/app/views/projects/workflow_executions/_edit_dialog.html.erb @@ -0,0 +1,54 @@ +<%= viral_dialog(open: open,classes: ["overflow-visible"]) do |dialog| %> + <%= dialog.with_header( + title: + t( + "projects.workflow_executions.edit_dialog.title", + workflow_execution_id: @workflow_execution.id, + ), + ) %> + <%= dialog.with_section do %> + +
+

+ <%= t( + "projects.workflow_executions.edit_dialog.description", + workflow_execution_id: @workflow_execution.id, + ) %> +

+
+ +
+ <%= turbo_frame_tag("edit_workflow_execution_error_alert") %> +
+ + <%= form_with(model: workflow_execution, url: namespace_project_workflow_execution_path, method: :patch, class: "grid gap-4") do |form| %> +
+ <%= form.label :name %> + <%= form.text_field :name, + autofocus: true, + value: @workflow_execution.name, + placeholder: + t("projects.workflow_executions.edit_dialog.name_placeholder") %> + +
+ +
+ <%= form.submit t("projects.workflow_executions.edit_dialog.submit_button"), + class: + "focus:outline-none text-sm text-white bg-primary-700 hover:bg-primary-800 focus:ring-0 rounded-md p-2 dark:text-white dark:bg-primary-600 dark:hover:bg-primary-700 cursor-pointer" %> + + +
+ <% end %> + <% end %> +<% end %> diff --git a/app/views/projects/workflow_executions/_summary.html.erb b/app/views/projects/workflow_executions/_summary.html.erb index fa5ab88427..d6ab900fe6 100644 --- a/app/views/projects/workflow_executions/_summary.html.erb +++ b/app/views/projects/workflow_executions/_summary.html.erb @@ -16,7 +16,10 @@ <% unless @workflow_execution.name.blank? %>
<%= t(:".name") %>
-
<%= @workflow_execution.name %>
+
+ <%= turbo_frame_tag('we_name') do %> + <%= @workflow_execution.name %>
+ <% end %>
<% end %>
diff --git a/app/views/projects/workflow_executions/_table.html.erb b/app/views/projects/workflow_executions/_table.html.erb index 862ea16023..84d50c8d98 100644 --- a/app/views/projects/workflow_executions/_table.html.erb +++ b/app/views/projects/workflow_executions/_table.html.erb @@ -6,7 +6,7 @@ namespace: namespace, search_params: @search_params, abilities: { - select_workflow_executions: allowed_to?(:export_data?, namespace) + select_workflow_executions: allowed_to?(:export_data?, namespace), }, row_actions: { cancel: allowed_to?(:update?, namespace), diff --git a/app/views/projects/workflow_executions/edit.turbo_stream.erb b/app/views/projects/workflow_executions/edit.turbo_stream.erb new file mode 100644 index 0000000000..5a82a376ba --- /dev/null +++ b/app/views/projects/workflow_executions/edit.turbo_stream.erb @@ -0,0 +1,6 @@ +<%= turbo_stream.update "edit_dialog", + partial: "edit_dialog", + locals: { + open: true, + workflow_execution: @workflow_execution, + } %> diff --git a/app/views/projects/workflow_executions/show.html.erb b/app/views/projects/workflow_executions/show.html.erb index fe72beb1ce..92799cea01 100644 --- a/app/views/projects/workflow_executions/show.html.erb +++ b/app/views/projects/workflow_executions/show.html.erb @@ -4,6 +4,8 @@ <%= turbo_frame_tag "export_dialog" %> +<%= turbo_frame_tag "edit_dialog" %> + <%= render Viral::PageHeaderComponent.new(title: @workflow_execution.id, id: t("workflow_executions.state.#{@workflow_execution.state}"), id_color: find_pill_color_for_state(@workflow_execution.state)) do |component| %> <%= component.with_icon(name: "beaker", classes: "h-14 w-14 text-primary-700") %> <%= component.with_buttons do %> @@ -16,7 +18,7 @@ analysis_type: "project", namespace_id: @namespace.id, workflow_execution_id: @workflow_execution.id, - single_workflow: true + single_workflow: true, ), data: { turbo_stream: true, @@ -29,7 +31,7 @@ analysis_type: "project", namespace_id: @namespace.id, workflow_execution_id: @workflow_execution.id, - single_workflow: true + single_workflow: true, ), data: { turbo_stream: true, @@ -38,7 +40,6 @@ "button button--size-default button--state-default pointer-events-none cursor-not-allowed bg-slate-100 text-slate-600 mr-2 dark:bg-slate-600 dark:text-slate-300" %> <% end %> <% end %> - <% if @workflow_execution.cancellable? && allowed_to?(:cancel?, @workflow_execution) %> <%= link_to( t("projects.workflow_executions.show.cancel_button"), @@ -55,6 +56,20 @@ class: "button button--state-default button--size-default mr-1", ) %> <% end %> + <% if allowed_to?(:update?, @workflow_execution) %> + <%= link_to( + t("projects.workflow_executions.show.edit_button"), + edit_namespace_project_workflow_execution_path( + @namespace.parent, + @namespace.project, + @workflow_execution, + ), + data: { + turbo_stream: true, + }, + class: "button button--state-default button--size-default mr-1", + ) %> + <% end %> <% if @workflow_execution.deletable? && allowed_to?(:destroy?, @workflow_execution) %> <%= link_to( t("projects.workflow_executions.show.remove_button"), diff --git a/app/views/projects/workflow_executions/update.turbo_stream.erb b/app/views/projects/workflow_executions/update.turbo_stream.erb index e69de29bb2..e661fbcd0c 100644 --- a/app/views/projects/workflow_executions/update.turbo_stream.erb +++ b/app/views/projects/workflow_executions/update.turbo_stream.erb @@ -0,0 +1,21 @@ +<% unless @workflow_execution.errors.any? %> + <%= turbo_stream.append "flashes" do %> + <%= viral_flash(type:, data: message) %> + <% end %> +<% end %> + +<% if @updated %> + <%= turbo_stream.update "edit_dialog", + partial: "edit_dialog", + locals: { + open: @workflow_execution.errors.any?, + workflow_execution: @workflow_execution, + } %> + + <%= turbo_stream.update "we_name" do %> + <%= @workflow_execution.name %> + <% end %> +<% else %> + <%= turbo_stream.update "edit_workflow_execution_error_alert", + viral_alert(type:, message:, classes: "mb-4") %> +<% end %> diff --git a/app/views/workflow_executions/_edit_dialog.html.erb b/app/views/workflow_executions/_edit_dialog.html.erb new file mode 100644 index 0000000000..9bc21269a4 --- /dev/null +++ b/app/views/workflow_executions/_edit_dialog.html.erb @@ -0,0 +1,48 @@ +<%= viral_dialog(open: open,classes: ["overflow-visible"]) do |dialog| %> + <%= dialog.with_header(title: t("workflow_executions.edit_dialog.title")) %> + <%= dialog.with_section do %> + +
+

+ <%= t( + "workflow_executions.edit_dialog.description", + workflow_execution_id: @workflow_execution.id, + ) %> +

+
+ +
+ <%= turbo_frame_tag("edit_workflow_execution_error_alert") %> +
+ + <%= form_with(model: workflow_execution, url: workflow_execution_path, method: :patch, class: "grid gap-4") do |form| %> +
+ <%= form.label :name %> + <%= form.text_field :name, + autofocus: true, + value: @workflow_execution.name, + placeholder: + t("workflow_executions.edit_dialog.name_placeholder") %> + +
+ +
+ <%= form.submit t("workflow_executions.edit_dialog.submit_button"), + class: + "focus:outline-none text-sm text-white bg-primary-700 hover:bg-primary-800 focus:ring-0 rounded-md p-2 dark:text-white dark:bg-primary-600 dark:hover:bg-primary-700 cursor-pointer" %> + + +
+ <% end %> + <% end %> +<% end %> diff --git a/app/views/workflow_executions/_summary.html.erb b/app/views/workflow_executions/_summary.html.erb index cc3093d91e..ead8b6de3e 100644 --- a/app/views/workflow_executions/_summary.html.erb +++ b/app/views/workflow_executions/_summary.html.erb @@ -19,7 +19,11 @@ <% unless @workflow_execution.name.blank? %>
<%= t(:".name") %>
-
<%= @workflow_execution.name %>
+
+ <%= turbo_frame_tag('we_name') do %> + <%= @workflow_execution.name %> + <% end %> +
<% end %>
diff --git a/app/views/workflow_executions/_table.html.erb b/app/views/workflow_executions/_table.html.erb index 61f4e5f778..e5fe278196 100644 --- a/app/views/workflow_executions/_table.html.erb +++ b/app/views/workflow_executions/_table.html.erb @@ -5,7 +5,7 @@ q, search_params: @search_params, abilities: { - select_workflow_executions: true + select_workflow_executions: true, }, row_actions: { cancel: true, diff --git a/app/views/workflow_executions/edit.turbo_stream.erb b/app/views/workflow_executions/edit.turbo_stream.erb new file mode 100644 index 0000000000..5a82a376ba --- /dev/null +++ b/app/views/workflow_executions/edit.turbo_stream.erb @@ -0,0 +1,6 @@ +<%= turbo_stream.update "edit_dialog", + partial: "edit_dialog", + locals: { + open: true, + workflow_execution: @workflow_execution, + } %> diff --git a/app/views/workflow_executions/show.html.erb b/app/views/workflow_executions/show.html.erb index 4566753a7d..d76a19168a 100644 --- a/app/views/workflow_executions/show.html.erb +++ b/app/views/workflow_executions/show.html.erb @@ -4,7 +4,10 @@ <%= turbo_frame_tag "export_dialog" %> -<%= render Viral::PageHeaderComponent.new(title: @workflow_execution.name.blank? ? @workflow_execution.metadata["workflow_name"] : @workflow_execution.name, id: @workflow_execution.id, id_color: find_pill_color_for_state(@workflow_execution.state)) do |component| %> +<%= turbo_frame_tag "edit_dialog" %> + +<%= render Viral::PageHeaderComponent.new(title: @workflow_execution.name.blank? ? @workflow_execution.metadata["workflow_name"] : + turbo_frame_tag('we_name_header') do @workflow_execution.name end, id: @workflow_execution.id, id_color: find_pill_color_for_state(@workflow_execution.state)) do |component| %> <%= component.with_icon(name: "beaker", classes: "h-14 w-14 text-primary-700") %> <%= component.with_buttons do %>
@@ -45,6 +48,16 @@ class: "button button--state-default button--size-default mr-1" ) %> <% end %> + <% if allowed_to?(:update?, @workflow_execution) %> + <%= link_to( + t("workflow_executions.show.edit_button"), + edit_workflow_execution_path(id: @workflow_execution.id), + data: { + turbo_stream: true + }, + class: "button button--state-default button--size-default mr-1" + ) %> + <% end %> <% if @workflow_execution.deletable? %> <%= link_to( t("workflow_executions.show.remove_button"), diff --git a/app/views/workflow_executions/update.turbo_stream.erb b/app/views/workflow_executions/update.turbo_stream.erb index e69de29bb2..345d9a71c6 100644 --- a/app/views/workflow_executions/update.turbo_stream.erb +++ b/app/views/workflow_executions/update.turbo_stream.erb @@ -0,0 +1,25 @@ +<% unless @workflow_execution.errors.any? %> + <%= turbo_stream.append "flashes" do %> + <%= viral_flash(type:, data: message) %> + <% end %> +<% end %> + +<% if @updated %> + <%= turbo_stream.update "edit_dialog", + partial: "edit_dialog", + locals: { + open: @workflow_execution.errors.any?, + workflow_execution: @workflow_execution, + } %> + + <%= turbo_stream.update "we_name" do %> + <%= @workflow_execution.name %> + <% end %> + + <%= turbo_stream.update "we_name_header" do %> + <%= @workflow_execution.name %> + <% end %> +<% else %> + <%= turbo_stream.update "edit_workflow_execution_error_alert", + viral_alert(type:, message:, classes: "mb-4") %> +<% end %> diff --git a/config/locales/en.yml b/config/locales/en.yml index 26af7d1fd7..70f8d65fc2 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -95,6 +95,7 @@ en: cancel?: You are not authorized to cancel workflow executions for %{namespace_type} %{name} create?: You are not authorized to submit workflow executions for %{namespace_type} %{name} destroy?: You are not authorized to destroy workflow executions for %{namespace_type} %{name} + edit?: You are not authorized to edit workflow execution %{id} index?: You are not authorized to view workflow executions for %{namespace_type} %{name} read?: You are not authorized to view workflow execution %{id} update?: You are not authorized to update workflow execution %{id} @@ -451,6 +452,9 @@ en: destroy: error: Could not delete workflow %{workflow_name} success: Workflow %{workflow_name} was successfully deleted + update: + error: Could not update workflow %{workflow_name} + success: Workflow %{workflow_name} was successfully updated dashboard: groups: index: @@ -1492,6 +1496,12 @@ en: update: success: Project %{project_name} was successfully updated workflow_executions: + edit_dialog: + cancel_button: Cancel + description: You are editing automated workflow execution '%{workflow_execution_id}' + name_placeholder: Enter workflow execution name (optional) + submit_button: Submit + title: Edit automated workflow execution files: table_header: created_at: Created At @@ -1512,6 +1522,7 @@ en: cancel_button: Cancel cancel_button_confirmation: Are you sure that you want to cancel this workflow execution? create_export_button: Create Export + edit_button: Edit remove_button: Remove remove_button_confirmation: Are you sure that you want to remove this workflow execution? summary: @@ -1698,6 +1709,12 @@ en: add_all: Add all remove_all: Remove all workflow_executions: + edit_dialog: + cancel_button: Cancel + description: You are editing workflow execution '%{workflow_execution_id}' + name_placeholder: Enter workflow execution name (optional) + submit_button: Submit + title: Edit workflow execution files: table_header: created_at: Created At @@ -1724,6 +1741,7 @@ en: cancel_button: Cancel cancel_button_confirmation: Are you sure that you want to cancel this workflow execution? create_export_button: Create Export + edit_button: Edit remove_button: Remove remove_button_confirmation: Are you sure that you want to remove this workflow execution? tabs: diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 3df04efbb1..684f89c780 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -95,6 +95,7 @@ fr: cancel?: You are not authorized to cancel workflow executions for %{namespace_type} %{name} create?: You are not authorized to submit workflow executions for %{namespace_type} %{name} destroy?: You are not authorized to destroy workflow executions for %{namespace_type} %{name} + edit?: You are not authorized to edit workflow execution %{id} index?: You are not authorized to view workflow executions for %{namespace_type} %{name} read?: You are not authorized to view workflow execution %{id} update?: You are not authorized to update workflow execution %{id} @@ -451,6 +452,9 @@ fr: destroy: error: Could not delete workflow %{workflow_name} success: Workflow %{workflow_name} was successfully deleted + update: + error: Could not update workflow %{workflow_name} + success: Workflow %{workflow_name} was successfully updated dashboard: groups: index: @@ -1492,6 +1496,12 @@ fr: update: success: Project %{project_name} was successfully updated workflow_executions: + edit_dialog: + cancel_button: Cancel + description: You are editing automated workflow execution '%{workflow_execution_id}' + name_placeholder: Enter workflow execution name (optional) + submit_button: Submit + title: Edit automated workflow execution files: table_header: created_at: Created At @@ -1512,6 +1522,7 @@ fr: cancel_button: Cancel cancel_button_confirmation: Are you sure that you want to cancel this workflow execution? create_export_button: Create Export + edit_button: Edit remove_button: Remove remove_button_confirmation: Are you sure that you want to remove this workflow execution? summary: @@ -1698,6 +1709,12 @@ fr: add_all: Add all remove_all: Remove all workflow_executions: + edit_dialog: + cancel_button: Cancel + description: You are editing workflow execution '%{workflow_execution_id}' + name_placeholder: Enter workflow execution name (optional) + submit_button: Submit + title: Edit workflow execution files: table_header: created_at: Created At @@ -1724,6 +1741,7 @@ fr: cancel_button: Cancel cancel_button_confirmation: Are you sure that you want to cancel this workflow execution? create_export_button: Create Export + edit_button: Edit remove_button: Remove remove_button_confirmation: Are you sure that you want to remove this workflow execution? tabs: