diff --git a/activeadmin_reorderable.gemspec b/activeadmin_reorderable.gemspec index 816f2b9..490c64a 100644 --- a/activeadmin_reorderable.gemspec +++ b/activeadmin_reorderable.gemspec @@ -24,7 +24,6 @@ Gem::Specification.new do |s| s.add_development_dependency "rails", "~> 6.1", ">= 6.1.4.4" s.add_development_dependency "rspec-rails" s.add_development_dependency "selenium-webdriver", '~> 4.10' - s.add_development_dependency "site_prism" s.add_development_dependency "sqlite3", "~> 1.4" s.add_development_dependency "sassc-rails" end diff --git a/app/assets/javascripts/activeadmin_reorderable.js b/app/assets/javascripts/activeadmin_reorderable.js index 8b51b34..56cd048 100644 --- a/app/assets/javascripts/activeadmin_reorderable.js +++ b/app/assets/javascripts/activeadmin_reorderable.js @@ -59,7 +59,10 @@ const updateEvenOddClasses = (row, index) => { } const updatePositionText = (row, index) => { - row.querySelector(".position").textContent = index + const position = row.querySelector(".position") + if (position) { + position.textContent = index + } } const updateBackend = (url, rowIndex) => { @@ -79,7 +82,7 @@ const updateBackend = (url, rowIndex) => { } document.addEventListener("DOMContentLoaded", () => { - document.querySelectorAll(".aa-reorderable").forEach((table) => { + document.querySelectorAll("table.aa-reorderable").forEach((table) => { setupReorderable({ table, onUpdate: (row) => { diff --git a/spec/dummy/app/admin/item_queue.rb b/spec/dummy/app/admin/item_queue.rb index 282123c..27b9928 100644 --- a/spec/dummy/app/admin/item_queue.rb +++ b/spec/dummy/app/admin/item_queue.rb @@ -1,4 +1,16 @@ ActiveAdmin.register ItemQueue do + config.sort_order = 'position_asc' + + permit_params :id, :position + + reorderable + + index as: :reorderable_table do + column :id + column :title + column :position, class: "position" + end + show do |item_queue| attributes_table do row :id diff --git a/spec/dummy/app/models/item_queue.rb b/spec/dummy/app/models/item_queue.rb index 06e4f40..9ffdca9 100644 --- a/spec/dummy/app/models/item_queue.rb +++ b/spec/dummy/app/models/item_queue.rb @@ -1,8 +1,10 @@ class ItemQueue < ApplicationRecord has_many :items, -> { order(position: :asc) } + acts_as_list + def self.ransackable_attributes(auth_object = nil) - ["created_at", "id", "updated_at"] + ["created_at", "id", "updated_at", "position", "title"] end def self.ransackable_associations(auth_object = nil) diff --git a/spec/dummy/db/migrate/20240715153551_add_position_to_item_queue.rb b/spec/dummy/db/migrate/20240715153551_add_position_to_item_queue.rb new file mode 100644 index 0000000..c77a020 --- /dev/null +++ b/spec/dummy/db/migrate/20240715153551_add_position_to_item_queue.rb @@ -0,0 +1,5 @@ +class AddPositionToItemQueue < ActiveRecord::Migration[6.1] + def change + add_column :item_queues, :position, :integer + end +end diff --git a/spec/dummy/db/migrate/20240715154734_add_title_to_item_queue.rb b/spec/dummy/db/migrate/20240715154734_add_title_to_item_queue.rb new file mode 100644 index 0000000..462882b --- /dev/null +++ b/spec/dummy/db/migrate/20240715154734_add_title_to_item_queue.rb @@ -0,0 +1,5 @@ +class AddTitleToItemQueue < ActiveRecord::Migration[6.1] + def change + add_column :item_queues, :title, :string + end +end diff --git a/spec/dummy/db/schema.rb b/spec/dummy/db/schema.rb index 9cf1a9e..59e8576 100644 --- a/spec/dummy/db/schema.rb +++ b/spec/dummy/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2024_07_11_185338) do +ActiveRecord::Schema.define(version: 2024_07_15_154734) do create_table "active_admin_comments", force: :cascade do |t| t.string "namespace" @@ -29,6 +29,8 @@ create_table "item_queues", force: :cascade do |t| t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false + t.integer "position" + t.string "title" end create_table "items", force: :cascade do |t| diff --git a/spec/dummy/spec/factories/item_queues.rb b/spec/dummy/spec/factories/item_queues.rb index 2df3c00..cee22af 100644 --- a/spec/dummy/spec/factories/item_queues.rb +++ b/spec/dummy/spec/factories/item_queues.rb @@ -1,5 +1,5 @@ FactoryBot.define do factory :item_queue do - + title { "Foobar" } end end diff --git a/spec/features/reorderable_spec.rb b/spec/features/reorderable_spec.rb index 161a859..7e98755 100644 --- a/spec/features/reorderable_spec.rb +++ b/spec/features/reorderable_spec.rb @@ -1,9 +1,10 @@ require 'rails_helper' describe "Reorderable", type: :feature do - let!(:queue) { ItemQueue.create } + let!(:queue) { ItemQueue.create(title: "Queue A") } let!(:item1) { Item.create(name: "Item 1", description: "Description 1", item_queue: queue, position: 1) } let!(:item2) { Item.create(name: "Item 2", description: "Description 2", item_queue: queue, position: 2) } + let!(:queue2) { ItemQueue.create(title: "Queue B") } it "item index page shows items" do visit admin_items_path @@ -17,7 +18,7 @@ visit admin_item_queue_path(queue) # Sanity checks - expect(page).to have_css(".aa-reorderable") + expect(page).to have_css("table.aa-reorderable") row1 = find(".aa-reorderable tbody tr:nth-child(1)") expect(row1).to have_content(item1.name) @@ -42,5 +43,40 @@ expect(item1.reload.position).to eq(2) expect(item2.reload.position).to eq(1) + + expect(page).to_not have_js_errors + end + + it "item queue index allows reordering", js: true do + visit admin_item_queues_path + + expect(page).to have_css("table.aa-reorderable") + + row1 = find(".aa-reorderable tbody tr:nth-child(1)") + expect(row1).to have_content(queue.title) + + row2 = find(".aa-reorderable tbody tr:nth-child(2)") + expect(row2).to have_content(queue2.title) + + + # Test initial state + expect(queue.title).to appear_before(queue2.title) + expect(queue.reload.position).to eq(1) + expect(queue2.reload.position).to eq(2) + + row1.find(".reorder-handle").drag_by(0, 50) # Drag down 50, far enough to put it in the next row + + expect(queue2.title).to appear_before(queue.title) + + # Check that the position column updated immediately + expect(row1.find(".position")).to have_content("2") + expect(row2.find(".position")).to have_content("1") + + sleep 1 # Give some time for the DB to update + + expect(queue.reload.position).to eq(2) + expect(queue2.reload.position).to eq(1) + + expect(page).to_not have_js_errors end end diff --git a/spec/support/have_js_errors.rb b/spec/support/have_js_errors.rb new file mode 100644 index 0000000..11dc134 --- /dev/null +++ b/spec/support/have_js_errors.rb @@ -0,0 +1,11 @@ +RSpec::Matchers.define :have_js_errors do + failure_message_when_negated do + %(Found JS errors:\n #{@errors.join("\n ")}) + end + + match do + logs = page.driver.browser.logs.get(:browser) + @errors = logs.select { |log| log.level == "SEVERE" } + @errors.count > 0 + end +end