Improve index tables

Stretch inputs to column width in place of fixed sizing.
Set minimum column widths for columns with form inputs.
Simplify table operations by removing `thead` and adding sentinel.
Manage empty table display with CSS only.
This commit is contained in:
2026-10-17 05:13:39 +02:00
parent 2c845f3528
commit 9c51887024
19 changed files with 108 additions and 106 deletions
+2 -1
View File
@@ -19,7 +19,8 @@
<details id="quantity_select" class="center hexpand" open
onkeydown="detailsProcessKey(event)">
<summary autofocus>
<!-- TODO: Set content with CSS when span empty to avoid duplication -->
<%# TODO: Set content with CSS when span empty to avoid duplication; or
change to disabled input with prompt %>
<span data-prompt="<%= t('.select_quantity') %>">
<%= t('.select_quantity') %>
</span>
+6 -9
View File
@@ -3,17 +3,14 @@
data: {link: link, form: form_tag, hidden_row: hidden_row} do %>
<td style="--depth:<%= @quantity.depth %>">
<%= form.text_field :name, required: true, autofocus: true, size: 20 %>
</td>
<td>
<%= form.text_area :description, cols: 30, rows: 1, escape: false %>
</td>
<%= form.text_field :name, autofocus: true, class: 'hstretch', required: true %>
<td><%= form.text_area :description, class: 'hstretch', escape: false, rows: 1 %>
<td class="flex">
<%= form.button %>
<%= image_link_to t(:cancel), "close-outline", quantities_path, class: 'dangerous',
name: :cancel, onclick: render_turbo_stream('form_close', {row: row}) %>
</td>
<td></td>
<%= image_link_to t(:cancel), "close-outline", quantities_path,
class: 'dangerous', name: :cancel,
onclick: render_turbo_stream('form_close', {row: row}) %>
<td>
<% end %>
<% end %>
+1 -3
View File
@@ -1,7 +1,5 @@
<%= turbo_stream.close_form dom_target(:new, @quantity.parent || :quantity) %>
<%= turbo_stream.remove :no_items %>
<% @ancestors.each do |ancestor| %>
<%= turbo_stream.replace ancestor %>
<% end %>
<%= @before ? turbo_stream.before(@before, @quantity) :
turbo_stream.append(:quantities, @quantity) %>
<%= turbo_stream.before @before || :endmark, @quantity %>
@@ -2,4 +2,3 @@
<%= turbo_stream.replace ancestor %>
<% end %>
<%= turbo_stream.remove @quantity %>
<%= turbo_stream.append(:quantities, render_no_items) if current_user.quantities.empty? %>
+1 -2
View File
@@ -3,11 +3,10 @@
link: nil,
form_tag: dom_target(:edit, @quantity, :form)} %>
<%= turbo_stream.append :quantity_form do %>
<%= turbo_stream.append_all 'body' do %>
<%- tabular_form_with model: @quantity, html: {id: ids[:form_tag]} do %>
<% end %>
<% end %>
<%= turbo_stream.hide ids[:hidden_row] %>
<%= turbo_stream.remove ids[:row] %>
<%= turbo_stream.after @quantity, partial: 'form', locals: ids -%>
+20 -22
View File
@@ -3,31 +3,29 @@
<%= image_link_to t('.new_quantity'), 'plus-outline', new_quantity_path,
id: :new_quantity_link, onclick: 'this.blur();', data: {turbo_stream: true} %>
<% end %>
<%#= image_link_to t('.import_quantities'), 'download-outline', default_quantities_path,
class: 'tools-area' %>
<%#= image_link_to t('.import_quantities'), 'download-outline',
default_quantities_path, class: 'tools-area' %>
</div>
<%# TODO: remove? form can be inserted directly, e.g. at the end of index %>
<%= tag.div class: 'main-area', id: :quantity_form %>
<table class="main-area items-table">
<thead>
<caption class="hint"><%= t '.no_items' %></caption>
<tbody>
<tr>
<th><%= Quantity.human_attribute_name(:name) %></th>
<th class="hexpand"><%= Quantity.human_attribute_name(:description) %></th>
<% if current_user.at_least(:active) %>
<th><%= t :actions %></th>
<th></th>
<% end %>
</tr>
<%= tag.tr id: "quantity_", hidden: true,
ondragover: "dragOver(event)", ondrop: "drop(event)",
ondragenter: "dragEnter(event)", ondragleave: "dragLeave(event)",
data: {drop_id: "quantity_", drop_id_param: "quantity[parent_id]"} do %>
<th colspan="4"><%= t '.top_level_drop' %></th>
<th class="hmintext"><%= Quantity.human_attribute_name(:name) %>
<th class="hexpand"><%= Quantity.human_attribute_name(:description) %>
<% if current_user.at_least(:active) %>
<th><%= t :actions %>
<th>
<tr id="quantity_" hidden
ondragover="dragOver(event)" ondrop="drop(event)"
ondragenter="dragEnter(event)" ondragleave="dragLeave(event)"
data-drop-id="quantity_"
data-drop-id-param="<%= field_name(:quantity, :parent_id) %>">
<th colspan="4"><%= t '.top_level_drop' %>
<% end %>
</thead>
<tbody id="quantities">
<%= render(@quantities) || render_no_items %>
</tbody>
<%= render @quantities %>
<tr id="endmark" hidden>
</table>
+2 -7
View File
@@ -6,15 +6,10 @@
<%= turbo_stream.disable ids[:link] -%>
<%= turbo_stream.append :quantity_form do %>
<%= turbo_stream.append_all 'body' do %>
<%- tabular_form_with model: @quantity, html: {id: ids[:form_tag]} do |form| %>
<%= form.hidden_field :parent_id if @quantity.parent_id? %>
<% end %>
<% end %>
<% if @quantity.parent_id? %>
<%= turbo_stream.remove ids[:row] %>
<%= turbo_stream.after @quantity.parent, partial: 'form', locals: ids %>
<% else %>
<%= turbo_stream.prepend :quantities, partial: 'form', locals: ids %>
<% end %>
<%= turbo_stream.after @quantity.parent || :quantity_, partial: 'form', locals: ids %>
@@ -1,9 +1,7 @@
<% @self_and_progenies.each do |q| %>
<%= turbo_stream.remove q %>
<% end %>
<% @previous_ancestors.union(@ancestors).each do |ancestor| %>
<%= turbo_stream.replace ancestor %>
<% end %>
<% @self_and_progenies.each do |q| %>
<%= @before ? turbo_stream.before(@before, q) : turbo_stream.append(:quantities, q) %>
<% @self_and_progenies.each do |quantity| %>
<%= turbo_stream.remove quantity %>
<%= turbo_stream.before @before || :endmark, quantity %>
<% end %>
+6 -9
View File
@@ -3,20 +3,17 @@
data: {link: link, form: form_tag, hidden_row: hidden_row} do %>
<td style="--depth:<%= @unit.base_id? ? 1 : 0 %>">
<%= form.text_field :symbol, required: true, autofocus: true, size: 12 %>
</td>
<%= form.text_field :symbol, autofocus: true, class: 'hstretch', required: true %>
<td>
<%= form.text_area :description, cols: 30, rows: 1, escape: false %>
</td>
<td>
<%= form.number_field :multiplier, required: true if @unit.base_id? %>
</td>
<% if @unit.base_id? %>
<%= form.number_field :multiplier, class: 'hstretch', required: true %>
<% end %>
<td><%= form.text_area :description, class: 'hstretch', escape: false, rows: 1 %>
<td class="flex">
<%= form.button %>
<%= image_link_to t(:cancel), "close-outline", units_path, class: 'dangerous',
name: :cancel, onclick: render_turbo_stream('form_close', {row: row}) %>
</td>
<td></td>
<td>
<% end %>
<% end %>
+1 -1
View File
@@ -9,9 +9,9 @@
<td style="--depth:<%= unit.base_id? ? 1 : 0 %>">
<%= link_to unit, edit_unit_path(unit), class: 'link', onclick: 'this.blur();',
data: {turbo_stream: true} %>
<td><%= unit.description %>
<%# Closing <td> tag required to avoid whitespace inclusion for testing. %>
<td class="ralign"><%= unit.multiplier.to_html if unit.base_id? %></td>
<td><%= unit.description %>
<% if current_user.at_least(:active) %>
<td class="flex">
+1 -2
View File
@@ -1,4 +1,3 @@
<%= turbo_stream.close_form dom_target(:new, @unit.base || :unit) %>
<%= turbo_stream.remove :no_items %>
<%= turbo_stream.replace @unit.base if @unit.base_id? %>
<%= @before ? turbo_stream.before(@before, @unit) : turbo_stream.append(:units, @unit) %>
<%= turbo_stream.before @before || :endmark, @unit %>
-1
View File
@@ -1,3 +1,2 @@
<%= turbo_stream.replace @unit.base if @unit.base_id? %>
<%= turbo_stream.remove @unit %>
<%= turbo_stream.append(:units, render_no_items) if current_user.units.empty? %>
+1 -2
View File
@@ -3,11 +3,10 @@
link: nil,
form_tag: dom_target(:edit, @unit, :form)} %>
<%= turbo_stream.append :unit_form do %>
<%= turbo_stream.append_all 'body' do %>
<%- tabular_form_with model: @unit, html: {id: ids[:form_tag]} do %>
<% end %>
<% end %>
<%= turbo_stream.hide ids[:hidden_row] %>
<%= turbo_stream.remove ids[:row] %>
<%= turbo_stream.after @unit, partial: 'form', locals: ids -%>
+20 -21
View File
@@ -7,28 +7,27 @@
class: 'tools-area' %>
</div>
<%# TODO: remove? form can be inserted directly, e.g. at the end of index %>
<%= tag.div id: :unit_form %>
<table class="main-area items-table">
<thead>
<caption class="hint"><%= t '.no_items' %></caption>
<tbody>
<tr>
<th><%= Unit.human_attribute_name(:symbol) %></th>
<th class="hexpand"><%= Unit.human_attribute_name(:description) %></th>
<th><%= Unit.human_attribute_name(:multiplier) %></th>
<% if current_user.at_least(:active) %>
<th><%= t :actions %></th>
<th></th>
<% end %>
</tr>
<%= tag.tr id: "unit_", hidden: true,
ondragover: "dragOver(event)", ondrop: "drop(event)",
ondragenter: "dragEnter(event)", ondragleave: "dragLeave(event)",
data: {drop_id: "unit_", drop_id_param: "unit[base_id]"} do %>
<th colspan="5"><%= t '.top_level_drop' %></th>
<th class="hmintext"><%= Unit.human_attribute_name(:symbol) %>
<th class="hminnumber"><%= Unit.human_attribute_name(:multiplier) %>
<th class="hexpand"><%= Unit.human_attribute_name(:description) %>
<% if current_user.at_least(:active) %>
<th><%= t :actions %>
<th>
<tr id="unit_" hidden
ondragover="dragOver(event)" ondrop="drop(event)"
ondragenter="dragEnter(event)" ondragleave="dragLeave(event)"
data-drop-id="unit_" data-drop-id-param="<%= field_name(:unit, :base_id) %>">
<th colspan="5"><%= t '.top_level_drop' %>
<% end %>
</thead>
<tbody id="units">
<%= render(@units) || render_no_items %>
</tbody>
<%= render @units %>
<%# Hidden rows with IDs allow simplier row insertion by using only
turbo_stream #after/#before instead of #after + #prepend/#before + #append. %>
<tr id="endmark" hidden>
</table>
+2 -7
View File
@@ -6,15 +6,10 @@
<%= turbo_stream.disable ids[:link] -%>
<%= turbo_stream.append :unit_form do %>
<%= turbo_stream.append_all 'body' do %>
<%- tabular_form_with model: @unit, html: {id: ids[:form_tag]} do |form| %>
<%= form.hidden_field :base_id if @unit.base_id? %>
<% end %>
<% end %>
<% if @unit.base_id? %>
<%= turbo_stream.remove ids[:row] %>
<%= turbo_stream.after @unit.base, partial: 'form', locals: ids %>
<% else %>
<%= turbo_stream.prepend :units, partial: 'form', locals: ids %>
<% end %>
<%= turbo_stream.after @unit.base || :unit_, partial: 'form', locals: ids %>
+4 -3
View File
@@ -1,4 +1,5 @@
<% [@previous_base, @unit.base].uniq.compact.each do |unit| %>
<%= turbo_stream.replace unit %>
<% end %>
<%= turbo_stream.remove @unit %>
<%= turbo_stream.replace @previous_base if @previous_base %>
<%= turbo_stream.replace @unit.base if @unit.base_id? && (@previous_base&.id != @unit.base_id) %>
<%= @before ? turbo_stream.before(@before, @unit) : turbo_stream.append(:units, @unit) %>
<%= turbo_stream.before @before || :endmark, @unit %>