Skip to content

Commit

Permalink
Fix: Action links incorrectly enabled on empty table (DFCT0010080) (#635
Browse files Browse the repository at this point in the history
)

* chore: update action links to disable themselves on controller connection

* chore: installed dependencies using pnpm version specified in tool versions file and update Dockerfile

* chore: update samples tables to use partials and no longer use delayed loading

* chore: add in magic comment to samples partial to verify existence of locals

* chore: fix border issue on samples table footer

* chore: add in empty state message to project samples table

* chore: add in empty state message to group samples table

* chore: fix samples table display to not show empty message when filtering results in no matching samples

* chore: fix scrollbar positioning on samples tables

* chore: increase test timeout to 15 minutes from 10

* chore: add in tests to verify that action links are disabled when a project/group does not have any samples

* chore: fix permission checking for samples table selections

* chore: fix rubocop violations

* feat: replace group and project samples table with new Samples::TableComponent

* chore: fix project samples test

* chore: move capybara lockstep to try and alleviate test flakes

* chore: include capybara lockstep middleware to alleviate test flakes

* chore: remove loading: lazy as that only makes sense if the content is off screen

* chore: update github actions to use newer version of node and pnpm

* chore: add in retry to assert accessible

* chore: add in french translation file with english placeholders

* chore: fix dark mode styling for ID column in samples table

* chore: don't render import metadata button when no samples present in the Project

* chore: render sample count via Samples::TableComponent and rename some functions in selection controller

* chore: fix select all checkbox

* chore: fix Samples::TableComponent french translations

* chore: fix samples test after removing selection controller total target

* chorre: fix flaky transfer test
  • Loading branch information
ericenns authored Jun 13, 2024
1 parent de3320f commit 35b11ee
Show file tree
Hide file tree
Showing 50 changed files with 1,085 additions and 1,267 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/docs-site.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ jobs:
- name: Set up PNPM
uses: pnpm/action-setup@v2
with:
version: 7
- name: Use Node.js 19
version: 9
- name: Use Node.js 20
uses: actions/setup-node@v3
with:
node-version: 19
node-version: 20
cache: "pnpm"
- name: Install dependencies
run: pnpm install
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/ruby.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ on:

jobs:
test:
timeout-minutes: 10
timeout-minutes: 15
runs-on: ubuntu-latest

services:
Expand Down Expand Up @@ -38,11 +38,11 @@ jobs:
- name: Set up PNPM
uses: pnpm/action-setup@v2
with:
version: 7
- name: Use Node.js 19
version: 9
- name: Use Node.js 20
uses: actions/setup-node@v3
with:
node-version: 19
node-version: 20
cache: "pnpm"
- name: Install dependencies
run: pnpm install
Expand Down
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ RUN apt-get update -qq && \
python-is-python3

# Install JavaScript dependencies
ARG NODE_VERSION=19.7.0
ARG PNPM_VERSION=7.29.1
ARG NODE_VERSION=20.14.0
ARG PNPM_VERSION=9.2.0
ENV PATH=/usr/local/node/bin:$PATH
RUN curl -sL https://github.com/nodenv/node-build/archive/master.tar.gz | tar xz -C /tmp/ && \
/tmp/node-build-master/bin/node-build "${NODE_VERSION}" /usr/local/node && \
Expand Down
5 changes: 5 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,8 @@ GEM
net-smtp (0.5.0)
net-protocol
nio4r (2.7.3)
nokogiri (1.16.5-aarch64-linux)
racc (~> 1.4)
nokogiri (1.16.5-arm64-darwin)
racc (~> 1.4)
nokogiri (1.16.5-x86_64-darwin)
Expand Down Expand Up @@ -545,6 +547,8 @@ GEM
strscan (3.1.0)
syntax_tree (6.2.0)
prettier_print (>= 1.2.0)
tailwindcss-rails (2.6.0-aarch64-linux)
railties (>= 7.0.0)
tailwindcss-rails (2.6.0-arm64-darwin)
railties (>= 7.0.0)
tailwindcss-rails (2.6.0-x86_64-darwin)
Expand Down Expand Up @@ -593,6 +597,7 @@ GEM
zip_kit (6.3.0)

PLATFORMS
aarch64-linux
arm64-darwin-22
arm64-darwin-23
x86_64-darwin-21
Expand Down
12 changes: 12 additions & 0 deletions app/components/samples/table_component.en.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
en:
puid: ID
name: Sample
project: Project
created_at: Created
updated_at: Last Updated
attachments_updated_at: Files Last Updated
action: Action
counts:
samples: Samples
selected: Selected
select_all: Select All
12 changes: 12 additions & 0 deletions app/components/samples/table_component.fr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
fr:
puid: ID
name: Sample
project: Project
created_at: Created
updated_at: Last Updated
attachments_updated_at: Files Last Updated
action: Action
counts:
samples: Samples
selected: Selected
select_all: Select All
260 changes: 260 additions & 0 deletions app/components/samples/table_component.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,260 @@
<%= 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 text-slate-700 uppercase 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-6 py-3', 'sticky left-0 z-10 flex': index.zero?)
) do %>
<% if index.zero? and @abilities[:select_samples] %>
<%= search_form_for(
@q,
url: select_samples_url(**request.query_parameters),
html: { "data-controller": "filters", id: "select-all-form" },
class: "filters align-middle"
) do |f| %>
<input type="hidden" name="format" value="turbo_stream"/>

<% @search_params.each do |key, value| %>
<% if value.is_a?(Array) %>
<% value.each do |val| %>
<input type="hidden" name="q[<%= key %>][]" value="<%= val %>">
<% end %>
<% else %>
<input type="hidden" name="q[<%= key %>]" value="<%= value %>">
<% end %>
<% end %>

<label for="select-all" class="sr-only"><%= t(:".select_all") %></label>
<input
type="checkbox"
id="select-all"
name="select"
class="
w-4 h-4 mr-2.5 text-primary-600 bg-slate-100 border-slate-300 rounded
focus:ring-primary-500 dark:focus:ring-primary-600 dark:ring-offset-slate-800
focus:ring-2 dark:bg-slate-700 dark:border-slate-600
"
data-selection-target="selectAll"
onchange="Turbo.navigator.submitForm(this.form)"
/>
<% end %>
<% end %>

<% if column == :attachments_updated_at %>
<%= render Ransack::SortComponent.new(
ransack_obj: @q,
label: t(".#{column}"),
url: helpers.sorting_url(@q, :attachments_updated_at_nulls_last),
field: :attachments_updated_at_nulls_last,
) %>
<% else %>
<%= render Ransack::SortComponent.new(
ransack_obj: @q,
label: t(".#{column}"),
url: helpers.sorting_url(@q, column),
field: column,
) %>
<% end %>
<% end %>
<% end %>
<% @metadata_fields.each do |field| %>
<%= render_cell(
tag: 'th',
scope: 'col',
class: class_names('px-6 py-3')
) do %>
<%= render Ransack::SortComponent.new(
ransack_obj: @q,
label: field,
url:
helpers.sorting_url(@q, URI.encode_www_form_component("metadata_#{field}")),
field: "metadata_#{field}",
) %>
<% end %>
<% end %>
<% if @renders_row_actions %>
<%= render_cell(
tag: 'th',
scope: 'col',
classes: class_names('px-6 py-3 bg-slate-50 dark:bg-slate-700 sticky right-0')
) do %>
<%= t(".action") %>
<% end %>
<% end %>
</tr>
</thead>
<tbody
class='
bg-white divide-y divide-slate-200 dark:bg-slate-800 dark:divide-slate-700
'
>
<% @samples.each do |sample| %>
<%= render Viral::BaseComponent.new(**row_arguments(sample)) do %>
<% @columns.each_with_index do |column, index| %>
<%= render_cell(
tag: index.zero? ? 'th' :'td',
scope: index.zero? ? 'row' : nil,
classes: class_names('px-6 py-3', 'sticky left-0 bg-slate-50 dark:bg-slate-900': index.zero?)
) do %>
<% if index.zero? && @abilities[:select_samples] %>
<%= check_box_tag "sample_ids[]",
sample.id,
nil,
id: dom_id(sample),
"aria-label": sample.name,
data: {
action: "input->selection#toggle",
selection_target: "rowSelection",
},
class:
"w-4 h-4 mr-2.5 text-primary-600 bg-slate-100 border-slate-300 rounded focus:ring-primary-500 dark:focus:ring-primary-600 dark:ring-offset-slate-800 focus:ring-2 dark:bg-slate-700 dark:border-slate-600" %>
<% end %>
<% if column == :puid || column == :name %>
<%= link_to(
project_sample_path(sample.project, sample),
data: { turbo: false },
class: "text-slate-900 dark:text-slate-100 font-semibold hover:underline"
) do %>
<span class="font-semibold">
<%= highlight(
sample[column],
defined?(params[:q][:name_or_puid_cont]) && params[:q][:name_or_puid_cont],
highlighter: '<mark class="bg-primary-300 dark:bg-primary-600">\1</mark>',
) %>
</span>
<% end %>
<% elsif column == :project %>
<%= viral_tooltip(title: project_path(sample.project)) do %>
<%= link_to sample.project.abbreviated_path,
project_path(sample.project),
data: {
turbo: false,
},
class: "text-slate-900 dark:text-slate-100 font-semibold hover:underline" %>
<% end %>
<% elsif column == :created_at %>
<%= l(sample[column].localtime, format: :full_date) %>
<% elsif column == :updated_at || column == :attachments_updated_at %>
<% if sample[column].present? %>
<%= viral_time_ago(original_time: sample[column]) %>
<% end %>
<% else %>
<%= sample[column.to_sym] %>
<% end %>
<% end %>
<% end %>
<% @metadata_fields.each do |field| %>
<%= render_cell(
tag: 'td',
scope: 'col',
class: class_names('px-6 py-3')
) do %>
<%= sample.metadata[field] %>
<% end %>
<% end %>
<% if @renders_row_actions %>
<%= render_cell(
tag: 'td',
classes: class_names('px-6 py-3 sticky right-0 bg-white dark:bg-slate-800 z-10 space-x-2')
) do %>
<% if @row_actions[:edit] %>
<%= link_to(
t(:"projects.samples.index.edit_button"),
edit_project_sample_path(sample.project, sample),
data: {
turbo: false,
},
class:
"font-medium text-blue-600 underline dark:text-blue-500 hover:no-underline cursor-pointer",
) %>
<% end %>
<% if @row_actions[:destroy] %>
<%= link_to(
t(:"projects.samples.index.remove_button"),
project_sample_path(sample.project, sample),
data: {
turbo_method: :delete,
turbo_confirm: t(:"projects.samples.index.remove_button_confirmation"),
},
class:
"font-medium text-blue-600 underline dark:text-blue-500 hover:no-underline cursor-pointer",
) %>
<% end %>
<% end %>
<% end %>
<% end %>
<% end %>
</tbody>
<% if @abilities[:select_samples] && @has_samples %>
<tfoot>
<tr class="border-t dark:border-slate-700 border-slate-200">
<td
class="
px-6 py-3 sticky left-0 bg-slate-50 dark:bg-slate-900 z-10
"
colspan="3"
>
<span>
<%= t(".counts.samples") %>:
<strong><%= @pagy.count %></strong>
</span>
<span>
<%= t(".counts.selected") %>:
<strong data-selection-target="selected">0</strong>
</span>
</td>
<td colspan="100%" class="px-6 py-3 bg-slate-50 dark:bg-slate-900"></td>
</tr>
</tfoot>
<% end %>
</table>
<% end %>
<% if @has_samples %>
<%= render PaginationComponent.new(
info: helpers.pagy_info(@pagy),
prev_url:
(
if @pagy.prev
helpers.pagy_url_for(@pagy, @pagy.prev).gsub(
"samples.turbo_stream",
"samples",
)
else
nil
end
),
next_url:
(
if @pagy.next
helpers.pagy_url_for(@pagy, @pagy.next).gsub(
"samples.turbo_stream",
"samples",
)
else
nil
end
),
) %>
<% end %>
<div class="empty_state_message">
<%= viral_empty(
title: @empty[:title],
description: @empty[:description],
icon_name: :beaker,
) %>
</div>
<% end %>
Loading

0 comments on commit 35b11ee

Please sign in to comment.