Implement Measurements#new
This commit is contained in:
		
							parent
							
								
									2f3c0e40a6
								
							
						
					
					
						commit
						c48bf290fd
					
				@ -49,15 +49,18 @@
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* TODO: collapse gaps around empty rows (`topside`) once possible
 | 
				
			||||||
 | 
					 * https://github.com/w3c/csswg-drafts/issues/5813 */
 | 
				
			||||||
body {
 | 
					body {
 | 
				
			||||||
  display: grid;
 | 
					  display: grid;
 | 
				
			||||||
  gap: 0.8em;
 | 
					  gap: 0.8em;
 | 
				
			||||||
  grid-template-areas:
 | 
					  grid-template-areas:
 | 
				
			||||||
    "header    header  header"
 | 
					    "header    header  header"
 | 
				
			||||||
    "nav       nav     nav"
 | 
					    "nav       nav     nav"
 | 
				
			||||||
 | 
					    "leftempty topside rightempty"
 | 
				
			||||||
    "leftside  main    rightside";
 | 
					    "leftside  main    rightside";
 | 
				
			||||||
  grid-template-columns: 1fr auto 1fr;
 | 
					  grid-template-columns: 1fr auto 1fr;
 | 
				
			||||||
  grid-template-rows: repeat(3, auto);
 | 
					  grid-template-rows: repeat(4, auto);
 | 
				
			||||||
  font-family: system-ui;
 | 
					  font-family: system-ui;
 | 
				
			||||||
  margin: 0.4em;
 | 
					  margin: 0.4em;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -108,12 +111,14 @@ textarea {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
.button,
 | 
					.button,
 | 
				
			||||||
button,
 | 
					button,
 | 
				
			||||||
 | 
					fieldset,
 | 
				
			||||||
input,
 | 
					input,
 | 
				
			||||||
select,
 | 
					select,
 | 
				
			||||||
textarea {
 | 
					textarea {
 | 
				
			||||||
  border: solid 1px var(--color-gray);
 | 
					  border: solid 1px var(--color-gray);
 | 
				
			||||||
  border-radius: 0.25em;
 | 
					  border-radius: 0.25em;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					fieldset,
 | 
				
			||||||
textarea {
 | 
					textarea {
 | 
				
			||||||
  margin: 0
 | 
					  margin: 0
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -124,6 +129,12 @@ button > svg {
 | 
				
			|||||||
  padding-right: 0.4em;
 | 
					  padding-right: 0.4em;
 | 
				
			||||||
  width: 1.8em;
 | 
					  width: 1.8em;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					fieldset {
 | 
				
			||||||
 | 
					  padding: 0.4em;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					legend {
 | 
				
			||||||
 | 
					  color: var(--color-gray);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* TODO: move normal non-button links (<a>:hover/:focus) styling here (i.e.
 | 
					/* TODO: move normal non-button links (<a>:hover/:focus) styling here (i.e.
 | 
				
			||||||
 * page-wide, top-level) and remove from table.items - as the style should be
 | 
					 * page-wide, top-level) and remove from table.items - as the style should be
 | 
				
			||||||
@ -230,6 +241,9 @@ header {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.topside {
 | 
				
			||||||
 | 
					  grid-area: topside;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
.leftside {
 | 
					.leftside {
 | 
				
			||||||
  grid-area: leftside;
 | 
					  grid-area: leftside;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -409,8 +423,7 @@ table.items td {
 | 
				
			|||||||
  height: 2.4em;
 | 
					  height: 2.4em;
 | 
				
			||||||
  padding-block: 0.1em;
 | 
					  padding-block: 0.1em;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
table.items td.actions {
 | 
					table.items .actions {
 | 
				
			||||||
  align-items: center;
 | 
					 | 
				
			||||||
  display: flex;
 | 
					  display: flex;
 | 
				
			||||||
  gap: 0.4em;
 | 
					  gap: 0.4em;
 | 
				
			||||||
  justify-content: end;
 | 
					  justify-content: end;
 | 
				
			||||||
@ -505,6 +518,17 @@ table.items select:focus-visible {
 | 
				
			|||||||
  color: black;
 | 
					  color: black;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					form table.items {
 | 
				
			||||||
 | 
					  border: none;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					form table.items td {
 | 
				
			||||||
 | 
					  border: none;
 | 
				
			||||||
 | 
					  text-align: left;
 | 
				
			||||||
 | 
					  vertical-align: middle;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					form table.items td:first-child {
 | 
				
			||||||
 | 
					  color: inherit;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.centered {
 | 
					.centered {
 | 
				
			||||||
  margin: 0 auto;
 | 
					  margin: 0 auto;
 | 
				
			||||||
@ -512,10 +536,15 @@ table.items select:focus-visible {
 | 
				
			|||||||
.extendedright {
 | 
					.extendedright {
 | 
				
			||||||
  margin-right: auto;
 | 
					  margin-right: auto;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.htoolbox {
 | 
					.hflex {
 | 
				
			||||||
  display: flex;
 | 
					  display: flex;
 | 
				
			||||||
  gap: 0.8em;
 | 
					  gap: 0.8em;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					.vflex {
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  gap: 0.8em;
 | 
				
			||||||
 | 
					  flex-direction: column;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
[disabled] {
 | 
					[disabled] {
 | 
				
			||||||
  border-color: var(--color-border-gray) !important;
 | 
					  border-color: var(--color-border-gray) !important;
 | 
				
			||||||
  color: var(--color-border-gray) !important;
 | 
					  color: var(--color-border-gray) !important;
 | 
				
			||||||
 | 
				
			|||||||
@ -1,9 +1,31 @@
 | 
				
			|||||||
class MeasurementsController < ApplicationController
 | 
					class MeasurementsController < ApplicationController
 | 
				
			||||||
 | 
					  before_action :find_quantity, only: [:new]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def index
 | 
					  def index
 | 
				
			||||||
    @quantities = current_user.quantities.ordered
 | 
					    @quantities = current_user.quantities.ordered
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def new
 | 
					  def new
 | 
				
			||||||
 | 
					    readouts_params = params.permit(user: [readouts_attributes: Readout::ATTRIBUTES])
 | 
				
			||||||
 | 
					    build_attrs = readouts_params.dig(:user, :readouts_attributes)&.values
 | 
				
			||||||
 | 
					    prev_readouts = build_attrs ? Array(current_user.readouts.build(build_attrs)) : []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    quantities =
 | 
				
			||||||
 | 
					      case params[:scope]
 | 
				
			||||||
 | 
					      when 'children'
 | 
				
			||||||
 | 
					        @quantity.subquantities
 | 
				
			||||||
 | 
					      when 'subtree'
 | 
				
			||||||
 | 
					        @quantity.progenies
 | 
				
			||||||
 | 
					      else
 | 
				
			||||||
 | 
					        [@quantity]
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    quantities -= prev_readouts.map(&:quantity)
 | 
				
			||||||
 | 
					    new_readouts = current_user.readouts.build(quantities.map { |q| {quantity: q} })
 | 
				
			||||||
 | 
					    @readouts = prev_readouts + new_readouts
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @ancestor_fullname = current_user.quantities
 | 
				
			||||||
 | 
					      .common_ancestors(@readouts.map { |r| r.quantity.parent_id }).first&.fullname || ''
 | 
				
			||||||
 | 
					    @units = current_user.units.ordered
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def create
 | 
					  def create
 | 
				
			||||||
@ -11,4 +33,10 @@ class MeasurementsController < ApplicationController
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  def destroy
 | 
					  def destroy
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def find_quantity
 | 
				
			||||||
 | 
					    @quantity = current_user.quantities.find_by!(id: params[:id])
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
				
			|||||||
@ -104,11 +104,12 @@ module ApplicationHelper
 | 
				
			|||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def tabular_fields_for(record_name, record_object = nil, options = {}, &block)
 | 
					  def tabular_fields_for(record_name, record_object = nil, options = {}, &block)
 | 
				
			||||||
    # skip_default_ids causes turbo to generate unique ID for element with [autofocus].
 | 
					    # skip_default_ids causes turbo to generate unique ID for element with
 | 
				
			||||||
    # Otherwise IDs are not unique when multiple forms are open and the first input gets focus.
 | 
					    # [autofocus].  Otherwise IDs are not unique when multiple forms are open
 | 
				
			||||||
 | 
					    # and the first input gets focus.
 | 
				
			||||||
    record_object, options = nil, record_object if record_object.is_a? Hash
 | 
					    record_object, options = nil, record_object if record_object.is_a? Hash
 | 
				
			||||||
    options.merge! builder: TabularFormBuilder, skip_default_ids: true
 | 
					    options.merge! builder: TabularFormBuilder, skip_default_ids: true
 | 
				
			||||||
    render_errors(record_name)
 | 
					    render_errors(record_object || record_name)
 | 
				
			||||||
    fields_for(record_name, record_object, **options, &block)
 | 
					    fields_for(record_name, record_object, **options, &block)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -169,8 +170,9 @@ module ApplicationHelper
 | 
				
			|||||||
    link_to name, options, html_options
 | 
					    link_to name, options, html_options
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def render_errors(record)
 | 
					  def render_errors(records)
 | 
				
			||||||
    flash.now[:alert] = record.errors.full_messages unless record.errors.empty?
 | 
					    flash[:alert] ||= []
 | 
				
			||||||
 | 
					    Array(records).each { |record| flash[:alert] += record.errors.full_messages }
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def render_flash_messages
 | 
					  def render_flash_messages
 | 
				
			||||||
 | 
				
			|||||||
@ -61,17 +61,20 @@ class Quantity < ApplicationRecord
 | 
				
			|||||||
  scope :defaults, ->{ where(user: nil) }
 | 
					  scope :defaults, ->{ where(user: nil) }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # Return: ordered [sub]hierarchy
 | 
					  # Return: ordered [sub]hierarchy
 | 
				
			||||||
  scope :ordered, ->(root: nil) {
 | 
					  scope :ordered, ->(root: nil, include_root: true) {
 | 
				
			||||||
    numbered = Arel::Table.new('numbered')
 | 
					    numbered = Arel::Table.new('numbered')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    self.model.with(numbered: numbered(:parent_id, :name)).with_recursive(arel_table.name => [
 | 
					    self.model.with(numbered: numbered(:parent_id, :name)).with_recursive(arel_table.name => [
 | 
				
			||||||
      numbered.project(
 | 
					      numbered.project(
 | 
				
			||||||
        numbered[Arel.star],
 | 
					        numbered[Arel.star],
 | 
				
			||||||
        numbered.cast(numbered[:child_number], 'BINARY').as('path'),
 | 
					        numbered.cast(numbered[:child_number], 'BINARY').as('path'),
 | 
				
			||||||
      ).where(numbered[root ? :id : :parent_id].eq(root)),
 | 
					        numbered.cast(numbered[:name], 'CHAR(512)').as('fullname')
 | 
				
			||||||
 | 
					      ).where(numbered[root && include_root ? :id : :parent_id].eq(root)),
 | 
				
			||||||
      numbered.project(
 | 
					      numbered.project(
 | 
				
			||||||
        numbered[Arel.star],
 | 
					        numbered[Arel.star],
 | 
				
			||||||
        arel_table[:path].concat(numbered[:child_number]),
 | 
					        arel_table[:path].concat(numbered[:child_number]),
 | 
				
			||||||
 | 
					        arel_table[:fullname].concat(Arel::Nodes.build_quoted(' → '))
 | 
				
			||||||
 | 
					          .concat(numbered[:name]),
 | 
				
			||||||
      ).join(arel_table).on(numbered[:parent_id].eq(arel_table[:id]))
 | 
					      ).join(arel_table).on(numbered[:parent_id].eq(arel_table[:id]))
 | 
				
			||||||
    ]).order(arel_table[:path])
 | 
					    ]).order(arel_table[:path])
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@ -109,6 +112,23 @@ class Quantity < ApplicationRecord
 | 
				
			|||||||
    parent_id.nil?
 | 
					    parent_id.nil?
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # Common ancestors, assuming node is a descendant of itself
 | 
				
			||||||
 | 
					  scope :common_ancestors, ->(of) {
 | 
				
			||||||
 | 
					    selected = Arel::Table.new('selected')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Take unique IDs, so self can be called with parent nodes of collection to
 | 
				
			||||||
 | 
					    # get common ancestors of collection _excluding_ nodes in collection.
 | 
				
			||||||
 | 
					    uniq_of = of.uniq
 | 
				
			||||||
 | 
					    model.with(selected: self).with_recursive(arel_table.name => [
 | 
				
			||||||
 | 
					      selected.project(selected[Arel.star]).where(selected[:id].in(uniq_of)),
 | 
				
			||||||
 | 
					      selected.project(selected[Arel.star])
 | 
				
			||||||
 | 
					        .join(arel_table).on(selected[:id].eq(arel_table[:parent_id]))
 | 
				
			||||||
 | 
					    ]).select(arel_table[Arel.star])
 | 
				
			||||||
 | 
					      .group(column_names)
 | 
				
			||||||
 | 
					      .having(arel_table[:id].count.eq(uniq_of.size))
 | 
				
			||||||
 | 
					      .order(arel_table[:depth].desc)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # Return: successive record in order of appearance; used for partial view reload
 | 
					  # Return: successive record in order of appearance; used for partial view reload
 | 
				
			||||||
  def successive
 | 
					  def successive
 | 
				
			||||||
    quantities = Quantity.arel_table
 | 
					    quantities = Quantity.arel_table
 | 
				
			||||||
@ -124,6 +144,10 @@ class Quantity < ApplicationRecord
 | 
				
			|||||||
    user.quantities.ordered(root: id).to_a
 | 
					    user.quantities.ordered(root: id).to_a
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def progenies
 | 
				
			||||||
 | 
					    user.quantities.ordered(root: id, include_root: false).to_a
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # Return: record with ID `of` with its ancestors, sorted by `depth`
 | 
					  # Return: record with ID `of` with its ancestors, sorted by `depth`
 | 
				
			||||||
  scope :with_ancestors, ->(of) {
 | 
					  scope :with_ancestors, ->(of) {
 | 
				
			||||||
    selected = Arel::Table.new('selected')
 | 
					    selected = Arel::Table.new('selected')
 | 
				
			||||||
@ -143,4 +167,9 @@ class Quantity < ApplicationRecord
 | 
				
			|||||||
  def ancestor_of?(progeny)
 | 
					  def ancestor_of?(progeny)
 | 
				
			||||||
    user.quantities.with_ancestors(progeny.id).exists?(id)
 | 
					    user.quantities.with_ancestors(progeny.id).exists?(id)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def fullname
 | 
				
			||||||
 | 
					    self['fullname'] ||
 | 
				
			||||||
 | 
					      user.quantities.with_ancestors(id).order(:depth).map(&:name).join(' → ')
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,6 @@
 | 
				
			|||||||
class Readout < ApplicationRecord
 | 
					class Readout < ApplicationRecord
 | 
				
			||||||
 | 
					  ATTRIBUTES = [:quantity_id, :value, :unit_id]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  belongs_to :user
 | 
					  belongs_to :user
 | 
				
			||||||
  belongs_to :quantity
 | 
					  belongs_to :quantity
 | 
				
			||||||
  belongs_to :unit
 | 
					  belongs_to :unit
 | 
				
			||||||
 | 
				
			|||||||
@ -11,6 +11,8 @@ class User < ApplicationRecord
 | 
				
			|||||||
    disabled: 0,    # administratively disallowed to sign in
 | 
					    disabled: 0,    # administratively disallowed to sign in
 | 
				
			||||||
  }, default: :active
 | 
					  }, default: :active
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  has_many :readouts, dependent: :destroy
 | 
				
			||||||
 | 
					  accepts_nested_attributes_for :readouts
 | 
				
			||||||
  has_many :quantities, dependent: :destroy
 | 
					  has_many :quantities, dependent: :destroy
 | 
				
			||||||
  has_many :units, dependent: :destroy
 | 
					  has_many :units, dependent: :destroy
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -23,7 +23,7 @@
 | 
				
			|||||||
  </head>
 | 
					  </head>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  <body>
 | 
					  <body>
 | 
				
			||||||
    <header class="htoolbox">
 | 
					    <header class="hflex">
 | 
				
			||||||
      <%= image_link_to t(".source_code"), "code-braces", source_code_url %>
 | 
					      <%= image_link_to t(".source_code"), "code-braces", source_code_url %>
 | 
				
			||||||
      <%= image_link_to t(".issue_tracker"), "bug-outline", issue_tracker_url,
 | 
					      <%= image_link_to t(".issue_tracker"), "bug-outline", issue_tracker_url,
 | 
				
			||||||
            class: "extendedright" %>
 | 
					            class: "extendedright" %>
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										45
									
								
								app/views/measurements/_form.html.erb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								app/views/measurements/_form.html.erb
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,45 @@
 | 
				
			|||||||
 | 
					<%= tabular_form_with model: current_user, html: {id: :new_readouts_form} do |user| %>
 | 
				
			||||||
 | 
					  <% if @readouts&.present? %>
 | 
				
			||||||
 | 
					    <fieldset>
 | 
				
			||||||
 | 
					      <%= tag.legend @ancestor_fullname unless @ancestor_fullname.empty? %>
 | 
				
			||||||
 | 
					      <table class="items centered">
 | 
				
			||||||
 | 
					        <tbody id="readouts">
 | 
				
			||||||
 | 
					          <%= user.fields_for :readouts, @readouts do |form| %>
 | 
				
			||||||
 | 
					            <% row = dom_id(form.object.quantity, :new, :readout) %>
 | 
				
			||||||
 | 
					            <%- tag.tr id: row, onkeydown: 'processKey(event)' do %>
 | 
				
			||||||
 | 
					              <td>
 | 
				
			||||||
 | 
					                <%= form.object.quantity.fullname.delete_prefix(@ancestor_fullname) %>
 | 
				
			||||||
 | 
					                <%= form.hidden_field :quantity_id %>
 | 
				
			||||||
 | 
					              </td>
 | 
				
			||||||
 | 
					              <td>
 | 
				
			||||||
 | 
					                <%= form.number_field :value, required: true, autofocus: true,
 | 
				
			||||||
 | 
					                  size: 10 %>
 | 
				
			||||||
 | 
					              </td>
 | 
				
			||||||
 | 
					              <td>
 | 
				
			||||||
 | 
					                <%= form.select :unit_id, options_from_collection_for_select(
 | 
				
			||||||
 | 
					                  @units, :id, ->(u){ sanitize(' '*(u.base_id ? 1 : 0) + u.symbol) }
 | 
				
			||||||
 | 
					                ) %>
 | 
				
			||||||
 | 
					              </td>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					              <td class="actions">
 | 
				
			||||||
 | 
					                <%= image_link_to t(:delete), 'delete-outline', quantities_path,
 | 
				
			||||||
 | 
					                  class: 'dangerous',
 | 
				
			||||||
 | 
					                  onclick: render_turbo_stream('form_destroy_row', {row: row}) %>
 | 
				
			||||||
 | 
					              </td>
 | 
				
			||||||
 | 
					            <% end %>
 | 
				
			||||||
 | 
					          <% end %>
 | 
				
			||||||
 | 
					          <tr id="new_readouts_actions">
 | 
				
			||||||
 | 
					            <td></td>
 | 
				
			||||||
 | 
					            <td></td>
 | 
				
			||||||
 | 
					            <td><div class="actions"><%= user.button %></div></td>
 | 
				
			||||||
 | 
					            <td><div class="actions">
 | 
				
			||||||
 | 
					              <%= image_link_to t(:cancel), "close-outline", measurements_path,
 | 
				
			||||||
 | 
					                class: 'dangerous', name: :cancel,
 | 
				
			||||||
 | 
					                onclick: render_turbo_stream('form_close') %>
 | 
				
			||||||
 | 
					            </div></td>
 | 
				
			||||||
 | 
					          </tr>
 | 
				
			||||||
 | 
					        </tbody>
 | 
				
			||||||
 | 
					      </table>
 | 
				
			||||||
 | 
					    </fieldset>
 | 
				
			||||||
 | 
					  <% end %>
 | 
				
			||||||
 | 
					<% end %>
 | 
				
			||||||
							
								
								
									
										2
									
								
								app/views/measurements/_form_close.html.erb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								app/views/measurements/_form_close.html.erb
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					<%= turbo_stream.update :new_readouts_form %>
 | 
				
			||||||
 | 
					<%= turbo_stream.update :flashes %>
 | 
				
			||||||
							
								
								
									
										2
									
								
								app/views/measurements/_form_destroy_row.html.erb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								app/views/measurements/_form_destroy_row.html.erb
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					<%= turbo_stream.remove row %>
 | 
				
			||||||
 | 
					<%= turbo_stream.update :flashes %>
 | 
				
			||||||
@ -1,16 +1,20 @@
 | 
				
			|||||||
<div class="main">
 | 
					<div class="topside vflex">
 | 
				
			||||||
  <% if current_user.at_least(:active) %>
 | 
					  <% if current_user.at_least(:active) %>
 | 
				
			||||||
 | 
					    <%= render partial: 'form' %>
 | 
				
			||||||
    <%# TODO: show hint when no quantities/units defined %>
 | 
					    <%# TODO: show hint when no quantities/units defined %>
 | 
				
			||||||
    <%= form_tag new_measurement_path, method: :get, class: "htoolbox",
 | 
					    <div class="hflex">
 | 
				
			||||||
      data: {turbo_stream: true} do %>
 | 
					      <%= select_tag :id, options_from_collection_for_select(
 | 
				
			||||||
      <%= select_tag :id,
 | 
					        @quantities, :id, ->(q){ sanitize(' '*q.depth + q.name) }
 | 
				
			||||||
        options_from_collection_for_select(@quantities, :id,
 | 
					      ), form: :new_readouts_form %>
 | 
				
			||||||
                                           ->(q) { sanitize('- '*q.depth + q.name) }) %>
 | 
					      <% common_options = {form: :new_readouts_form, formaction: new_measurement_path,
 | 
				
			||||||
      <%= image_button_tag t('.new_quantity'), 'plus-outline', name: :scope -%>
 | 
					                           formmethod: :get, formnovalidate: true,
 | 
				
			||||||
 | 
					                           data: {turbo_stream: true}} %>
 | 
				
			||||||
 | 
					      <%= image_button_tag t('.new_quantity'), 'plus-outline', name: :scope,
 | 
				
			||||||
 | 
					        **common_options -%>
 | 
				
			||||||
      <%= image_button_tag t('.new_children'), 'plus-multiple-outline', name: :scope,
 | 
					      <%= image_button_tag t('.new_children'), 'plus-multiple-outline', name: :scope,
 | 
				
			||||||
        value: :children -%>
 | 
					        value: :children, **common_options -%>
 | 
				
			||||||
      <%= image_button_tag t('.new_subtree'), 'plus-multiple-outline', name: :scope,
 | 
					      <%= image_button_tag t('.new_subtree'), 'plus-multiple-outline', name: :scope,
 | 
				
			||||||
        value: :subtree -%>
 | 
					        value: :subtree, **common_options -%>
 | 
				
			||||||
    <% end %>
 | 
					    </div>
 | 
				
			||||||
  <% end %>
 | 
					  <% end %>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										3
									
								
								app/views/measurements/new.turbo_stream.erb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								app/views/measurements/new.turbo_stream.erb
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					<%= turbo_stream.replace :new_readouts_form, method: :morph do %>
 | 
				
			||||||
 | 
					  <%= render partial: 'form' %>
 | 
				
			||||||
 | 
					<% end %>
 | 
				
			||||||
@ -7,7 +7,7 @@
 | 
				
			|||||||
    class: 'tools' %>
 | 
					    class: 'tools' %>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<%= tag.div id: :quantity_form %>
 | 
					<%= tag.div class: 'main', id: :quantity_form %>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<table class="main items">
 | 
					<table class="main items">
 | 
				
			||||||
  <thead>
 | 
					  <thead>
 | 
				
			||||||
 | 
				
			|||||||
@ -151,6 +151,7 @@ en:
 | 
				
			|||||||
  add: Add
 | 
					  add: Add
 | 
				
			||||||
  back: Back
 | 
					  back: Back
 | 
				
			||||||
  cancel: Cancel
 | 
					  cancel: Cancel
 | 
				
			||||||
 | 
					  delete: Delete
 | 
				
			||||||
  or: or
 | 
					  or: or
 | 
				
			||||||
  register: Register
 | 
					  register: Register
 | 
				
			||||||
  sign_in: Sign in
 | 
					  sign_in: Sign in
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user