From e4a3f8465c5131fceaf88af99d2c62fe28a06bfc Mon Sep 17 00:00:00 2001 From: Ko Nagase Date: Sat, 25 Mar 2023 23:07:08 +0900 Subject: [PATCH 01/10] Add position:integer column to text_blocks table --- db/migrate/20230325132825_add_position_to_text_blocks.rb | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 db/migrate/20230325132825_add_position_to_text_blocks.rb diff --git a/db/migrate/20230325132825_add_position_to_text_blocks.rb b/db/migrate/20230325132825_add_position_to_text_blocks.rb new file mode 100644 index 0000000..003588d --- /dev/null +++ b/db/migrate/20230325132825_add_position_to_text_blocks.rb @@ -0,0 +1,5 @@ +class AddPositionToTextBlocks < ActiveRecord::Migration[5.2] + def change + add_column :text_blocks, :position, :integer + end +end From a3862d46d04a40a2ae2b0c4a28365989fc026c7b Mon Sep 17 00:00:00 2001 From: Ko Nagase Date: Sun, 26 Mar 2023 21:10:10 +0900 Subject: [PATCH 02/10] Supporting sortable text_blocks --- app/controllers/text_blocks_controller.rb | 19 +++++++++++++++---- app/models/text_block.rb | 3 ++- .../projects/settings/_text_blocks.html.erb | 2 +- app/views/text_blocks/_list.html.erb | 8 ++++++++ app/views/text_blocks/_text_block.html.erb | 5 ++++- ...30325132825_add_position_to_text_blocks.rb | 2 +- 6 files changed, 31 insertions(+), 8 deletions(-) diff --git a/app/controllers/text_blocks_controller.rb b/app/controllers/text_blocks_controller.rb index 720ff69..2d54f96 100644 --- a/app/controllers/text_blocks_controller.rb +++ b/app/controllers/text_blocks_controller.rb @@ -40,9 +40,20 @@ def update r = RedmineTextBlocks::SaveTextBlock.(text_block_params, text_block: @text_block) if r.text_block_saved? - redirect_to index_path + respond_to do |format| + format.html { + flash[:notice] = l(:notice_successful_update) + redirect_to index_path + } + format.js { head 200 } + end else - render 'edit' + respond_to do |format| + format.html { + render 'edit' + } + format.js { head 422 } + end end end @@ -69,7 +80,7 @@ def index_path end def text_block_params - params[:text_block].permit :name, :text, :issue_status_ids => [] + params[:text_block].permit :name, :text, :issue_status_ids, :position end def find_text_block @@ -83,7 +94,7 @@ def find_project_by_project_id end def text_block_scope - TextBlock.order(name: :asc).where(project_id: @project&.id) + TextBlock.where(project_id: @project&.id).sorted end def get_issue_statuses diff --git a/app/models/text_block.rb b/app/models/text_block.rb index 02edf38..45ccedf 100644 --- a/app/models/text_block.rb +++ b/app/models/text_block.rb @@ -1,10 +1,11 @@ class TextBlock < ActiveRecord::Base belongs_to :project has_and_belongs_to_many :issue_statuses + acts_as_positioned :scope => [:project_id] validates :name, presence: true validate :name_uniqueness - + scope :sorted, ->{ order :position } private diff --git a/app/views/projects/settings/_text_blocks.html.erb b/app/views/projects/settings/_text_blocks.html.erb index 7906cfa..05ca901 100644 --- a/app/views/projects/settings/_text_blocks.html.erb +++ b/app/views/projects/settings/_text_blocks.html.erb @@ -2,5 +2,5 @@ <%= link_to l(:label_text_block_new), new_project_text_block_path(@project), class: 'icon icon-add' %>

-<%= render partial: 'text_blocks/list', locals: { text_blocks: TextBlock.where(project_id: @project.id) } %> +<%= render partial: 'text_blocks/list', locals: { text_blocks: TextBlock.where(project_id: @project.id).sorted } %> diff --git a/app/views/text_blocks/_list.html.erb b/app/views/text_blocks/_list.html.erb index ba21976..aac4a57 100644 --- a/app/views/text_blocks/_list.html.erb +++ b/app/views/text_blocks/_list.html.erb @@ -32,5 +32,13 @@ $("table.list.textblocks tbody td.text div").trigger('update.dot'); } }); + $(function() { + $("table.textblocks tbody").positionedItems({ + scroll: false, + sort: function (event, ui) { + ui.helper.css({'top': ui.position.top + $(window).scrollTop() + 'px'}); + }, + }); + }); <% end %> <% end %> diff --git a/app/views/text_blocks/_text_block.html.erb b/app/views/text_blocks/_text_block.html.erb index 758f70b..4d65240 100644 --- a/app/views/text_blocks/_text_block.html.erb +++ b/app/views/text_blocks/_text_block.html.erb @@ -6,5 +6,8 @@ <%= textilizable s %> <% end %> - <%= delete_link(text_block.project ? project_text_block_path(text_block.project, text_block) : text_block_path(text_block)) %> + + <%= reorder_handle(text_block, url: text_block.project ? project_text_block_path(text_block.project, text_block) : text_block_path(text_block)) %> + <%= delete_link(text_block.project ? project_text_block_path(text_block.project, text_block) : text_block_path(text_block)) %> + diff --git a/db/migrate/20230325132825_add_position_to_text_blocks.rb b/db/migrate/20230325132825_add_position_to_text_blocks.rb index 003588d..9fd84c0 100644 --- a/db/migrate/20230325132825_add_position_to_text_blocks.rb +++ b/db/migrate/20230325132825_add_position_to_text_blocks.rb @@ -1,5 +1,5 @@ class AddPositionToTextBlocks < ActiveRecord::Migration[5.2] def change - add_column :text_blocks, :position, :integer + add_column :text_blocks, :position, :integer, :default => 1 end end From 30f4c9e4c6e0a5205a7ce0a8ea47230096f65a5a Mon Sep 17 00:00:00 2001 From: Ko Nagase Date: Sun, 26 Mar 2023 23:27:52 +0900 Subject: [PATCH 03/10] Sort issue_status filtered text_blocks --- app/controllers/text_blocks_controller.rb | 2 +- app/helpers/text_blocks_helper.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/controllers/text_blocks_controller.rb b/app/controllers/text_blocks_controller.rb index 2d54f96..0b6d44b 100644 --- a/app/controllers/text_blocks_controller.rb +++ b/app/controllers/text_blocks_controller.rb @@ -102,6 +102,6 @@ def get_issue_statuses end def get_blocks_by_status(status_id) - IssueStatus.find(status_id).text_blocks.blank? ? text_block_scope : IssueStatus.find(status_id).text_blocks.where(project_id: [nil, @project&.id]) + IssueStatus.find(status_id).text_blocks.blank? ? text_block_scope : IssueStatus.find(status_id).text_blocks.where(project_id: [nil, @project&.id]).sorted end end diff --git a/app/helpers/text_blocks_helper.rb b/app/helpers/text_blocks_helper.rb index dd21738..153fb6e 100644 --- a/app/helpers/text_blocks_helper.rb +++ b/app/helpers/text_blocks_helper.rb @@ -6,13 +6,13 @@ def text_block_options(issue=nil) end status_textblocks = IssueStatus.find(issue.status_id).text_blocks if issue if !status_textblocks.blank? - tags += status_textblocks.where(project_id: [nil, @project.id]).map{|tb| + tags += status_textblocks.where(project_id: [nil, @project.id]).sorted.map{|tb| content_tag :option, value: tb.text do tb.name end } else - tags += TextBlock.where(project_id: [nil, @project.id]).to_a.map{|tb| + tags += TextBlock.where(project_id: [nil, @project.id]).sorted.to_a.map{|tb| content_tag :option, value: tb.text do tb.name end From 391863e3128c2dd730b2de7c2426b43520f46c01 Mon Sep 17 00:00:00 2001 From: Ko Nagase Date: Mon, 27 Mar 2023 13:54:58 +0900 Subject: [PATCH 04/10] Adjust db/migrate and js scroll part --- app/views/text_blocks/_list.html.erb | 7 +------ db/migrate/20230325132825_add_position_to_text_blocks.rb | 3 +++ 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/app/views/text_blocks/_list.html.erb b/app/views/text_blocks/_list.html.erb index aac4a57..0a5b8bc 100644 --- a/app/views/text_blocks/_list.html.erb +++ b/app/views/text_blocks/_list.html.erb @@ -33,12 +33,7 @@ } }); $(function() { - $("table.textblocks tbody").positionedItems({ - scroll: false, - sort: function (event, ui) { - ui.helper.css({'top': ui.position.top + $(window).scrollTop() + 'px'}); - }, - }); + $("table.textblocks tbody").positionedItems(); }); <% end %> <% end %> diff --git a/db/migrate/20230325132825_add_position_to_text_blocks.rb b/db/migrate/20230325132825_add_position_to_text_blocks.rb index 9fd84c0..684077c 100644 --- a/db/migrate/20230325132825_add_position_to_text_blocks.rb +++ b/db/migrate/20230325132825_add_position_to_text_blocks.rb @@ -1,5 +1,8 @@ class AddPositionToTextBlocks < ActiveRecord::Migration[5.2] def change add_column :text_blocks, :position, :integer, :default => 1 + # # After executing "rake redmine:plugins:migrate", execute the following on "rails console", if keeping the existing positions is important: + # res = TextBlock.connection.select_all("SELECT id, name, project_id, row_number() over(PARTITION by project_id) AS position FROM #{TextBlock.table_name}") + # res.rows.each{|row| TextBlock.connection.execute("UPDATE #{TextBlock.table_name} SET position=#{row[3]} WHERE id=#{row[0]}")} end end From 2507624b2702cde36abee26f2ddfb34d3f58d95c Mon Sep 17 00:00:00 2001 From: Ko Nagase Date: Mon, 27 Mar 2023 18:23:05 +0900 Subject: [PATCH 05/10] Set position=max+1 for new text block and add asserts to existing integration tests --- app/models/text_block.rb | 14 ++++++++++++++ test/integration/text_blocks_admin_test.rb | 12 ++++++++++++ test/integration/text_blocks_project_test.rb | 12 ++++++++++++ 3 files changed, 38 insertions(+) diff --git a/app/models/text_block.rb b/app/models/text_block.rb index 45ccedf..610b251 100644 --- a/app/models/text_block.rb +++ b/app/models/text_block.rb @@ -5,6 +5,9 @@ class TextBlock < ActiveRecord::Base validates :name, presence: true validate :name_uniqueness + validates_numericality_of :position, :only_integer => true + before_create :set_position + scope :sorted, ->{ order :position } private @@ -21,4 +24,15 @@ def name_uniqueness end end + def set_position + if project_id.present? + max = self.class.where(:project_id => project_id).maximum(:position) || 0 + self.position = max + 1 + else + binding.pry + max = self.class.where(:project_id => nil).maximum(:position) || 0 + self.position = max + 1 + end + end + end diff --git a/test/integration/text_blocks_admin_test.rb b/test/integration/text_blocks_admin_test.rb index 844e117..0e38138 100644 --- a/test/integration/text_blocks_admin_test.rb +++ b/test/integration/text_blocks_admin_test.rb @@ -31,6 +31,7 @@ def test_textblock_crud assert b = TextBlock.find_by_name('test') assert_equal 'lorem ipsum', b.text + assert_equal 1, b.position get "/text_blocks/#{b.id}/edit" assert_response :success @@ -40,6 +41,17 @@ def test_textblock_crud assert_equal 'lorem ipsum', b.text assert_equal 'new', b.name + assert_difference 'TextBlock.count' do + post '/text_blocks', params: { text_block: { name: 'test2', text: 'lorem ipsum2'}} + end + assert_redirected_to '/text_blocks' + + follow_redirect! + + assert b = TextBlock.find_by_name('test2') + assert_equal 'lorem ipsum2', b.text + assert_equal 2, b.position + assert_difference 'TextBlock.count', -1 do delete "/text_blocks/#{b.id}" end diff --git a/test/integration/text_blocks_project_test.rb b/test/integration/text_blocks_project_test.rb index 3adbded..3952731 100644 --- a/test/integration/text_blocks_project_test.rb +++ b/test/integration/text_blocks_project_test.rb @@ -45,6 +45,7 @@ def test_textblock_crud assert b = TextBlock.find_by_name('test') assert_equal 'lorem ipsum', b.text + assert_equal 1, b.position get "/projects/ecookbook/text_blocks/#{b.id}/edit" assert_response :success @@ -54,6 +55,17 @@ def test_textblock_crud assert_equal 'lorem ipsum', b.text assert_equal 'new', b.name + assert_difference 'TextBlock.count' do + post '/projects/ecookbook/text_blocks', params: { text_block: { name: 'test2', text: 'lorem ipsum2'}} + end + assert_redirected_to '/projects/ecookbook/settings/text_blocks' + + follow_redirect! + + assert b = TextBlock.find_by_name('test2') + assert_equal 'lorem ipsum2', b.text + assert_equal 2, b.position + assert_difference 'TextBlock.count', -1 do delete "/projects/ecookbook/text_blocks/#{b.id}" end From bbc1fcd7a139e13430aa8ad4c59422c4d75c3284 Mon Sep 17 00:00:00 2001 From: Ko Nagase Date: Tue, 28 Mar 2023 01:55:18 +0900 Subject: [PATCH 06/10] Fix permit issue and binding.pry Sort text blocks by global => project order --- app/controllers/text_blocks_controller.rb | 9 +++++++-- app/models/text_block.rb | 4 +--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/app/controllers/text_blocks_controller.rb b/app/controllers/text_blocks_controller.rb index 0b6d44b..c4f8581 100644 --- a/app/controllers/text_blocks_controller.rb +++ b/app/controllers/text_blocks_controller.rb @@ -80,7 +80,7 @@ def index_path end def text_block_params - params[:text_block].permit :name, :text, :issue_status_ids, :position + params[:text_block].permit :name, :text, :position, :issue_status_ids => [] end def find_text_block @@ -102,6 +102,11 @@ def get_issue_statuses end def get_blocks_by_status(status_id) - IssueStatus.find(status_id).text_blocks.blank? ? text_block_scope : IssueStatus.find(status_id).text_blocks.where(project_id: [nil, @project&.id]).sorted + if IssueStatus.find(status_id).text_blocks.blank + text_block_scope + else + IssueStatus.find(status_id).text_blocks. + where(project_id: [nil, @project&.id]).sorted + end end end diff --git a/app/models/text_block.rb b/app/models/text_block.rb index 610b251..4c88e3a 100644 --- a/app/models/text_block.rb +++ b/app/models/text_block.rb @@ -8,7 +8,7 @@ class TextBlock < ActiveRecord::Base validates_numericality_of :position, :only_integer => true before_create :set_position - scope :sorted, ->{ order :position } + scope :sorted, ->{ order('project_id IS NOT NULL, project_id ASC, position ASC') } private @@ -29,10 +29,8 @@ def set_position max = self.class.where(:project_id => project_id).maximum(:position) || 0 self.position = max + 1 else - binding.pry max = self.class.where(:project_id => nil).maximum(:position) || 0 self.position = max + 1 end end - end From 59baa08e2ef1e591c31cb172f06c897053c79919 Mon Sep 17 00:00:00 2001 From: Ko Nagase Date: Tue, 28 Mar 2023 02:01:02 +0900 Subject: [PATCH 07/10] Fix get_blocks_by_status condition --- app/controllers/text_blocks_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/text_blocks_controller.rb b/app/controllers/text_blocks_controller.rb index c4f8581..f7f90a8 100644 --- a/app/controllers/text_blocks_controller.rb +++ b/app/controllers/text_blocks_controller.rb @@ -102,7 +102,7 @@ def get_issue_statuses end def get_blocks_by_status(status_id) - if IssueStatus.find(status_id).text_blocks.blank + if IssueStatus.find(status_id).text_blocks.blank? text_block_scope else IssueStatus.find(status_id).text_blocks. From eb703a0cf15f7edf9c6a97d676b6d8876f51d757 Mon Sep 17 00:00:00 2001 From: Ko Nagase Date: Tue, 28 Mar 2023 02:15:26 +0900 Subject: [PATCH 08/10] Wrap order query by Arel.sql for Rails >= 6.0 --- app/models/text_block.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/text_block.rb b/app/models/text_block.rb index 4c88e3a..ab03ed8 100644 --- a/app/models/text_block.rb +++ b/app/models/text_block.rb @@ -8,7 +8,7 @@ class TextBlock < ActiveRecord::Base validates_numericality_of :position, :only_integer => true before_create :set_position - scope :sorted, ->{ order('project_id IS NOT NULL, project_id ASC, position ASC') } + scope :sorted, ->{ order(Arel.sql('project_id IS NOT NULL, project_id ASC, position ASC')) } private From 3110f86c18e8bae83d938fde02634f46dedff348 Mon Sep 17 00:00:00 2001 From: Ko Nagase Date: Tue, 28 Mar 2023 03:07:45 +0900 Subject: [PATCH 09/10] Add issue status check tests --- test/integration/text_blocks_admin_test.rb | 12 +++++-- test/integration/text_blocks_project_test.rb | 12 +++++-- test/unit/text_block_test.rb | 37 +++++++++++++++++++- 3 files changed, 54 insertions(+), 7 deletions(-) diff --git a/test/integration/text_blocks_admin_test.rb b/test/integration/text_blocks_admin_test.rb index 0e38138..53404d5 100644 --- a/test/integration/text_blocks_admin_test.rb +++ b/test/integration/text_blocks_admin_test.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' class TextBlocksAdminTest < Redmine::IntegrationTest - fixtures :users, :email_addresses, :user_preferences + fixtures :users, :email_addresses, :user_preferences, :issue_statuses def setup super @@ -23,7 +23,9 @@ def test_textblock_crud assert_response :success assert_difference 'TextBlock.count' do - post '/text_blocks', params: { text_block: { name: 'test', text: 'lorem ipsum'}} + post '/text_blocks', params: { + text_block: { name: 'test', text: 'lorem ipsum', issue_status_ids: [1, 2] } + } end assert_redirected_to '/text_blocks' @@ -31,6 +33,7 @@ def test_textblock_crud assert b = TextBlock.find_by_name('test') assert_equal 'lorem ipsum', b.text + assert_equal [1, 2], b.issue_statuses.map(&:id).sort assert_equal 1, b.position get "/text_blocks/#{b.id}/edit" @@ -42,7 +45,9 @@ def test_textblock_crud assert_equal 'new', b.name assert_difference 'TextBlock.count' do - post '/text_blocks', params: { text_block: { name: 'test2', text: 'lorem ipsum2'}} + post '/text_blocks', params: { + text_block: { name: 'test2', text: 'lorem ipsum2', issue_status_ids: [1, 2] } + } end assert_redirected_to '/text_blocks' @@ -50,6 +55,7 @@ def test_textblock_crud assert b = TextBlock.find_by_name('test2') assert_equal 'lorem ipsum2', b.text + assert_equal [1, 2], b.issue_statuses.map(&:id).sort assert_equal 2, b.position assert_difference 'TextBlock.count', -1 do diff --git a/test/integration/text_blocks_project_test.rb b/test/integration/text_blocks_project_test.rb index 3952731..9c77dae 100644 --- a/test/integration/text_blocks_project_test.rb +++ b/test/integration/text_blocks_project_test.rb @@ -2,7 +2,7 @@ class TextBlocksProjectTest < Redmine::IntegrationTest fixtures :users, :email_addresses, :user_preferences, - :roles, :projects, :members, :member_roles + :roles, :projects, :members, :member_roles, :issue_statuses def setup super @@ -37,7 +37,9 @@ def test_textblock_crud assert_response :success assert_difference 'TextBlock.count' do - post '/projects/ecookbook/text_blocks', params: { text_block: { name: 'test', text: 'lorem ipsum'}} + post '/projects/ecookbook/text_blocks', params: { + text_block: { name: 'test', text: 'lorem ipsum', issue_status_ids: [1, 2] } + } end assert_redirected_to '/projects/ecookbook/settings/text_blocks' @@ -45,6 +47,7 @@ def test_textblock_crud assert b = TextBlock.find_by_name('test') assert_equal 'lorem ipsum', b.text + assert_equal [1, 2], b.issue_statuses.map(&:id).sort assert_equal 1, b.position get "/projects/ecookbook/text_blocks/#{b.id}/edit" @@ -56,7 +59,9 @@ def test_textblock_crud assert_equal 'new', b.name assert_difference 'TextBlock.count' do - post '/projects/ecookbook/text_blocks', params: { text_block: { name: 'test2', text: 'lorem ipsum2'}} + post '/projects/ecookbook/text_blocks', params: { + text_block: { name: 'test2', text: 'lorem ipsum2', issue_status_ids: [1, 2] } + } end assert_redirected_to '/projects/ecookbook/settings/text_blocks' @@ -64,6 +69,7 @@ def test_textblock_crud assert b = TextBlock.find_by_name('test2') assert_equal 'lorem ipsum2', b.text + assert_equal [1, 2], b.issue_statuses.map(&:id).sort assert_equal 2, b.position assert_difference 'TextBlock.count', -1 do diff --git a/test/unit/text_block_test.rb b/test/unit/text_block_test.rb index 97e5695..9f711fb 100644 --- a/test/unit/text_block_test.rb +++ b/test/unit/text_block_test.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' class TextBlockTest < ActiveSupport::TestCase - fixtures :projects + fixtures :projects, :issue_statuses setup do @project = Project.find 'ecookbook' @@ -55,6 +55,41 @@ class TextBlockTest < ActiveSupport::TestCase end end + test 'should save params in global text block' do + assert_difference 'TextBlock.count' do + r = RedmineTextBlocks::SaveTextBlock.( + { + name: 'test', + text: 'lorem ipsum', + issue_status_ids: [1, 2] + } + ) + assert r.text_block_saved? + assert_equal 'test', r.text_block.name + assert_equal 'lorem ipsum', r.text_block.text + assert_equal [1, 2], r.text_block.issue_status_ids.sort + assert_equal 1, r.text_block.position + end + end + + test 'should save params in local text block' do + assert_difference 'TextBlock.count' do + r = RedmineTextBlocks::SaveTextBlock.( + { + name: 'test', + text: 'lorem ipsum', + issue_status_ids: [1, 2] + }, + project: @project + ) + assert r.text_block_saved? + assert_equal 'test', r.text_block.name + assert_equal 'lorem ipsum', r.text_block.text + assert_equal [1, 2], r.text_block.issue_status_ids.sort + assert_equal 1, r.text_block.position + end + end + test 'deletion of project should delete textblocks' do RedmineTextBlocks::SaveTextBlock.({name: 'test'}, project: @project) assert_difference 'TextBlock.count', -1 do From 65086e6c6b8d394aba3a7ff084f9b4fb20c10e90 Mon Sep 17 00:00:00 2001 From: Ko Nagase Date: Tue, 28 Mar 2023 10:36:27 +0900 Subject: [PATCH 10/10] Delete position default 1 and other customization from Redmine CustomFieldEnumeration model --- app/models/text_block.rb | 12 ------------ .../20230325132825_add_position_to_text_blocks.rb | 2 +- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/app/models/text_block.rb b/app/models/text_block.rb index ab03ed8..f6a5b7e 100644 --- a/app/models/text_block.rb +++ b/app/models/text_block.rb @@ -5,8 +5,6 @@ class TextBlock < ActiveRecord::Base validates :name, presence: true validate :name_uniqueness - validates_numericality_of :position, :only_integer => true - before_create :set_position scope :sorted, ->{ order(Arel.sql('project_id IS NOT NULL, project_id ASC, position ASC')) } @@ -23,14 +21,4 @@ def name_uniqueness errors.add :name, I18n.t('model.text_block.name_uniqueness') end end - - def set_position - if project_id.present? - max = self.class.where(:project_id => project_id).maximum(:position) || 0 - self.position = max + 1 - else - max = self.class.where(:project_id => nil).maximum(:position) || 0 - self.position = max + 1 - end - end end diff --git a/db/migrate/20230325132825_add_position_to_text_blocks.rb b/db/migrate/20230325132825_add_position_to_text_blocks.rb index 684077c..bcc91f3 100644 --- a/db/migrate/20230325132825_add_position_to_text_blocks.rb +++ b/db/migrate/20230325132825_add_position_to_text_blocks.rb @@ -1,6 +1,6 @@ class AddPositionToTextBlocks < ActiveRecord::Migration[5.2] def change - add_column :text_blocks, :position, :integer, :default => 1 + add_column :text_blocks, :position, :integer # # After executing "rake redmine:plugins:migrate", execute the following on "rails console", if keeping the existing positions is important: # res = TextBlock.connection.select_all("SELECT id, name, project_id, row_number() over(PARTITION by project_id) AS position FROM #{TextBlock.table_name}") # res.rows.each{|row| TextBlock.connection.execute("UPDATE #{TextBlock.table_name} SET position=#{row[3]} WHERE id=#{row[0]}")}