Skip to content

Commit 07c904f

Browse files
authored
Merge pull request #34 from gtt-project/fix/sortable-text-blocks
Sortable text_blocks (templates)
2 parents 60ab5bc + 65086e6 commit 07c904f

File tree

10 files changed

+117
-15
lines changed

10 files changed

+117
-15
lines changed

app/controllers/text_blocks_controller.rb

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,20 @@ def update
4040
r = RedmineTextBlocks::SaveTextBlock.(text_block_params,
4141
text_block: @text_block)
4242
if r.text_block_saved?
43-
redirect_to index_path
43+
respond_to do |format|
44+
format.html {
45+
flash[:notice] = l(:notice_successful_update)
46+
redirect_to index_path
47+
}
48+
format.js { head 200 }
49+
end
4450
else
45-
render 'edit'
51+
respond_to do |format|
52+
format.html {
53+
render 'edit'
54+
}
55+
format.js { head 422 }
56+
end
4657
end
4758
end
4859

@@ -69,7 +80,7 @@ def index_path
6980
end
7081

7182
def text_block_params
72-
params[:text_block].permit :name, :text, :issue_status_ids => []
83+
params[:text_block].permit :name, :text, :position, :issue_status_ids => []
7384
end
7485

7586
def find_text_block
@@ -83,14 +94,19 @@ def find_project_by_project_id
8394
end
8495

8596
def text_block_scope
86-
TextBlock.order(name: :asc).where(project_id: @project&.id)
97+
TextBlock.where(project_id: @project&.id).sorted
8798
end
8899

89100
def get_issue_statuses
90101
@issue_statuses = IssueStatus.all.sorted
91102
end
92103

93104
def get_blocks_by_status(status_id)
94-
IssueStatus.find(status_id).text_blocks.blank? ? text_block_scope : IssueStatus.find(status_id).text_blocks.where(project_id: [nil, @project&.id])
105+
if IssueStatus.find(status_id).text_blocks.blank?
106+
text_block_scope
107+
else
108+
IssueStatus.find(status_id).text_blocks.
109+
where(project_id: [nil, @project&.id]).sorted
110+
end
95111
end
96112
end

app/helpers/text_blocks_helper.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ def text_block_options(issue=nil)
66
end
77
status_textblocks = IssueStatus.find(issue.status_id).text_blocks if issue
88
if !status_textblocks.blank?
9-
tags += status_textblocks.where(project_id: [nil, @project.id]).map{|tb|
9+
tags += status_textblocks.where(project_id: [nil, @project.id]).sorted.map{|tb|
1010
content_tag :option, value: tb.text do
1111
tb.name
1212
end
1313
}
1414
else
15-
tags += TextBlock.where(project_id: [nil, @project.id]).to_a.map{|tb|
15+
tags += TextBlock.where(project_id: [nil, @project.id]).sorted.to_a.map{|tb|
1616
content_tag :option, value: tb.text do
1717
tb.name
1818
end

app/models/text_block.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
class TextBlock < ActiveRecord::Base
22
belongs_to :project
33
has_and_belongs_to_many :issue_statuses
4+
acts_as_positioned :scope => [:project_id]
45

56
validates :name, presence: true
67
validate :name_uniqueness
78

9+
scope :sorted, ->{ order(Arel.sql('project_id IS NOT NULL, project_id ASC, position ASC')) }
810

911
private
1012

@@ -19,5 +21,4 @@ def name_uniqueness
1921
errors.add :name, I18n.t('model.text_block.name_uniqueness')
2022
end
2123
end
22-
2324
end

app/views/projects/settings/_text_blocks.html.erb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
<%= link_to l(:label_text_block_new), new_project_text_block_path(@project), class: 'icon icon-add' %>
33
</p>
44

5-
<%= render partial: 'text_blocks/list', locals: { text_blocks: TextBlock.where(project_id: @project.id) } %>
5+
<%= render partial: 'text_blocks/list', locals: { text_blocks: TextBlock.where(project_id: @project.id).sorted } %>
66

app/views/text_blocks/_list.html.erb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,8 @@
3232
$("table.list.textblocks tbody td.text div").trigger('update.dot');
3333
}
3434
});
35+
$(function() {
36+
$("table.textblocks tbody").positionedItems();
37+
});
3538
<% end %>
3639
<% end %>

app/views/text_blocks/_text_block.html.erb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,8 @@
66
<%= textilizable s %>
77
<% end %>
88
</div></td>
9-
<td><%= delete_link(text_block.project ? project_text_block_path(text_block.project, text_block) : text_block_path(text_block)) %>
9+
<td class="buttons">
10+
<%= reorder_handle(text_block, url: text_block.project ? project_text_block_path(text_block.project, text_block) : text_block_path(text_block)) %>
11+
<%= delete_link(text_block.project ? project_text_block_path(text_block.project, text_block) : text_block_path(text_block)) %>
12+
</td>
1013
</tr>
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
class AddPositionToTextBlocks < ActiveRecord::Migration[5.2]
2+
def change
3+
add_column :text_blocks, :position, :integer
4+
# # After executing "rake redmine:plugins:migrate", execute the following on "rails console", if keeping the existing positions is important:
5+
# res = TextBlock.connection.select_all("SELECT id, name, project_id, row_number() over(PARTITION by project_id) AS position FROM #{TextBlock.table_name}")
6+
# res.rows.each{|row| TextBlock.connection.execute("UPDATE #{TextBlock.table_name} SET position=#{row[3]} WHERE id=#{row[0]}")}
7+
end
8+
end

test/integration/text_blocks_admin_test.rb

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
require_relative '../test_helper'
22

33
class TextBlocksAdminTest < Redmine::IntegrationTest
4-
fixtures :users, :email_addresses, :user_preferences
4+
fixtures :users, :email_addresses, :user_preferences, :issue_statuses
55

66
def setup
77
super
@@ -23,14 +23,18 @@ def test_textblock_crud
2323
assert_response :success
2424

2525
assert_difference 'TextBlock.count' do
26-
post '/text_blocks', params: { text_block: { name: 'test', text: 'lorem ipsum'}}
26+
post '/text_blocks', params: {
27+
text_block: { name: 'test', text: 'lorem ipsum', issue_status_ids: [1, 2] }
28+
}
2729
end
2830
assert_redirected_to '/text_blocks'
2931

3032
follow_redirect!
3133

3234
assert b = TextBlock.find_by_name('test')
3335
assert_equal 'lorem ipsum', b.text
36+
assert_equal [1, 2], b.issue_statuses.map(&:id).sort
37+
assert_equal 1, b.position
3438

3539
get "/text_blocks/#{b.id}/edit"
3640
assert_response :success
@@ -40,6 +44,20 @@ def test_textblock_crud
4044
assert_equal 'lorem ipsum', b.text
4145
assert_equal 'new', b.name
4246

47+
assert_difference 'TextBlock.count' do
48+
post '/text_blocks', params: {
49+
text_block: { name: 'test2', text: 'lorem ipsum2', issue_status_ids: [1, 2] }
50+
}
51+
end
52+
assert_redirected_to '/text_blocks'
53+
54+
follow_redirect!
55+
56+
assert b = TextBlock.find_by_name('test2')
57+
assert_equal 'lorem ipsum2', b.text
58+
assert_equal [1, 2], b.issue_statuses.map(&:id).sort
59+
assert_equal 2, b.position
60+
4361
assert_difference 'TextBlock.count', -1 do
4462
delete "/text_blocks/#{b.id}"
4563
end

test/integration/text_blocks_project_test.rb

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
class TextBlocksProjectTest < Redmine::IntegrationTest
44
fixtures :users, :email_addresses, :user_preferences,
5-
:roles, :projects, :members, :member_roles
5+
:roles, :projects, :members, :member_roles, :issue_statuses
66

77
def setup
88
super
@@ -37,14 +37,18 @@ def test_textblock_crud
3737
assert_response :success
3838

3939
assert_difference 'TextBlock.count' do
40-
post '/projects/ecookbook/text_blocks', params: { text_block: { name: 'test', text: 'lorem ipsum'}}
40+
post '/projects/ecookbook/text_blocks', params: {
41+
text_block: { name: 'test', text: 'lorem ipsum', issue_status_ids: [1, 2] }
42+
}
4143
end
4244
assert_redirected_to '/projects/ecookbook/settings/text_blocks'
4345

4446
follow_redirect!
4547

4648
assert b = TextBlock.find_by_name('test')
4749
assert_equal 'lorem ipsum', b.text
50+
assert_equal [1, 2], b.issue_statuses.map(&:id).sort
51+
assert_equal 1, b.position
4852

4953
get "/projects/ecookbook/text_blocks/#{b.id}/edit"
5054
assert_response :success
@@ -54,6 +58,20 @@ def test_textblock_crud
5458
assert_equal 'lorem ipsum', b.text
5559
assert_equal 'new', b.name
5660

61+
assert_difference 'TextBlock.count' do
62+
post '/projects/ecookbook/text_blocks', params: {
63+
text_block: { name: 'test2', text: 'lorem ipsum2', issue_status_ids: [1, 2] }
64+
}
65+
end
66+
assert_redirected_to '/projects/ecookbook/settings/text_blocks'
67+
68+
follow_redirect!
69+
70+
assert b = TextBlock.find_by_name('test2')
71+
assert_equal 'lorem ipsum2', b.text
72+
assert_equal [1, 2], b.issue_statuses.map(&:id).sort
73+
assert_equal 2, b.position
74+
5775
assert_difference 'TextBlock.count', -1 do
5876
delete "/projects/ecookbook/text_blocks/#{b.id}"
5977
end

test/unit/text_block_test.rb

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
require_relative '../test_helper'
22

33
class TextBlockTest < ActiveSupport::TestCase
4-
fixtures :projects
4+
fixtures :projects, :issue_statuses
55

66
setup do
77
@project = Project.find 'ecookbook'
@@ -55,6 +55,41 @@ class TextBlockTest < ActiveSupport::TestCase
5555
end
5656
end
5757

58+
test 'should save params in global text block' do
59+
assert_difference 'TextBlock.count' do
60+
r = RedmineTextBlocks::SaveTextBlock.(
61+
{
62+
name: 'test',
63+
text: 'lorem ipsum',
64+
issue_status_ids: [1, 2]
65+
}
66+
)
67+
assert r.text_block_saved?
68+
assert_equal 'test', r.text_block.name
69+
assert_equal 'lorem ipsum', r.text_block.text
70+
assert_equal [1, 2], r.text_block.issue_status_ids.sort
71+
assert_equal 1, r.text_block.position
72+
end
73+
end
74+
75+
test 'should save params in local text block' do
76+
assert_difference 'TextBlock.count' do
77+
r = RedmineTextBlocks::SaveTextBlock.(
78+
{
79+
name: 'test',
80+
text: 'lorem ipsum',
81+
issue_status_ids: [1, 2]
82+
},
83+
project: @project
84+
)
85+
assert r.text_block_saved?
86+
assert_equal 'test', r.text_block.name
87+
assert_equal 'lorem ipsum', r.text_block.text
88+
assert_equal [1, 2], r.text_block.issue_status_ids.sort
89+
assert_equal 1, r.text_block.position
90+
end
91+
end
92+
5893
test 'deletion of project should delete textblocks' do
5994
RedmineTextBlocks::SaveTextBlock.({name: 'test'}, project: @project)
6095
assert_difference 'TextBlock.count', -1 do

0 commit comments

Comments
 (0)