Skip to content

Commit

Permalink
Workflow executions table enhancements (#694)
Browse files Browse the repository at this point in the history
* feat: add in WorkflowExecutions::TableComponent and updated it to use turbo morphs

* chore: fix test failures due to refactor

* chore: fix workflow executions controller tests

* chore: correct mistake of puid to id in workflow executions table component

* chore: remove unused french translations

* chore: fix tests after correcting puid to id

* chore: fix tests again

* chore: fix typo with prevented display of workflow version

* chore: fix typo correction in test files
  • Loading branch information
ericenns authored Aug 14, 2024
1 parent a3b6c3f commit 3c8b4f7
Show file tree
Hide file tree
Showing 31 changed files with 459 additions and 663 deletions.
10 changes: 10 additions & 0 deletions app/components/workflow_executions/table_component.en.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
en:
id: ID
name: Name
state: State
run_id: Run ID
workflow_name: Workflow Name
workflow_version: Workflow Version
created_at: Created
updated_at: Last Updated
actions: Actions
10 changes: 10 additions & 0 deletions app/components/workflow_executions/table_component.fr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
fr:
id: ID
name: Name
state: State
run_id: Run ID
workflow_name: Workflow Name
workflow_version: Workflow Version
created_at: Created
updated_at: Last Updated
actions: Actions
177 changes: 177 additions & 0 deletions app/components/workflow_executions/table_component.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
<%= render Viral::BaseComponent.new(**wrapper_arguments) do %>
<%= render Viral::BaseComponent.new(**system_arguments) do %>
<table
class='
w-full text-sm text-left rtl:text-right text-slate-500 dark:text-slate-400
whitespace-nowrap
'
>
<thead
class='
text-xs uppercase text-slate-700 bg-slate-50 dark:bg-slate-700
dark:text-slate-400
'
>
<tr>
<% @columns.each_with_index do |column, index| %>
<%= render_cell(
tag: 'th',
scope: 'col',
classes: class_names('px-3 py-3', 'sticky left-0 z-10 bg-slate-50 dark:bg-slate-700': index.zero?)
) do %>

<% if column == :workflow_name || column == :workflow_version %>
<%= render Ransack::SortComponent.new(
ransack_obj: @q,
label: t(".#{column}"),
url:
helpers.sorting_url(
@q,
URI.encode_www_form_component("metadata_#{column}"),
),
field: "metadata_#{column}",
data: {
turbo_action: "replace",
},
) %>
<% else %>
<%= render Ransack::SortComponent.new(
ransack_obj: @q,
label: t(".#{column}"),
url: helpers.sorting_url(@q, column),
field: column,
data: {
turbo_action: "replace",
},
) %>
<% end %>
<% end %>
<% end %>
<% if @renders_row_actions %>
<%= render_cell(
tag: 'th',
scope: 'col',
classes: class_names('px-3 py-3 bg-slate-50 dark:bg-slate-700 sticky right-0')
) do %>
<%= t(".actions") %>
<% end %>
<% end %>
</tr>
</thead>
<tbody
class='
bg-white divide-y divide-slate-200 dark:bg-slate-800 dark:divide-slate-700
'
>
<% @workflow_executions.each do |workflow_execution| %>
<%= render Viral::BaseComponent.new(**row_arguments(workflow_execution)) do %>
<% @columns.each_with_index do |column, index| %>
<%= render_cell(
tag: index.zero? ? 'th' :'td',
scope: index.zero? ? 'row' : nil,
classes: class_names('px-3 py-3', 'sticky left-0 bg-slate-50 dark:bg-slate-900': index.zero?)
) do %>
<% if column == :id %>
<%= link_to(
workflow_execution.id,
individual_path(workflow_execution),
data: {
turbo: false,
},
class: "text-slate-900 dark:text-slate-100 font-semibold hover:underline",
) %>
<% elsif column == :state %>
<%= viral_pill(
text: t(:"workflow_executions.state.#{workflow_execution[column]}"),
color: helpers.find_pill_color_for_state(workflow_execution[column]),
border: true,
) %>
<% elsif column == :workflow_name || column == :workflow_version %>
<%= workflow_execution.metadata[column.to_s] %>
<% elsif column == :created_at %>
<%= helpers.local_time(workflow_execution[column], :full_date) %>
<% elsif column == :updated_at || column == :attachments_updated_at %>
<% if workflow_execution[column].present? %>
<%= helpers.local_time_ago(workflow_execution[column]) %>
<% end %>
<% else %>
<%= workflow_execution[column.to_sym] %>
<% end %>
<% end %>
<% end %>
<% if @renders_row_actions %>
<%= render_cell(
tag: 'td',
classes: class_names('px-3 py-3 sticky right-0 bg-white dark:bg-slate-800 z-10 space-x-2')
) do %>
<% if workflow_execution.cancellable? && @row_actions.key?(:cancel) %>
<%= link_to(
t(:"workflow_executions.index.actions.cancel_button"),
cancel_path(workflow_execution),
data: {
turbo_stream: true,
turbo_method: :put,
turbo_confirm: t(:"workflow_executions.index.actions.cancel_confirm"),
},
class:
"font-medium text-blue-600 underline dark:text-blue-500 hover:no-underline cursor-pointer",
) %>
<% end %>
<% if workflow_execution.deletable? && @row_actions.key?(:destroy) %>
<%= link_to(
t(:"workflow_executions.index.actions.delete_button"),
individual_path(workflow_execution),
data: {
turbo_stream: true,
turbo_method: :delete,
turbo_confirm: t(:"workflow_executions.index.actions.delete_confirm"),
},
class:
"font-medium text-blue-600 underline dark:text-blue-500 hover:no-underline cursor-pointer",
) %>
<% end %>
<% end %>
<% end %>
<% end %>
<% end %>
</tbody>
</table>
<% end %>
<% unless @workflow_executions.empty? %>
<%= render PaginationComponent.new(
info: helpers.pagy_info(@pagy),
prev_url:
(
if @pagy.prev
helpers.pagy_url_for(@pagy, @pagy.prev).gsub(
"workflow_executions.turbo_stream",
"workflow_executions",
)
else
nil
end
),
next_url:
(
if @pagy.next
helpers.pagy_url_for(@pagy, @pagy.next).gsub(
"workflow_executions.turbo_stream",
"workflow_executions",
)
else
nil
end
),
data: {
turbo_action: "replace",
},
) %>
<% end %>
<div class="empty_state_message">
<%= viral_empty(
title: @empty[:title],
description: @empty[:description],
icon_name: :document_text,
) %>
</div>
<% end %>
86 changes: 86 additions & 0 deletions app/components/workflow_executions/table_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# frozen_string_literal: true

module WorkflowExecutions
# Component for rendering a table of Samples
class TableComponent < Component
include Ransack::Helpers::FormHelper

# rubocop:disable Naming/MethodParameterName,Metrics/ParameterLists
def initialize(
workflow_executions,
pagy,
q,
namespace: nil,
row_actions: false,
empty: {},
**system_arguments
)
@workflow_executions = workflow_executions
@pagy = pagy
@q = q
@namespace = namespace
@row_actions = row_actions
@empty = empty
@renders_row_actions = @row_actions.select { |_key, value| value }.count.positive?
@system_arguments = system_arguments

@columns = columns
end
# rubocop:enable Naming/MethodParameterName,Metrics/ParameterLists

def system_arguments
{ tag: 'div' }.deep_merge(@system_arguments).tap do |args|
args[:id] = 'workflow-executions-table'
args[:classes] = class_names(args[:classes], 'relative', 'overflow-x-auto')
end
end

def wrapper_arguments
{
tag: 'div',
classes: class_names('table-container')
}
end

def row_arguments(sample)
{ tag: 'tr' }.tap do |args|
args[:classes] = class_names('bg-white', 'border-b', 'dark:bg-slate-800', 'dark:border-slate-700')
args[:id] = sample.id
end
end

def render_cell(**arguments, &)
render(Viral::BaseComponent.new(**arguments), &)
end

def cancel_path(workflow_execution)
if @namespace
cancel_namespace_project_workflow_execution_path(
@namespace.parent,
@namespace.project,
workflow_execution
)
else
cancel_workflow_execution_path(workflow_execution)
end
end

def individual_path(workflow_execution)
if @namespace
namespace_project_workflow_execution_path(
@namespace.parent,
@namespace.project,
workflow_execution
)
else
workflow_execution_path(workflow_execution)
end
end

private

def columns
%i[id name state run_id workflow_name workflow_version created_at updated_at]
end
end
end
35 changes: 13 additions & 22 deletions app/controllers/concerns/workflow_execution_actions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,17 @@ def index

@q = load_workflows.ransack(params[:q])
set_default_sort
@pagy, @workflows = pagy_with_metadata_sort(@q.result)
@pagy, @workflow_executions = pagy_with_metadata_sort(@q.result)
end

def show
authorize! @namespace, to: :view_workflow_executions? unless @namespace.nil?

case @tab
when 'files'
@samples_worfklow_executions = @workflow_execution.samples_workflow_executions
@samples_workflow_executions = @workflow_execution.samples_workflow_executions
@attachments = Attachment.where(attachable: @workflow_execution)
.or(Attachment.where(attachable: @samples_worfklow_executions))
.or(Attachment.where(attachable: @samples_workflow_executions))
when 'params'
@workflow = Irida::Pipelines.instance.find_pipeline_by(@workflow_execution.metadata['workflow_name'],
@workflow_execution.metadata['workflow_version'])
Expand All @@ -36,26 +36,18 @@ def show
end
end

def destroy # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
def destroy
WorkflowExecutions::DestroyService.new(@workflow_execution, current_user).execute

if @workflow_execution.deleted? && params[:redirect]
flash[:success] = t('.success', workflow_name: @workflow_execution.metadata['workflow_name'])
redirect_to redirect_path
else
respond_to do |format|
format.turbo_stream do
if @workflow_execution.deleted?
render status: :ok,
locals: { type: 'success',
message: t('.success',
workflow_name: @workflow_execution.metadata['workflow_name']) }

else
render status: :unprocessable_entity, locals: {
type: 'alert', message: t('.error', workflow_name: @workflow_execution.metadata['workflow_name'])
}
end
respond_to do |format|
format.turbo_stream do
if @workflow_execution.deleted?
flash[:success] = t('.success', workflow_name: @workflow_execution.metadata['workflow_name'])
redirect_to redirect_path
else
render status: :unprocessable_entity, locals: {
type: 'alert', message: t('.error', workflow_name: @workflow_execution.metadata['workflow_name'])
}
end
end
end
Expand All @@ -70,7 +62,6 @@ def cancel
render status: :ok,
locals: { type: 'success',
message: t('.success', workflow_name: @workflow_execution.metadata['workflow_name']) }

else
render status: :unprocessable_entity, locals: {
type: 'alert', message: t('.error', workflow_name: @workflow_execution.metadata['workflow_name'])
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/projects/workflow_executions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def context_crumbs
protected

def redirect_path
namespace_project_workflow_executions_path(format: :html)
namespace_project_workflow_executions_path
end
end
end
4 changes: 2 additions & 2 deletions app/controllers/workflow_executions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def create
@workflow_execution = WorkflowExecutions::CreateService.new(current_user, workflow_execution_params).execute

if @workflow_execution.persisted?
redirect_to workflow_executions_path(format: :html)
redirect_to workflow_executions_path
else
render turbo_stream: [], status: :unprocessable_entity
end
Expand Down Expand Up @@ -76,6 +76,6 @@ def context_crumbs
end

def redirect_path
workflow_executions_path(format: :html)
workflow_executions_path
end
end
4 changes: 4 additions & 0 deletions app/models/concerns/has_user_type.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ module HasUserType
validates :user_type, presence: true
end

def human?
(USER_TYPES.keys - BOT_USER_TYPE).include?(user_type)
end

def bot?
BOT_USER_TYPES.include?(user_type)
end
Expand Down
Loading

0 comments on commit 3c8b4f7

Please sign in to comment.