From 46dd480b4ea46df3df0b44151b34964ea4c96979 Mon Sep 17 00:00:00 2001 From: cryptogopher Date: Fri, 15 Aug 2025 23:26:57 +0200 Subject: [PATCH 1/3] Alternative new Measurement form, WIP --- app/assets/stylesheets/application.css | 5 +- app/controllers/measurements_controller.rb | 40 +------------- app/controllers/readouts_controller.rb | 43 +++++++++++++++ app/helpers/quantities_helper.rb | 5 ++ app/models/measurement.rb | 3 ++ app/views/measurements/_form.html.erb | 52 ++++++++++--------- app/views/measurements/_form_close.html.erb | 2 +- app/views/measurements/_form_frame.html.erb | 16 ------ app/views/measurements/index.html.erb | 24 +++------ app/views/measurements/new.turbo_stream.erb | 9 +--- app/views/quantities/index.html.erb | 3 +- app/views/readouts/_form.html.erb | 30 +++++++++++ .../_form_discard.html.erb} | 0 .../_form_repath.html.erb | 2 +- app/views/readouts/new.turbo_stream.erb | 8 +++ config/initializers/core_ext.rb | 1 + config/locales/en.yml | 6 ++- config/routes.rb | 8 +-- lib/core_ext/array_delete_bang.rb | 10 ++++ 19 files changed, 155 insertions(+), 112 deletions(-) create mode 100644 app/controllers/readouts_controller.rb create mode 100644 app/models/measurement.rb delete mode 100644 app/views/measurements/_form_frame.html.erb create mode 100644 app/views/readouts/_form.html.erb rename app/views/{measurements/discard.turbo_stream.erb => readouts/_form_discard.html.erb} (100%) rename app/views/{measurements => readouts}/_form_repath.html.erb (66%) create mode 100644 app/views/readouts/new.turbo_stream.erb create mode 100644 lib/core_ext/array_delete_bang.rb diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 6fe64c8..7220e07 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -86,9 +86,10 @@ input[type=submit] { text-decoration: none; white-space: nowrap; } +/* [hidden] submit controls cannot have `display` set as it makes them visible */ .button, -button, -input[type=submit], +button:not([hidden]), +input[type=submit]:not([hidden]), .tab { align-items: center; color: var(--color-gray); diff --git a/app/controllers/measurements_controller.rb b/app/controllers/measurements_controller.rb index 307aac8..6d6dbf5 100644 --- a/app/controllers/measurements_controller.rb +++ b/app/controllers/measurements_controller.rb @@ -1,36 +1,9 @@ class MeasurementsController < ApplicationController - before_action :find_quantity, only: [:new, :discard] - before_action :find_prev_quantities, only: [:new, :discard] - def index - @quantities = current_user.quantities.ordered end def new - quantities = - case params[:scope] - when 'children' - @quantity.subquantities - when 'subtree' - @quantity.progenies - else - [@quantity] - end - quantities -= @prev_quantities - @readouts = current_user.readouts.build(quantities.map { |q| {quantity: q} }) - - @units = current_user.units.ordered - - all_quantities = @prev_quantities + quantities - @common_ancestor = current_user.quantities - .common_ancestors(all_quantities.map(&:parent_id)).first - end - - def discard - @prev_quantities -= [@quantity] - - @common_ancestor = current_user.quantities - .common_ancestors(@prev_quantities.map(&:parent_id)).first + @quantities = current_user.quantities.ordered end def create @@ -38,15 +11,4 @@ class MeasurementsController < ApplicationController def destroy end - - private - - def find_quantity - @quantity = current_user.quantities.find_by!(id: params[:id]) - end - - def find_prev_quantities - prev_quantity_ids = params[:readouts]&.map { |r| r[:quantity_id] } || [] - @prev_quantities = current_user.quantities.find(prev_quantity_ids) - end end diff --git a/app/controllers/readouts_controller.rb b/app/controllers/readouts_controller.rb new file mode 100644 index 0000000..a009260 --- /dev/null +++ b/app/controllers/readouts_controller.rb @@ -0,0 +1,43 @@ +class ReadoutsController < ApplicationController + before_action :find_quantity, only: [:new, :discard] + before_action :find_prev_quantities, only: [:new, :discard] + + def new + new_quantities = + case params[:scope] + when 'children' + @quantity.subquantities + when 'subtree' + @quantity.progenies + else + [@quantity] + end + new_quantities -= @prev_quantities + @readouts = current_user.readouts.build(new_quantities.map { |q| {quantity: q} }) + + @user_quantities = current_user.quantities.ordered + @user_units = current_user.units.ordered + + @quantities = @prev_quantities + new_quantities +# @common_ancestor = current_user.quantities +# .common_ancestors(all_quantities.map(&:parent_id)).first + end + + def discard + @prev_quantities -= [@quantity] + + @common_ancestor = current_user.quantities + .common_ancestors(@prev_quantities.map(&:parent_id)).first + end + + private + + def find_quantity + @quantity = current_user.quantities.find_by!(id: params[:id]) + end + + def find_prev_quantities + prev_quantity_ids = params[:readouts]&.map { |r| r[:quantity_id] } || [] + @prev_quantities = current_user.quantities.find(prev_quantity_ids) + end +end diff --git a/app/helpers/quantities_helper.rb b/app/helpers/quantities_helper.rb index 9e6aa8b..e6e42cf 100644 --- a/app/helpers/quantities_helper.rb +++ b/app/helpers/quantities_helper.rb @@ -1,2 +1,7 @@ module QuantitiesHelper + def quantity_options(quantities, selected: nil) + values = quantities.map { |q| [sanitize(' ' * q.depth + q.name), q.id] } + values.unshift([t('.select_quantity'), nil, {hidden: true}]) + options_for_select(values, selected: selected) + end end diff --git a/app/models/measurement.rb b/app/models/measurement.rb new file mode 100644 index 0000000..7d19965 --- /dev/null +++ b/app/models/measurement.rb @@ -0,0 +1,3 @@ +class Measurement + include ActiveModel::Model +end diff --git a/app/views/measurements/_form.html.erb b/app/views/measurements/_form.html.erb index f07159a..10ff507 100644 --- a/app/views/measurements/_form.html.erb +++ b/app/views/measurements/_form.html.erb @@ -1,25 +1,29 @@ -<% @readouts.each do |readout| %> - <%= tabular_fields_for 'readouts[]', readout do |form| %> - <%- tag.tr id: dom_id(readout.quantity, :new, :readout), - onkeydown: 'processKey(event)' do %> - <%= tag.td id: dom_id(readout.quantity, nil, :pathname) do %> - <%= readout.quantity.relative_pathname(@common_ancestor) %> - <%end%> - - <%= form.number_field :value, required: true, autofocus: true, size: 10 %> - - - <%= form.select :unit_id, options_from_collection_for_select( - @units, :id, ->(u){ sanitize(' '*(u.base_id ? 1 : 0) + u.symbol) } - ) %> - - - - <%= image_button_tag '', 'delete-outline', class: 'dangerous', - formaction: discard_new_measurement_path(readout.quantity), - formmethod: :get, formnovalidate: true, data: {turbo_stream: true} %> - <%= form.hidden_field :quantity_id %> - - <% end %> - <% end %> +<%= tabular_form_with model: Measurement.new do |form| %> +
+ + <%= tag.span id: :measurement_form_legend %> + <%= image_link_to '', "close-outline", measurements_path, name: :cancel, + class: 'dangerous', onclick: render_turbo_stream('form_close') %> + + + + + + + + + + + + + +
+ <%= select_tag :id, quantity_options(@quantities), onchange: + "this.form.requestSubmit(document.getElementById('readout_submit'));", + class: 'quantity' %> + <%= form.submit id: :readout_submit, name: nil, value: nil, + formaction: new_readout_path, formmethod: :get, formnovalidate: true, + hidden: true, data: {turbo_stream: true} %> +
<%= form.button %>
+
<% end %> diff --git a/app/views/measurements/_form_close.html.erb b/app/views/measurements/_form_close.html.erb index a171e26..6975cb5 100644 --- a/app/views/measurements/_form_close.html.erb +++ b/app/views/measurements/_form_close.html.erb @@ -1,2 +1,2 @@ -<%= turbo_stream.update :new_readouts_form %> +<%= turbo_stream.update :measurement_form %> <%= turbo_stream.update :flashes %> diff --git a/app/views/measurements/_form_frame.html.erb b/app/views/measurements/_form_frame.html.erb deleted file mode 100644 index fa7e7de..0000000 --- a/app/views/measurements/_form_frame.html.erb +++ /dev/null @@ -1,16 +0,0 @@ -<%= tabular_fields_for Readout.new do |form| %> -
- - <%= tag.span id: :new_readouts_form_legend %> - <%= image_link_to '', "close-outline", measurements_path, name: :cancel, - class: 'dangerous', onclick: render_turbo_stream('form_close') %> - - - - - - - -
<%= form.button %>
-
-<% end %> diff --git a/app/views/measurements/index.html.erb b/app/views/measurements/index.html.erb index 2bc361d..ad0c275 100644 --- a/app/views/measurements/index.html.erb +++ b/app/views/measurements/index.html.erb @@ -1,20 +1,10 @@ -
+<%# TODO: show hint when no quantities/units defined %> +
<% if current_user.at_least(:active) %> - <%# TODO: show hint when no quantities/units defined %> - <%= tabular_form_with url: new_measurement_path, - html: {id: :new_readouts_form} do |f| %> - <% end %> -
- <%= select_tag :id, options_from_collection_for_select( - @quantities, :id, ->(q){ sanitize(' ' * q.depth + q.name) } - ), form: :new_readouts_form %> - <% common_options = {form: :new_readouts_form, formmethod: :get, - formnovalidate: true, data: {turbo_stream: true}} %> - <%= image_button_tag t('.new_quantity'), 'plus-outline', **common_options -%> - <%= image_button_tag t('.new_children'), 'plus-multiple-outline', - formaction: new_measurement_path(:children), **common_options -%> - <%= image_button_tag t('.new_subtree'), 'plus-multiple-outline', - formaction: new_measurement_path(:subtree), **common_options -%> -
+ <%= image_link_to t('.new_measurement'), 'plus-outline', new_measurement_path, + id: :new_measurement_link, onclick: 'this.blur();', + data: {turbo_stream: true} %> <% end %>
+ +<%= tag.div class: 'main', id: :measurement_form %> diff --git a/app/views/measurements/new.turbo_stream.erb b/app/views/measurements/new.turbo_stream.erb index 23f5364..1adc328 100644 --- a/app/views/measurements/new.turbo_stream.erb +++ b/app/views/measurements/new.turbo_stream.erb @@ -1,9 +1,4 @@ -<%= turbo_stream.update :new_readouts_form do %> - <%= render partial: 'form_frame' %> -<% end if @prev_quantities.empty? %> - -<%= render partial: 'form_repath' %> - -<%= turbo_stream.before :new_readouts_actions do %> +<%= turbo_stream.disable :new_measurement_link -%> +<%= turbo_stream.update :measurement_form do %> <%= render partial: 'form' %> <% end %> diff --git a/app/views/quantities/index.html.erb b/app/views/quantities/index.html.erb index 0ed1454..ea42e34 100644 --- a/app/views/quantities/index.html.erb +++ b/app/views/quantities/index.html.erb @@ -1,7 +1,8 @@
<% if current_user.at_least(:active) %> <%= image_link_to t('.new_quantity'), 'plus-outline', new_quantity_path, - id: dom_id(Quantity, :new, :link), onclick: 'this.blur();', data: {turbo_stream: true} %> + id: dom_id(Quantity, :new, :link), onclick: 'this.blur();', + data: {turbo_stream: true} %> <% end %> <%#= image_link_to t('.import_quantities'), 'download-outline', default_quantities_path, class: 'tools' %> diff --git a/app/views/readouts/_form.html.erb b/app/views/readouts/_form.html.erb new file mode 100644 index 0000000..62c7871 --- /dev/null +++ b/app/views/readouts/_form.html.erb @@ -0,0 +1,30 @@ +<%= tabular_fields_for 'readouts[]', readout do |form| %> + <%- tag.tr id: dom_id(readout.quantity, :new, :readout), + onkeydown: 'processKey(event)' do %> + + <%#= readout.quantity.relative_pathname(@common_ancestor) %> + <%= form.collection_select :quantity_id, @user_quantities, + :id, ->(q){ sanitize(' ' * q.depth + q.name) }, + {disabled: @quantities.map(&:id).delete!(form.object.quantity.id)}, + {class: 'quantity'} %> + + + <%= form.number_field :value, required: true, autofocus: true, size: 10 %> + + + <%= form.collection_select :unit_id, @user_units, :id, + ->(u){ sanitize(' ' * (u.base_id ? 1 : 0) + u.symbol) } %> + + + + <%= image_button_tag t('.new_children'), 'plus-multiple-outline', + formaction: new_measurement_path(readout.quantity, :children), + formmethod: :get, formnovalidate: true, data: {turbo_stream: true} %> + <%#= image_button_tag t('.new_subtree'), 'plus-multiple-outline', + formaction: new_measurement_path(:subtree), **common_options -%> + <%= image_button_tag '', 'delete-outline', class: 'dangerous', + formaction: discard_readouts_path(readout.quantity), + formmethod: :get, formnovalidate: true, data: {turbo_stream: true} %> + + <% end %> +<% end %> diff --git a/app/views/measurements/discard.turbo_stream.erb b/app/views/readouts/_form_discard.html.erb similarity index 100% rename from app/views/measurements/discard.turbo_stream.erb rename to app/views/readouts/_form_discard.html.erb diff --git a/app/views/measurements/_form_repath.html.erb b/app/views/readouts/_form_repath.html.erb similarity index 66% rename from app/views/measurements/_form_repath.html.erb rename to app/views/readouts/_form_repath.html.erb index 3edfd12..9167c85 100644 --- a/app/views/measurements/_form_repath.html.erb +++ b/app/views/readouts/_form_repath.html.erb @@ -1,4 +1,4 @@ -<%= turbo_stream.update(:new_readouts_form_legend) { @common_ancestor&.pathname } %> +<%= turbo_stream.update(:measurement_form_legend) { @common_ancestor&.pathname } %> <% @prev_quantities.each do |pq| %> <%= turbo_stream.update dom_id(pq, nil, :pathname) do %> diff --git a/app/views/readouts/new.turbo_stream.erb b/app/views/readouts/new.turbo_stream.erb new file mode 100644 index 0000000..c321479 --- /dev/null +++ b/app/views/readouts/new.turbo_stream.erb @@ -0,0 +1,8 @@ +<%#= render partial: 'form_repath' %> + +<% @readouts.each do |r| %> + <%= turbo_stream.disable_all "select.quantity option[value='#{r.quantity_id}']" %> +<% end %> +<%= turbo_stream.before :readouts_form do %> + <%= render partial: 'form', collection: @readouts, as: :readout %> +<% end %> diff --git a/config/initializers/core_ext.rb b/config/initializers/core_ext.rb index e73da73..1233f1b 100644 --- a/config/initializers/core_ext.rb +++ b/config/initializers/core_ext.rb @@ -1,3 +1,4 @@ +require 'core_ext/array_delete_bang' require 'core_ext/big_decimal_scientific_notation' ActiveSupport.on_load :action_dispatch_system_test_case do diff --git a/config/locales/en.yml b/config/locales/en.yml index 91d310f..ef6adae 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -64,8 +64,12 @@ en: source_code: Get code measurements: navigation: Measurements + form: + select_quantity: select quantity... index: - new_quantity: Selected + new_measurement: Add measurement + readouts: + form: new_children: Children new_subtree: Subtree quantities: diff --git a/config/routes.rb b/config/routes.rb index 6218a39..cc3e952 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,8 +1,10 @@ Rails.application.routes.draw do - resources :measurements, path_names: {new: '/new(/:scope)'}, - constraints: {scope: /children|subtree/}, defaults: {scope: nil} do + resources :measurements - get 'discard/:id', on: :new, action: :discard, as: :discard + resources :readouts, only: [:new], path_names: {new: '/new(/:id/:scope)'}, + constraints: {scope: /children|subtree|leaves/} do + + collection {get 'new/:id/discard', action: :discard, as: :discard} end resources :quantities, except: [:show], path_names: {new: '(/:id)/new'} do diff --git a/lib/core_ext/array_delete_bang.rb b/lib/core_ext/array_delete_bang.rb new file mode 100644 index 0000000..c10f974 --- /dev/null +++ b/lib/core_ext/array_delete_bang.rb @@ -0,0 +1,10 @@ +module CoreExt + module ArrayDeleteBang + def delete!(obj) + self.delete(obj) + self + end + end +end + +Array.prepend CoreExt::ArrayDeleteBang From 207699584beafdbec6a0d58f0cb17599df1c6b8d Mon Sep 17 00:00:00 2001 From: cryptogopher Date: Sun, 17 Aug 2025 01:03:08 +0200 Subject: [PATCH 2/3] Back to single-select form w/ multiple select actions --- .../images/pictograms/pencil-outline.svg | 1 + app/assets/stylesheets/application.css | 9 ++-- app/controllers/measurements_controller.rb | 2 + app/controllers/readouts_controller.rb | 11 +++-- app/helpers/quantities_helper.rb | 18 ++++++-- app/views/measurements/_form.html.erb | 41 ++++++++++++------- app/views/measurements/index.html.erb | 8 +++- app/views/readouts/_form.html.erb | 16 ++------ app/views/readouts/_form_discard.html.erb | 2 - app/views/readouts/_form_repath.html.erb | 4 +- app/views/readouts/discard.turbo_stream.erb | 5 +++ app/views/readouts/new.turbo_stream.erb | 9 ++-- config/locales/en.yml | 8 +++- config/routes.rb | 4 +- 14 files changed, 85 insertions(+), 53 deletions(-) create mode 100644 app/assets/images/pictograms/pencil-outline.svg delete mode 100644 app/views/readouts/_form_discard.html.erb create mode 100644 app/views/readouts/discard.turbo_stream.erb diff --git a/app/assets/images/pictograms/pencil-outline.svg b/app/assets/images/pictograms/pencil-outline.svg new file mode 100644 index 0000000..eb103c8 --- /dev/null +++ b/app/assets/images/pictograms/pencil-outline.svg @@ -0,0 +1 @@ + diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 7220e07..32dae52 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -56,7 +56,7 @@ body { grid-template-areas: "header header header" "nav nav nav" - "leftempty topside rightempty" + "leftside topside rightside" "leftside main rightside"; grid-template-columns: 1fr auto 1fr; grid-template-rows: repeat(4, auto); @@ -418,10 +418,10 @@ table.items td.link a::after { table.items td:first-child { padding-inline-start: calc(1em + var(--depth) * 0.8em); } -table.items td:has(input, textarea) { +table.items td:has(input, select, textarea) { padding-inline-start: calc(0.6em - 0.9px); } -table.items td:first-child:has(input, textarea) { +table.items td:first-child:has(input, select, textarea) { padding-inline-start: calc(0.6em + var(--depth) * 0.8em - 0.9px); } table.items th:last-child { @@ -560,6 +560,9 @@ form table.items td:first-child { display: flex; gap: 0.8em; } +.hflex.centered { + justify-content: center; +} .vflex { display: flex; gap: 0.8em; diff --git a/app/controllers/measurements_controller.rb b/app/controllers/measurements_controller.rb index 6d6dbf5..ebe6622 100644 --- a/app/controllers/measurements_controller.rb +++ b/app/controllers/measurements_controller.rb @@ -1,5 +1,7 @@ class MeasurementsController < ApplicationController def index + @measurements = [] + #@measurements = current_user.units.ordered.includes(:base, :subunits) end def new diff --git a/app/controllers/readouts_controller.rb b/app/controllers/readouts_controller.rb index a009260..d7b3870 100644 --- a/app/controllers/readouts_controller.rb +++ b/app/controllers/readouts_controller.rb @@ -4,7 +4,7 @@ class ReadoutsController < ApplicationController def new new_quantities = - case params[:scope] + case params[:button] when 'children' @quantity.subquantities when 'subtree' @@ -15,18 +15,17 @@ class ReadoutsController < ApplicationController new_quantities -= @prev_quantities @readouts = current_user.readouts.build(new_quantities.map { |q| {quantity: q} }) - @user_quantities = current_user.quantities.ordered @user_units = current_user.units.ordered - @quantities = @prev_quantities + new_quantities -# @common_ancestor = current_user.quantities -# .common_ancestors(all_quantities.map(&:parent_id)).first + quantities = @prev_quantities + new_quantities + @superquantity = current_user.quantities + .common_ancestors(quantities.map(&:parent_id)).first end def discard @prev_quantities -= [@quantity] - @common_ancestor = current_user.quantities + @superquantity = current_user.quantities .common_ancestors(@prev_quantities.map(&:parent_id)).first end diff --git a/app/helpers/quantities_helper.rb b/app/helpers/quantities_helper.rb index e6e42cf..cf1f741 100644 --- a/app/helpers/quantities_helper.rb +++ b/app/helpers/quantities_helper.rb @@ -1,7 +1,17 @@ module QuantitiesHelper - def quantity_options(quantities, selected: nil) - values = quantities.map { |q| [sanitize(' ' * q.depth + q.name), q.id] } - values.unshift([t('.select_quantity'), nil, {hidden: true}]) - options_for_select(values, selected: selected) + def quantity_option_text(quantity, checked = nil) + prefix = case checked + when true + # Use color and gray unicode emoji to assure same width. + # Avoid shapes similar to inputs (chackboxes, radio buttons etc.) + # (U+27A1 U+FE0F)/U+1F7E6/U+2705/U+1F499 U+2004 + '💙 ' + when false + # U+2B1C/U+1F90D U+2004 + '🤍 ' + else + '' + end + sanitize(' ' * quantity.depth + prefix + quantity.name) end end diff --git a/app/views/measurements/_form.html.erb b/app/views/measurements/_form.html.erb index 10ff507..6e1f675 100644 --- a/app/views/measurements/_form.html.erb +++ b/app/views/measurements/_form.html.erb @@ -1,29 +1,40 @@ <%= tabular_form_with model: Measurement.new do |form| %>
- <%= tag.span id: :measurement_form_legend %> - <%= image_link_to '', "close-outline", measurements_path, name: :cancel, - class: 'dangerous', onclick: render_turbo_stream('form_close') %> + <%= tag.span t('.no_items'), id: :measurement_form_legend %> + <%= image_link_to '', "pencil-outline", measurements_path, + data: {turbo_stream: true} %> + - - - - - -
- <%= select_tag :id, quantity_options(@quantities), onchange: - "this.form.requestSubmit(document.getElementById('readout_submit'));", - class: 'quantity' %> - <%= form.submit id: :readout_submit, name: nil, value: nil, - formaction: new_readout_path, formmethod: :get, formnovalidate: true, - hidden: true, data: {turbo_stream: true} %> + <%= select_tag :id, + options_from_collection_for_select( + @quantities, :id, ->(q){ quantity_option_text(q, false) } + ), class: 'quantity' %> + +
+ <% opts = {formaction: new_readout_path, formmethod: :get, + formnovalidate: true, data: {turbo_stream: true}} %> + <%= image_button_tag t('.new_readout'), 'plus-outline', id: :new_readout, + value: nil, **opts -%> + <%= image_button_tag t('.new_children'), 'plus-multiple-outline', + value: :children, **opts -%> + <%#= image_button_tag t('.new_subtree'), 'plus-multiple-outline', + value: :subtree, **opts -%> + <%= image_button_tag t('.new_leaves'), 'plus-multiple-outline', + value: :leaves, **opts -%> +
<%= form.button %>
+
+ <%= form.button -%> + <%= image_link_to t(:cancel), "close-outline", measurements_path, name: :cancel, + class: 'dangerous', onclick: render_turbo_stream('form_close') %> +
<% end %> diff --git a/app/views/measurements/index.html.erb b/app/views/measurements/index.html.erb index ad0c275..5cc12e9 100644 --- a/app/views/measurements/index.html.erb +++ b/app/views/measurements/index.html.erb @@ -7,4 +7,10 @@ <% end %>
-<%= tag.div class: 'main', id: :measurement_form %> +<%= tag.div class: 'topside', id: :measurement_form %> + + + + <%= render(@measurements) || render_no_items %> + +
diff --git a/app/views/readouts/_form.html.erb b/app/views/readouts/_form.html.erb index 62c7871..a9f0d37 100644 --- a/app/views/readouts/_form.html.erb +++ b/app/views/readouts/_form.html.erb @@ -1,28 +1,20 @@ +<%# TODO: add readout reordering by dragging %> <%= tabular_fields_for 'readouts[]', readout do |form| %> <%- tag.tr id: dom_id(readout.quantity, :new, :readout), onkeydown: 'processKey(event)' do %> - <%#= readout.quantity.relative_pathname(@common_ancestor) %> - <%= form.collection_select :quantity_id, @user_quantities, - :id, ->(q){ sanitize(' ' * q.depth + q.name) }, - {disabled: @quantities.map(&:id).delete!(form.object.quantity.id)}, - {class: 'quantity'} %> + <%= readout.quantity.relative_pathname(@superquantity) %> <%= form.number_field :value, required: true, autofocus: true, size: 10 %> + <%= form.hidden_field :quantity_id %> <%= form.collection_select :unit_id, @user_units, :id, ->(u){ sanitize(' ' * (u.base_id ? 1 : 0) + u.symbol) } %> - - <%= image_button_tag t('.new_children'), 'plus-multiple-outline', - formaction: new_measurement_path(readout.quantity, :children), - formmethod: :get, formnovalidate: true, data: {turbo_stream: true} %> - <%#= image_button_tag t('.new_subtree'), 'plus-multiple-outline', - formaction: new_measurement_path(:subtree), **common_options -%> - <%= image_button_tag '', 'delete-outline', class: 'dangerous', + <%= image_button_tag '', 'delete-outline', class: 'dangerous', name: :discard, formaction: discard_readouts_path(readout.quantity), formmethod: :get, formnovalidate: true, data: {turbo_stream: true} %> diff --git a/app/views/readouts/_form_discard.html.erb b/app/views/readouts/_form_discard.html.erb deleted file mode 100644 index 192a732..0000000 --- a/app/views/readouts/_form_discard.html.erb +++ /dev/null @@ -1,2 +0,0 @@ -<%= turbo_stream.remove dom_id(@quantity, :new, :readout) %> -<%= render partial: 'form_repath' %> diff --git a/app/views/readouts/_form_repath.html.erb b/app/views/readouts/_form_repath.html.erb index 9167c85..5743dec 100644 --- a/app/views/readouts/_form_repath.html.erb +++ b/app/views/readouts/_form_repath.html.erb @@ -1,7 +1,7 @@ -<%= turbo_stream.update(:measurement_form_legend) { @common_ancestor&.pathname } %> +<%= turbo_stream.update(:measurement_form_legend) { @superquantity&.pathname } %> <% @prev_quantities.each do |pq| %> <%= turbo_stream.update dom_id(pq, nil, :pathname) do %> - <%= pq.relative_pathname(@common_ancestor) %> + <%= pq.relative_pathname(@superquantity) %> <% end %> <% end %> diff --git a/app/views/readouts/discard.turbo_stream.erb b/app/views/readouts/discard.turbo_stream.erb new file mode 100644 index 0000000..8f14d3e --- /dev/null +++ b/app/views/readouts/discard.turbo_stream.erb @@ -0,0 +1,5 @@ +<%= turbo_stream.remove dom_id(@quantity, :new, :readout) %> +<%= turbo_stream.disable_all 'button[name="discard"]' if @prev_quantities.one? %> +<%= turbo_stream.update_all "#id option[value=\"#{@quantity.id}\"]", + quantity_option_text(@quantity, false) %> +<%= render partial: 'form_repath' %> diff --git a/app/views/readouts/new.turbo_stream.erb b/app/views/readouts/new.turbo_stream.erb index c321479..bd559a6 100644 --- a/app/views/readouts/new.turbo_stream.erb +++ b/app/views/readouts/new.turbo_stream.erb @@ -1,7 +1,10 @@ -<%#= render partial: 'form_repath' %> - +<%= render partial: 'form_repath' %> +<%= turbo_stream.enable_all 'button[name="discard"]' if @prev_quantities.one? %> +<%# TODO: disable Add actions accordingly (e.g. disable Children if childless or all + children already added), then disable option once all actions unavailable %> <% @readouts.each do |r| %> - <%= turbo_stream.disable_all "select.quantity option[value='#{r.quantity_id}']" %> + <%= turbo_stream.update_all "#id option[value=\"#{r.quantity_id}\"]", + quantity_option_text(r.quantity, true) %> <% end %> <%= turbo_stream.before :readouts_form do %> <%= render partial: 'form', collection: @readouts, as: :readout %> diff --git a/config/locales/en.yml b/config/locales/en.yml index ef6adae..d5264db 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -64,14 +64,18 @@ en: source_code: Get code measurements: navigation: Measurements + no_items: There are no measurements taken. You can Add some now. form: + new_readout: Add + new_children: Children + new_subtree: Subtree + new_leaves: Leaves + no_items: Select and add desired quantities... select_quantity: select quantity... index: new_measurement: Add measurement readouts: form: - new_children: Children - new_subtree: Subtree quantities: navigation: Quantities no_items: There are no configured quantities. You can Add some or Import from defaults. diff --git a/config/routes.rb b/config/routes.rb index cc3e952..7d3035d 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,9 +1,7 @@ Rails.application.routes.draw do resources :measurements - resources :readouts, only: [:new], path_names: {new: '/new(/:id/:scope)'}, - constraints: {scope: /children|subtree|leaves/} do - + resources :readouts, only: [:new] do collection {get 'new/:id/discard', action: :discard, as: :discard} end From 1acb179851b3b52b09bd62c15c1697cec36c5d01 Mon Sep 17 00:00:00 2001 From: cryptogopher Date: Thu, 15 Jan 2026 19:00:25 +0100 Subject: [PATCH 3/3] Single select form without action buttons --- app/assets/stylesheets/application.css | 3 ++ app/helpers/quantities_helper.rb | 15 --------- app/models/quantity.rb | 5 +++ app/views/measurements/_form.html.erb | 34 ++++++--------------- app/views/readouts/discard.turbo_stream.erb | 3 +- app/views/readouts/new.turbo_stream.erb | 6 ++-- config/locales/en.yml | 8 ++--- 7 files changed, 22 insertions(+), 52 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 32dae52..d45ffea 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -563,6 +563,9 @@ form table.items td:first-child { .hflex.centered { justify-content: center; } +.vexpand { + width: 100%; +} .vflex { display: flex; gap: 0.8em; diff --git a/app/helpers/quantities_helper.rb b/app/helpers/quantities_helper.rb index cf1f741..9e6aa8b 100644 --- a/app/helpers/quantities_helper.rb +++ b/app/helpers/quantities_helper.rb @@ -1,17 +1,2 @@ module QuantitiesHelper - def quantity_option_text(quantity, checked = nil) - prefix = case checked - when true - # Use color and gray unicode emoji to assure same width. - # Avoid shapes similar to inputs (chackboxes, radio buttons etc.) - # (U+27A1 U+FE0F)/U+1F7E6/U+2705/U+1F499 U+2004 - '💙 ' - when false - # U+2B1C/U+1F90D U+2004 - '🤍 ' - else - '' - end - sanitize(' ' * quantity.depth + prefix + quantity.name) - end end diff --git a/app/models/quantity.rb b/app/models/quantity.rb index 6748492..ed81124 100644 --- a/app/models/quantity.rb +++ b/app/models/quantity.rb @@ -100,6 +100,11 @@ class Quantity < ApplicationRecord name end + def to_s_with_depth + # em space, U+2003 + ' ' * depth + name + end + def destroyable? subquantities.empty? end diff --git a/app/views/measurements/_form.html.erb b/app/views/measurements/_form.html.erb index 6e1f675..e85d036 100644 --- a/app/views/measurements/_form.html.erb +++ b/app/views/measurements/_form.html.erb @@ -1,32 +1,16 @@ <%= tabular_form_with model: Measurement.new do |form| %>
- - <%= tag.span t('.no_items'), id: :measurement_form_legend %> - <%= image_link_to '', "pencil-outline", measurements_path, - data: {turbo_stream: true} %> - - +
- - diff --git a/app/views/readouts/discard.turbo_stream.erb b/app/views/readouts/discard.turbo_stream.erb index 8f14d3e..ae275ca 100644 --- a/app/views/readouts/discard.turbo_stream.erb +++ b/app/views/readouts/discard.turbo_stream.erb @@ -1,5 +1,4 @@ <%= turbo_stream.remove dom_id(@quantity, :new, :readout) %> <%= turbo_stream.disable_all 'button[name="discard"]' if @prev_quantities.one? %> -<%= turbo_stream.update_all "#id option[value=\"#{@quantity.id}\"]", - quantity_option_text(@quantity, false) %> +<%= turbo_stream.enable_all "select.quantity option[value='#{@quantity.id}']" %> <%= render partial: 'form_repath' %> diff --git a/app/views/readouts/new.turbo_stream.erb b/app/views/readouts/new.turbo_stream.erb index bd559a6..241bc21 100644 --- a/app/views/readouts/new.turbo_stream.erb +++ b/app/views/readouts/new.turbo_stream.erb @@ -1,10 +1,8 @@ <%= render partial: 'form_repath' %> +<%# is .one? proper condition? can @readouts be empty? %> <%= turbo_stream.enable_all 'button[name="discard"]' if @prev_quantities.one? %> -<%# TODO: disable Add actions accordingly (e.g. disable Children if childless or all - children already added), then disable option once all actions unavailable %> <% @readouts.each do |r| %> - <%= turbo_stream.update_all "#id option[value=\"#{r.quantity_id}\"]", - quantity_option_text(r.quantity, true) %> + <%= turbo_stream.disable_all "select.quantity option[value='#{r.quantity_id}']" %> <% end %> <%= turbo_stream.before :readouts_form do %> <%= render partial: 'form', collection: @readouts, as: :readout %> diff --git a/config/locales/en.yml b/config/locales/en.yml index d5264db..278be59 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -66,16 +66,12 @@ en: navigation: Measurements no_items: There are no measurements taken. You can Add some now. form: - new_readout: Add - new_children: Children - new_subtree: Subtree - new_leaves: Leaves - no_items: Select and add desired quantities... - select_quantity: select quantity... + select_quantity: select the measured quantity... index: new_measurement: Add measurement readouts: form: + new_children: Children quantities: navigation: Quantities no_items: There are no configured quantities. You can Add some or Import from defaults.
- <%= select_tag :id, - options_from_collection_for_select( - @quantities, :id, ->(q){ quantity_option_text(q, false) } - ), class: 'quantity' %> - -
- <% opts = {formaction: new_readout_path, formmethod: :get, - formnovalidate: true, data: {turbo_stream: true}} %> - <%= image_button_tag t('.new_readout'), 'plus-outline', id: :new_readout, - value: nil, **opts -%> - <%= image_button_tag t('.new_children'), 'plus-multiple-outline', - value: :children, **opts -%> - <%#= image_button_tag t('.new_subtree'), 'plus-multiple-outline', - value: :subtree, **opts -%> - <%= image_button_tag t('.new_leaves'), 'plus-multiple-outline', - value: :leaves, **opts -%> -
+
+ <%= collection_select :quantity, :id, @quantities, :id, :to_s_with_depth, + {prompt: t('.select_quantity'), disabled: '', selected: ''}, + {name: :id, class: 'quantity vexpand', + onchange: "this.form.requestSubmit(new_readout_submit);"} %> + <%= form.submit id: :new_readout_submit, name: nil, value: nil, + formaction: new_readout_path, formmethod: :get, formnovalidate: true, + hidden: true, data: {turbo_stream: true} %>