Compare commits
	
		
			5 Commits
		
	
	
		
			0d8e7c6c0e
			...
			1e7ef75e8b
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 1e7ef75e8b | |||
| c7f16514d2 | |||
| 23e2f6a062 | |||
| 9461c1f979 | |||
| fa7918f0e3 | 
@ -379,7 +379,8 @@ table.items td {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
/* For <a> to fill <td> completely, we use an ::after pseudoelement. */
 | 
					/* For <a> to fill <td> completely, we use an ::after pseudoelement. */
 | 
				
			||||||
table.items td.link {
 | 
					table.items td.link {
 | 
				
			||||||
  padding: 0 0 0 1em;
 | 
					  padding: 0;
 | 
				
			||||||
 | 
					  padding-inline-start: calc(1em + var(--depth) * 0.8em);
 | 
				
			||||||
  position: relative;
 | 
					  position: relative;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
table.items td.link a {
 | 
					table.items td.link a {
 | 
				
			||||||
 | 
				
			|||||||
@ -12,38 +12,33 @@ class Quantity < ApplicationRecord
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  scope :defaults, ->{ where(user: nil) }
 | 
					  scope :defaults, ->{ where(user: nil) }
 | 
				
			||||||
  scope :ordered, ->{
 | 
					  scope :ordered, ->{
 | 
				
			||||||
    cte = Arel::Table.new('cte')
 | 
					 | 
				
			||||||
    numbered = Arel::Table.new('numbered')
 | 
					    numbered = Arel::Table.new('numbered')
 | 
				
			||||||
    Quantity.with(numbered: numbered(:parent_id, :name)).with_recursive(
 | 
					    Quantity.with(numbered: numbered(:parent_id, :name)).with_recursive(quantities: [
 | 
				
			||||||
      cte:
 | 
					 | 
				
			||||||
      [
 | 
					 | 
				
			||||||
      Arel::SelectManager.new.project(
 | 
					      Arel::SelectManager.new.project(
 | 
				
			||||||
        numbered[Arel.star],
 | 
					        numbered[Arel.star],
 | 
				
			||||||
          numbered.cast(numbered[:child_number], 'BINARY').as('path')
 | 
					        numbered.cast(numbered[:child_number], 'BINARY').as('path'),
 | 
				
			||||||
 | 
					        Arel::Nodes.build_quoted(0).as('depth')
 | 
				
			||||||
      ).from(numbered).where(numbered[:parent_id].eq(nil)),
 | 
					      ).from(numbered).where(numbered[:parent_id].eq(nil)),
 | 
				
			||||||
      Arel::SelectManager.new.project(
 | 
					      Arel::SelectManager.new.project(
 | 
				
			||||||
        numbered[Arel.star],
 | 
					        numbered[Arel.star],
 | 
				
			||||||
          cte[:path].concat(numbered[:child_number])
 | 
					        arel_table[:path].concat(numbered[:child_number]),
 | 
				
			||||||
        ).from(numbered).join(cte).on(numbered[:parent_id].eq(cte[:id]))
 | 
					        arel_table[:depth] + 1
 | 
				
			||||||
      ]
 | 
					      ).from(numbered).join(arel_table).on(numbered[:parent_id].eq(arel_table[:id]))
 | 
				
			||||||
    ).select(cte[Arel.star]).from(cte).order(cte[:path])
 | 
					    ]).select(arel_table[Arel.star]).from(arel_table).order(arel_table[:path])
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # TODO: extract named functions to custom Arel extension
 | 
				
			||||||
 | 
					  # https://gist.github.com/ProGM/c6df08da14708dcc28b5ca325df37ceb#extending-arel
 | 
				
			||||||
  scope :numbered, ->(parent_column, order_column){
 | 
					  scope :numbered, ->(parent_column, order_column){
 | 
				
			||||||
    select(
 | 
					    select(
 | 
				
			||||||
      arel_table[Arel.star],
 | 
					      arel_table[Arel.star],
 | 
				
			||||||
      Arel::Nodes::NamedFunction.new(
 | 
					      Arel::Nodes::NamedFunction.new(
 | 
				
			||||||
        'LPAD',
 | 
					        'LPAD',
 | 
				
			||||||
        [
 | 
					        [
 | 
				
			||||||
          Arel::Nodes::NamedFunction.new(
 | 
					          Arel::Nodes::NamedFunction.new('ROW_NUMBER', [])
 | 
				
			||||||
            'ROW_NUMBER', []
 | 
					            .over(Arel::Nodes::Window.new.partition(parent_column).order(order_column)),
 | 
				
			||||||
          ).over(
 | 
					 | 
				
			||||||
            Arel::Nodes::Window.new.partition(parent_column).order(order_column)
 | 
					 | 
				
			||||||
          ),
 | 
					 | 
				
			||||||
          Arel::SelectManager.new.project(
 | 
					          Arel::SelectManager.new.project(
 | 
				
			||||||
            Arel::Nodes::NamedFunction.new(
 | 
					            Arel::Nodes::NamedFunction.new('LENGTH', [Arel.star.count])])
 | 
				
			||||||
              'LENGTH', [Arel::Nodes::NamedFunction.new('COUNT', [Arel.star])]
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
          Arel::Nodes.build_quoted('0')
 | 
					          Arel::Nodes.build_quoted('0')
 | 
				
			||||||
        ],
 | 
					        ],
 | 
				
			||||||
@ -62,4 +57,24 @@ class Quantity < ApplicationRecord
 | 
				
			|||||||
  def default?
 | 
					  def default?
 | 
				
			||||||
    parent_id.nil?
 | 
					    parent_id.nil?
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # Return: record, its ancestors and succesive record in order of appearance,
 | 
				
			||||||
 | 
					  # including :depth attribute. Used for table view reload.
 | 
				
			||||||
 | 
					  def successive
 | 
				
			||||||
 | 
					    quantities = Quantity.arel_table
 | 
				
			||||||
 | 
					    ancestors = Arel::Table.new('ancestors')
 | 
				
			||||||
 | 
					    Quantity.with(
 | 
				
			||||||
 | 
					      ancestors: user.quantities.ordered.select(
 | 
				
			||||||
 | 
					        Arel::Nodes::NamedFunction.new('LAG', [quantities[:id]]).over.as('lag_id')
 | 
				
			||||||
 | 
					      )
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    .with_recursive(quantities: [
 | 
				
			||||||
 | 
					      Arel::SelectManager.new.project(ancestors[Arel.star]).from(ancestors)
 | 
				
			||||||
 | 
					        .where(ancestors[:id].eq(id).or(ancestors[:lag_id].eq(id))),
 | 
				
			||||||
 | 
					      Arel::SelectManager.new.project(ancestors[Arel.star]).from(ancestors)
 | 
				
			||||||
 | 
					        .join(quantities).on(quantities[:parent_id].eq(ancestors[:id]))
 | 
				
			||||||
 | 
					        .where(quantities[:lag_id].not_eq(id))
 | 
				
			||||||
 | 
					    ]).order(quantities[:path])
 | 
				
			||||||
 | 
					    # return: .first == self ? nul, ancestors : ancestors.pop, ancestors
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
				
			|||||||
@ -10,7 +10,6 @@
 | 
				
			|||||||
    </td>
 | 
					    </td>
 | 
				
			||||||
    <td class="number">
 | 
					    <td class="number">
 | 
				
			||||||
      <% unless @unit.base.nil? %>
 | 
					      <% unless @unit.base.nil? %>
 | 
				
			||||||
        <%= form.hidden_field :base_id %>
 | 
					 | 
				
			||||||
        <%= form.number_field :multiplier, required: true, size: 10, min: :step %>
 | 
					        <%= form.number_field :multiplier, required: true, size: 10, min: :step %>
 | 
				
			||||||
      <% end %>
 | 
					      <% end %>
 | 
				
			||||||
    </td>
 | 
					    </td>
 | 
				
			||||||
 | 
				
			|||||||
@ -7,7 +7,8 @@
 | 
				
			|||||||
<%= turbo_stream.disable ids[:link] -%>
 | 
					<%= turbo_stream.disable ids[:link] -%>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<%= turbo_stream.append :unit_form do %>
 | 
					<%= turbo_stream.append :unit_form do %>
 | 
				
			||||||
  <%- tabular_form_with model: @unit, html: {id: ids[:form_tag]} do %>
 | 
					  <%- tabular_form_with model: @unit, html: {id: ids[:form_tag]} do |form| %>
 | 
				
			||||||
 | 
					    <%= form.hidden_field :base_id unless @unit.base.nil? %>
 | 
				
			||||||
  <% end %>
 | 
					  <% end %>
 | 
				
			||||||
<% end %>
 | 
					<% end %>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user