diff --git a/app/controllers/columns/left_positions_controller.rb b/app/controllers/columns/left_positions_controller.rb new file mode 100644 index 000000000..ce87befb9 --- /dev/null +++ b/app/controllers/columns/left_positions_controller.rb @@ -0,0 +1,8 @@ +class Columns::LeftPositionsController < ApplicationController + include ActionView::RecordIdentifier, ColumnScoped + + def create + @left_column = @column.left_column + @column.move_left + end +end diff --git a/app/controllers/columns/right_positions_controller.rb b/app/controllers/columns/right_positions_controller.rb new file mode 100644 index 000000000..14b7b849a --- /dev/null +++ b/app/controllers/columns/right_positions_controller.rb @@ -0,0 +1,8 @@ +class Columns::RightPositionsController < ApplicationController + include ActionView::RecordIdentifier, ColumnScoped + + def create + @right_column = @column.right_column + @column.move_right + end +end diff --git a/app/controllers/concerns/column_scoped.rb b/app/controllers/concerns/column_scoped.rb new file mode 100644 index 000000000..ea002b95a --- /dev/null +++ b/app/controllers/concerns/column_scoped.rb @@ -0,0 +1,12 @@ +module ColumnScoped + extend ActiveSupport::Concern + + included do + before_action :set_column + end + + private + def set_column + @column = Column.find(params[:column_id]) + end +end diff --git a/app/models/column/positioned.rb b/app/models/column/positioned.rb new file mode 100644 index 000000000..3ce92b290 --- /dev/null +++ b/app/models/column/positioned.rb @@ -0,0 +1,49 @@ +module Column::Positioned + extend ActiveSupport::Concern + + included do + scope :sorted, -> { order(position: :asc) } + + before_create :set_position + end + + def move_left + swap_position_with left_column + end + + def move_right + swap_position_with right_column + end + + def left_column + collection.columns.where("position < ?", position).sorted.last + end + + def right_column + collection.columns.where("position > ?", position).sorted.first + end + + def leftmost? + left_column.nil? + end + + def rightmost? + right_column.nil? + end + + private + def set_position + max_position = collection.columns.maximum(:position) + self.position = max_position + 1 + end + + def swap_position_with(other_column) + return if other_column.nil? + + transaction do + old_position = self.position + self.update_column(:position, other_column.position) + other_column.update_column(:position, old_position) + end + end +end diff --git a/app/models/concerns/column/positioned.rb b/app/models/concerns/column/positioned.rb deleted file mode 100644 index a3864dab0..000000000 --- a/app/models/concerns/column/positioned.rb +++ /dev/null @@ -1,35 +0,0 @@ -module Column::Positioned - extend ActiveSupport::Concern - - included do - scope :sorted, -> { order(position: :asc) } - - before_create :set_position - end - - def move_left - if column = collection.columns.where("position < ?", position).sorted.last - swap_position_with(column) - end - end - - def move_right - if column = collection.columns.where("position > ?", position).sorted.first - swap_position_with(column) - end - end - - private - def set_position - max_position = collection.columns.maximum(:position) - self.position = max_position + 1 - end - - def swap_position_with(other_column) - transaction do - other_column.position, self.position = self.position, other_column.position - other_column.save! - save! - end - end -end diff --git a/app/views/collections/show/menu/_column.html.erb b/app/views/collections/show/menu/_column.html.erb index 6870e34e7..3977f98a5 100644 --- a/app/views/collections/show/menu/_column.html.erb +++ b/app/views/collections/show/menu/_column.html.erb @@ -11,6 +11,24 @@ Edit column + + + + diff --git a/app/views/columns/left_positions/create.turbo_stream.erb b/app/views/columns/left_positions/create.turbo_stream.erb new file mode 100644 index 000000000..66eadf968 --- /dev/null +++ b/app/views/columns/left_positions/create.turbo_stream.erb @@ -0,0 +1,4 @@ +<% if @left_column %> + <%= turbo_stream.remove(dom_id(@column)) %> + <%= turbo_stream.before(@left_column, partial: "collections/show/column", locals: { column: @column }) %> +<% end %> diff --git a/app/views/columns/right_positions/create.turbo_stream.erb b/app/views/columns/right_positions/create.turbo_stream.erb new file mode 100644 index 000000000..ed04429fd --- /dev/null +++ b/app/views/columns/right_positions/create.turbo_stream.erb @@ -0,0 +1,4 @@ +<% if @right_column %> + <%= turbo_stream.remove(dom_id(@column)) %> + <%= turbo_stream.after(@right_column, partial: "collections/show/column", locals: { column: @column }) %> +<% end %> diff --git a/config/routes.rb b/config/routes.rb index 76a6204cc..bdf95a29a 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -35,6 +35,11 @@ Rails.application.routes.draw do end end + resources :columns, only: [] do + resource :left_position, module: :columns + resource :right_position, module: :columns + end + namespace :columns do resources :cards do scope module: "cards" do diff --git a/script/migrations/20251029-populate-column-positions.rb b/script/migrations/20251029-populate-column-positions.rb new file mode 100755 index 000000000..b47f5eccf --- /dev/null +++ b/script/migrations/20251029-populate-column-positions.rb @@ -0,0 +1,20 @@ +#!/usr/bin/env ruby + +require_relative "../../config/environment" + +ApplicationRecord.with_each_tenant do |tenant| + puts "Processing tenant: #{tenant}" + + Collection.find_each do |collection| + puts " Processing collection: #{collection.name} (ID: #{collection.id})" + + columns = collection.columns.order(:id) + + columns.each_with_index do |column, index| + column.update_column(:position, index) + puts " Set position #{index} for column '#{column.name}' (ID: #{column.id})" + end + end +end + +puts "Migration completed!"