From 46dd480b4ea46df3df0b44151b34964ea4c96979 Mon Sep 17 00:00:00 2001 From: cryptogopher Date: Fri, 15 Aug 2025 23:26:57 +0200 Subject: [PATCH] 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