Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for Redmine6/rails7 #50

Merged
merged 17 commits into from
Dec 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
8d81c70
update redmine versions in the github workflows
cat-in-136 Aug 3, 2024
fd0f143
refactor .github/workflows/redmine_plugin.yml
cat-in-136 Aug 3, 2024
53e8e3a
Ignore `unloadable` if method missing
cat-in-136 Aug 2, 2024
59f151e
Use ApplicationRecord instead of ActiveRecord::Base
cat-in-136 Aug 3, 2024
a978fbe
use :assigns instead of @-starting keys in :locals in render_to_string
cat-in-136 Aug 3, 2024
4b299a0
remove DateTime#to_s(:db) and use DateTime as-is
cat-in-136 Aug 3, 2024
9ecf6e3
add "LoadError: cannot load such file -- blankslate" Issue HACK worka…
cat-in-136 Aug 3, 2024
c1592b6
drop support redmine 4.0 and 4.1
cat-in-136 Aug 3, 2024
5ad0e66
update actions/checkout@v4, actions/cache@v4 and DamianReeves/write-f…
cat-in-136 Aug 3, 2024
1455710
Fix check condition of script[src]/link[href] test to relaxed path re…
cat-in-136 Aug 3, 2024
a358fa4
skip Heart#validate_user validation when importing from vote_on_issue…
nishidayuya Nov 1, 2024
075903d
skip invalid record data migration on VoteOnIssue
nishidayuya Nov 1, 2024
81bc7c1
Merge pull request #53 from nishidayuya/refine_migrate_from_vote_on_i…
cat-in-136 Nov 26, 2024
ee0c93c
upgrade redmine/redmica and ruby versions in redmine_plugin.yml
cat-in-136 Nov 26, 2024
a14e0a6
introduce tabler-icons for redmine 6.0
cat-in-136 Nov 28, 2024
ca8bbb3
Add tests for heart_link_with_counter method with IconsHelper support…
cat-in-136 Dec 1, 2024
6cbd468
Update README and init.rb: add license information and update version…
cat-in-136 Dec 1, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 31 additions & 35 deletions .github/workflows/redmine_plugin.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,22 @@ jobs:
fail-fast: false
matrix:
mat_env:
- '3.3 redmica/[email protected]'
- '3.3 redmica/[email protected]'
- '3.2 redmica/[email protected]'
- '3.2 redmica/[email protected]'
- '3.1 redmica/[email protected]'
- '3.0 redmica/[email protected]'
- '2.7 redmica/[email protected]'
- '3.2 redmine/[email protected]'
- '3.1 redmine/[email protected]'
- '3.0 redmine/[email protected]'
- '3.3 redmine/[email protected]'
- '3.2 redmine/[email protected]'
- '3.1 redmine/[email protected]'
- '3.0 redmine/[email protected]'
- '2.7 redmine/[email protected]'
- '2.6 redmine/[email protected]'
- '2.6 redmine/[email protected]'
- '2.6 redmine/[email protected]'
- '2.5 redmine/[email protected]'
experimental: [false]
include:
- mat_env: '3.2 redmica/redmica@master'
- mat_env: '3.3 redmica/redmica@master'
experimental: true
steps:
- run: |
Expand All @@ -43,11 +44,11 @@ jobs:
ruby-version: ${{ env.RUBY_VERSION }}

- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
path: ./${{ env.PLUGIN_NAME }}
- name: Set up Redmine
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
repository: ${{ env.REDMINE_REPOSITORY }}
ref: ${{ env.REDMINE_REF }}
Expand All @@ -56,32 +57,31 @@ jobs:
- name: Copy the plugin files to plugin directory
run: cp -pr ./${{ env.PLUGIN_NAME }} ./redmine/plugins/${{ env.PLUGIN_NAME }}
- name: Create redmine/config/database.yml
uses: DamianReeves/write-file-action@v1.2
uses: DamianReeves/write-file-action@v1.3
with:
path: ./redmine/config/database.yml
contents: |
test:
adapter: sqlite3
database: db/redmine_test.db

- uses: actions/cache@v3
- uses: actions/cache@v4
with:
path: ./redmine/vendor/bundle
key: ${{ runner.os }}-gems-${{ hashFiles('./redmine/**/Gemfile.lock') }}
restore-keys: |
${{ runner.os }}-gems-

- name: uninitialized constant Nokogiri::HTML4 Issue HACK ref. https://qiita.com/Mattani/items/c4bcc95a72b69d1c0489
uses: DamianReeves/write-file-action@v1.2
- name: "'LoadError: cannot load such file -- blankslate' Issue HACK ref. https://www.redmine.org/issues/40802#note-11"
uses: DamianReeves/write-file-action@v1.3
with:
path: ./redmine/Gemfile.local
contents: |
gem 'loofah', '~> 2.20.0'
if: contains(fromJSON('["2.6 redmine/[email protected]", "2.6 redmine/[email protected]", "2.5 redmine/[email protected]"]'), matrix.mat_env)
gem 'builder', '~> 3.2.4'
if: contains(fromJSON('["3.2 redmica/[email protected]", "3.2 redmica/[email protected]", "3.1 redmica/[email protected]", "3.0 redmica/[email protected]", "2.7 redmica/[email protected]", "2.6 redmine/[email protected]", "2.6 redmine/[email protected]", "2.5 redmine/[email protected]", "2.6 redmine/[email protected]", "2.7 redmine/[email protected]"]'), matrix.mat_env)

- name: Before script
run: |
cd ./redmine
bundle config --local path ${BUNDLE_PATH:-vendor/bundle}
bundle install

Expand All @@ -94,31 +94,27 @@ jobs:

# Execute plugin's migration
bundle exec rake redmine:plugins NAME=${{ env.PLUGIN_NAME }}
working-directory: ./redmine
env:
REDMINE_LANG: en
RAILS_ENV: test

# HACK sometimes fails login error, so retry 10 times
# HACK use shell script file to avoid interruption by error
- name: Prepare test script
uses: DamianReeves/[email protected]
with:
path: ./run_test.sh
contents: |
#!/bin/sh
cd ./redmine
for i in `seq 0 9`; do
# Execute plugin's test
bundle exec rake redmine:plugins:test NAME=${{ env.PLUGIN_NAME }}
retval=$?
if [ "$retval" -eq 0 ]; then
break
fi
echo "${i}-th test failed; Retry test..."
done
exit $retval
- name: Execute test
run: sh ./run_test.sh
run: |
#!/bin/sh
for i in `seq 0 9`; do
# Execute plugin's test
bundle exec rake redmine:plugins:test NAME=${{ env.PLUGIN_NAME }}
retval=$?
if [ "$retval" -eq 0 ]; then
break
fi
echo "${i}-th test failed; Retry test..."
done
exit $retval
shell: bash {0}
working-directory: ./redmine
env:
REDMINE_LANG: en
RAILS_ENV: test
7 changes: 7 additions & 0 deletions README.rdoc
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,10 @@ Follow below steps to migrate from other plugins :
* Restart your redmine

Ditto {issue_votes}[https://github.com/KohaSuomi/issue_votes]. Run <code>bundle exec rake -T redmine_hearts:migrate_from</code> to check the task name.

== License

* Codes: MIT License.
* Legacy Icons: famfamfam-silk: {CC-By-2.5}[https://creativecommons.org/licenses/by/2.5/] by Mark James http://www.famfamfam.com/lab/icons/silk/
* Vector Icons: {Tabler Icons}[https://tabler.io/]: MIT License

2 changes: 1 addition & 1 deletion app/controllers/hearts_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
# along with this program; if not, write to the Free Software

class HeartsController < ApplicationController
unloadable
unloadable if respond_to?(:unloadable)

accept_api_auth :index, :heart, :unheart, :hearted_users

Expand Down
17 changes: 16 additions & 1 deletion app/helpers/hearts_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,11 @@ def heart_link_with_counter_manual(objects, heart_bool, hearted_users_count, use
objects = Array.wrap(objects)

css = heart_bool ? 'icon icon-heart' : 'icon icon-heart-off'
text = content_tag :span, l(:hearts_link_label), :class => 'heart-link-label'
if defined? hearts_icon_with_label # redmine >= 6.0
text = hearts_icon_with_label('heart', l(:hearts_link_label), css_class: 'heart-link-label')
else
text = content_tag :span, l(:hearts_link_label), :class => 'heart-link-label'
end
object_type = objects.first.class.to_s.underscore
object_id = (objects.size == 1) ? objects.first.id : objects.map(&:id).sort

Expand Down Expand Up @@ -127,4 +131,15 @@ def render_api_heartable_include(heartable, api)
end
end
end

if defined? IconsHelper # redmine >= 6.0
include IconsHelper
def hearts_icon_with_label(icon_name, label_text, icon_only: false, size: 18, css_class: nil)
label_classes = ["icon-label"]
label_classes << "hidden" if icon_only
plugin = 'redmine_hearts'
sprite_icon(icon_name, size: size, css_class: css_class, plugin: plugin) + content_tag(:span, label_text, class: label_classes.join(' '))
end
end

end
12 changes: 7 additions & 5 deletions app/models/heart.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,24 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

class Heart < ActiveRecord::Base
unloadable
class Heart < (defined?(ApplicationRecord) == 'constant' ? ApplicationRecord : ActiveRecord::Base)
unloadable if respond_to?(:unloadable)

belongs_to :heartable, :polymorphic => true
belongs_to :user

attribute :skip_validate_user, :boolean

validates_presence_of :user
validates_uniqueness_of :user_id, :scope => [:heartable_type, :heartable_id]
validate :validate_user
validate :validate_user, :unless => :skip_validate_user

def self.of_projects(*args)
projects = args.size > 0 ? args.shift : Project.none
user = args.size > 0 ? args.shift : nil
raise ArgumentError if args.size > 0

ActiveRecord::Base.subclasses.select { |klass|
(defined?(ApplicationRecord) == 'constant' ? ApplicationRecord : ActiveRecord::Base).subclasses.select { |klass|
klass.included_modules.include?(Redmine::Acts::Heartable::InstanceMethods)
}.map { |klass|
if user && klass.respond_to?(:visible)
Expand All @@ -57,7 +59,7 @@ def self.of_projects(*args)
def self.notifications_to(user)
raise ArgumentError unless user

ActiveRecord::Base.subclasses.select { |klass|
(defined?(ApplicationRecord) == 'constant' ? ApplicationRecord : ActiveRecord::Base).subclasses.select { |klass|
klass.included_modules.include?(Redmine::Acts::Heartable::InstanceMethods)
}.select { |klass|
klass.column_names.include?("author_id") || klass.column_names.include?("user_id")
Expand Down
8 changes: 8 additions & 0 deletions assets/images/icons.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 11 additions & 2 deletions assets/stylesheets/application.css
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
.icon-heart { background-image: url(../images/heart.png); }
.icon-heart-off { background-image: url(../images/heart_off.png); }

.heart-link-with-count { display: inline-block; }
.heart-count-number { padding-left: 1ex; }
.heart-count-number { padding-left: 0.75ex; }

/* redmine >= 6.0 */
:is(.icon-heart, .icon-heart-off):has(svg.icon-svg) { background-image: none; }
.icon-heart .icon-svg { fill: #fb8098; stroke: none; }
.heart-link-with-count:has(svg.icon-svg) {
display: inline-flex;
align-items: center;
vertical-align: middle;
}


@media screen and (max-width: 899px) {
.heart-link-with-count > *:nth-child(1) {
Expand Down
2 changes: 2 additions & 0 deletions config/icon_source.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- name: heart
svg: heart
4 changes: 3 additions & 1 deletion init.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,12 @@
require File.expand_path('../lib/redmine_hearts/view_hook.rb', __FILE__)

Redmine::Plugin.register :redmine_hearts do
requires_redmine :version_or_higher => '4.2.0'

name 'Redmine Hearts plugin'
author '@cat_in_136'
description 'provide intra-Redmine Like/Fav reactions'
version '3.0.1'
version '4.0.0'
url 'https://github.com/cat-in-136/redmine_hearts'
author_url 'https://github.com/cat-in-136/'

Expand Down
2 changes: 1 addition & 1 deletion lib/redmine/acts/heartable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -98,5 +98,5 @@ module ClassMethods; end
end
end

ActiveRecord::Base.send(:include, Redmine::Acts::Heartable)
(defined?(ApplicationRecord) == 'constant' ? ApplicationRecord : ActiveRecord::Base).send(:include, Redmine::Acts::Heartable)

2 changes: 1 addition & 1 deletion lib/redmine_hearts/heartable_patch.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def self.included(base) # :nodoc:
end

base.class_eval do
unloadable
unloadable if respond_to?(:unloadable)
acts_as_heartable options
end
end
Expand Down
9 changes: 6 additions & 3 deletions lib/redmine_hearts/view_hook.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ def view_layouts_base_html_head(context={})
if subject
controller.send(:render_to_string, {
:partial => "hooks/redmine_hearts/view_layouts_base_html_head",
:locals => context.merge(:@heartable => subject)
:locals => context,
:assigns => { :heartable => subject }
})
end
end
Expand All @@ -36,7 +37,8 @@ def view_layouts_base_content(context={})
if subject
controller.send(:render_to_string, {
:partial => "hooks/redmine_hearts/view_layouts_base_content",
:locals => context.merge(:@heartable => subject)
:locals => context,
:assigns => { :heartable => subject }
})
end
end
Expand All @@ -47,7 +49,8 @@ def view_account_left_bottom(context={})
controller = context[:controller]
controller.send(:render_to_string, {
:partial => "hooks/redmine_hearts/view_account_left_bottom",
:locals => context.merge(:@heart_count => heart_count)
:locals => context,
:assigns => { :heart_count => heart_count }
})
end
end
Expand Down
3 changes: 2 additions & 1 deletion lib/tasks/redmine_hearts.rake
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ namespace :redmine_hearts do

num_of_heart_before_processing = Heart.count

VoteOnIssue.where('vote_val > 0').each do |vote|
VoteOnIssue.where('vote_val > 0').where.not(issue: nil, user: nil).each do |vote|
issue = vote.issue
user = vote.user
datetime = vote.created_at || Time.now
Expand All @@ -100,6 +100,7 @@ namespace :redmine_hearts do
:user => user,
:created_at => datetime,
:updated_at => datetime,
:skip_validate_user => true,
)
end
end
Expand Down
20 changes: 10 additions & 10 deletions test/fixtures/hearts.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,29 +21,29 @@ hearts_005:
heartable_type: Wiki
heartable_id: 1
user_id: 3
created_at: <%= 30.days.ago.to_date.to_s(:db) %>
updated_at: <%= 30.days.ago.to_date.to_s(:db) %>
created_at: <%= 30.days.ago %>
updated_at: <%= 30.days.ago %>
hearts_006:
heartable_type: WikiPage
heartable_id: 1
user_id: 3
created_at: <%= 29.days.ago.to_date.to_s(:db) %>
updated_at: <%= 29.days.ago.to_date.to_s(:db) %>
created_at: <%= 29.days.ago %>
updated_at: <%= 29.days.ago %>
hearts_007:
heartable_type: News
heartable_id: 1
user_id: 3
created_at: <%= 2.days.ago.to_date.to_s(:db) %>
updated_at: <%= 2.days.ago.to_date.to_s(:db) %>
created_at: <%= 2.days.ago %>
updated_at: <%= 2.days.ago %>
hearts_008:
heartable_type: Journal
heartable_id: 1
user_id: 3
created_at: <%= 1.day.ago.to_date.to_s(:db) %>
updated_at: <%= 1.day.ago.to_date.to_s(:db) %>
created_at: <%= 1.day.ago %>
updated_at: <%= 1.day.ago %>
hearts_004:
heartable_type: Board
heartable_id: 1
user_id: 3
created_at: <%= 1.minute.ago.to_date.to_s(:db) %>
updated_at: <%= 1.minute.ago.to_date.to_s(:db) %>
created_at: <%= 1.minute.ago %>
updated_at: <%= 1.minute.ago %>
8 changes: 4 additions & 4 deletions test/integration/hearts_hooked_boards_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,16 @@ class HeartsHookedBoardsTest < Redmine::IntegrationTest
def test_index_shall_not_contain_hooks
get '/projects/1/boards/'
assert_response :success
assert_select 'script[src*="transplant_heart_link_with_counter.js"]', :count => 0
assert_select 'link[href*="redmine_hearts/stylesheets/application.css"]', :count => 0
assert_select 'script:match("src", ?)', /\/redmine_hearts\/.*transplant_heart_link_with_counter.*\.js/, :count => 0
assert_select 'link:match("href", ?)', /\/redmine_hearts\/.*application.*\.css/, :count => 0
assert_select '.heart-link-with-count', :count => 0
end

def test_topic_view
get '/boards/1/topics/1'
assert_response :success
assert_select 'script[src*="transplant_heart_link_with_counter.js"]', :count => 1
assert_select 'link[href*="redmine_hearts/stylesheets/application.css"]', :count => 1
assert_select 'script:match("src", ?)', /\/redmine_hearts\/.*transplant_heart_link_with_counter.*\.js/, :count => 1
assert_select 'link:match("href", ?)', /\/redmine_hearts\/.*application.*\.css/, :count => 1

assert_select '#content > .heart-link-with-count.message-1-heart', :count => 1
assert_select '#content > .heart-link-with-count.message-1-heart .heart-count-number', :text => "1"
Expand Down
Loading