redmine_extensions 0.4.4 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c323b631909b06ccb6639635fe5a455377bb3bc52d32697219ee719af6703cb8
4
- data.tar.gz: 95b3915e35e038289454287eea645278fd50aa4a082c1d8e73fd58444aabc9e9
3
+ metadata.gz: 5f546239fc57393520a159c44ce22ff11a15065869488f1e65aafb8890d3f0ac
4
+ data.tar.gz: 8b1c89f27696a4013e95d9f6f1bf6ba87035af404bc78b3d323b27c94e508c3c
5
5
  SHA512:
6
- metadata.gz: 72ce72eaddf0dfb74b725161d5f10be15f14811bd0c10d7c393e4cb7d94bfe9e5270e2a04e51a0c26a72868ec6ffc69b014d2fe270423d4ba5a4b2a2dc5e43a4
7
- data.tar.gz: 7f3472c8c33946ebcf5a174528bc7413b1e5a1c118f369a345fdbd69a74ea4b5840da6a22aa663948758d7d8e4cdb76ea7f5b24ae0b336bb83b62ad3cd417df8
6
+ metadata.gz: d74ef572956e79c8c1ebb38d5db34ee3f812b52879b351fa10fd8e7126f7bac4b71caaa2b44f19e0f8fdc3c47a24f8bbfd6e39e022d2b68aa631c51a96f55c14
7
+ data.tar.gz: 57e51045f7038976950067078965bfc1a5c0bef1a0c1391150af94c8ef4fd9388f895417e120b41248078331de5bf12a44e7c49a456a0dd293efb8185e8432e9
data/README.md ADDED
@@ -0,0 +1,47 @@
1
+ # Redmine Extensions
2
+
3
+ [![pipeline status](https://git.easy.cz/redmine/redmine_extensions_gem/badges/master/pipeline.svg)](https://git.easy.cz/redmine/redmine_extensions_gem/-/commits/master)
4
+
5
+ [![Latest Release](https://git.easy.cz/redmine/redmine_extensions_gem/-/badges/release.svg)](https://git.easy.cz/redmine/redmine_extensions_gem/-/releases)
6
+
7
+ [![Gem Version](https://badge.fury.io/rb/redmine_extensions.svg)](http://badge.fury.io/rb/redmine_extensions)
8
+
9
+ This gem provides an extended funcionality for a Redmine project
10
+
11
+ ## Provided funcionalities
12
+ * EasySetting - per project settings
13
+ * Redmine Plugin Generator
14
+ * Redmine Entity Generator
15
+
16
+ ## Redmine Plugin Generator
17
+
18
+ Description:
19
+ The plugin generator creates stubs for a new Redmine plugin.
20
+ Plugin is prepared for use in Redmine and Easy Redmine as well.
21
+ You can use --customer flag to generate a special plugin if you can make just a few changes to code. Backup this plugin before Redmine or Easy Redmine upgrade and move back for keep you changes.
22
+
23
+ Example:
24
+ rails g redmine_extensions:plugin NameOfNewPlugin
25
+ create plugins/name_of_new_plugin/app/controllers
26
+ ...
27
+
28
+ Help:
29
+ rails g redmine_extensions:plugin --help
30
+
31
+
32
+ ## Redmine Entity Generator
33
+
34
+ Description:
35
+ The entity generator creates new entity for Redmine plugin.
36
+ New entity is prepared for use in Redmine and Easy Redmine as well.
37
+
38
+ Example:
39
+ rails g redmine_extensions:entity NameOfNewPlugin Post
40
+ create plugins/name_of_new_plugin/app/controllers
41
+ ...
42
+
43
+ Help:
44
+ rails g redmine_extensions:entity --help
45
+
46
+ ## Licence
47
+ This is published under GPL-2 license.
@@ -83,6 +83,7 @@ EasyGem.schedule.require(function () {
83
83
  render_item: function (ul, item) {
84
84
  return $("<li>")
85
85
  .data("item.autocomplete", item)
86
+ .attr('item_id', item.id)
86
87
  .text(item.label)
87
88
  .appendTo(ul);
88
89
  },
@@ -31,8 +31,9 @@ module RedmineExtensions
31
31
 
32
32
  # hide elements for issues and users
33
33
  def detect_hide_elements(uniq_id, user = nil, default = true)
34
- return ''.html_safe if uniq_id.blank?
35
- return 'style="display:none"'.html_safe if !toggle_button_expanded?(uniq_id, user, default)
34
+ return if uniq_id.blank?
35
+
36
+ 'style="display:none"'.html_safe if !toggle_button_expanded?(uniq_id, user, default)
36
37
  end
37
38
 
38
39
  def url_to_entity(entity, options={})
@@ -140,6 +141,8 @@ module RedmineExtensions
140
141
  end
141
142
 
142
143
  def get_jasmine_tags
144
+ ActiveSupport::Deprecation.warn "jasmine will be removed from redmine_extensions"
145
+
143
146
  tags = params[:jasmine]
144
147
  return [] if tags == 'true'
145
148
  if tags.is_a?(String)
@@ -154,7 +157,7 @@ module RedmineExtensions
154
157
  def easy_avatar_url(user = nil)
155
158
  user ||= User.current
156
159
  result = if Setting.gravatar_enabled?
157
- options = {:ssl => (request && request.ssl?), :default => Setting.gravatar_default}
160
+ options = { ssl: (request&.ssl?), default: Setting.gravatar_default }
158
161
  email = nil
159
162
  if user.respond_to?(:mail)
160
163
  email = user.mail
@@ -287,7 +290,7 @@ module RedmineExtensions
287
290
  # * +rootElement+ - Has sence only if jsonpath is used for available values. It tells if the json response has values wrapped under root element.
288
291
  # For response like <tt>{projects: [[<name>, <id>], [<name2>, <id2>]]}</tt> user option <tt>rootElement: 'projects'</tt>
289
292
  def autocomplete_field_tag(name, jsonpath_or_array, selected_values, options = {})
290
- options.reverse_merge!({select_first_value: false, load_immediately: false, preload: true, multiple: true, combo: false})
293
+ options.reverse_merge!(select_first_value: false, load_immediately: false, preload: true, multiple: true, combo: false)
291
294
  options[:id] ||= sanitize_to_id(name)
292
295
 
293
296
  selected_values ||= []
@@ -298,8 +301,8 @@ module RedmineExtensions
298
301
  source = "'#{jsonpath_or_array}'"
299
302
  end
300
303
 
301
- content_tag(:span, :class => 'easy-multiselect-tag-container') do
302
- search_field_tag('', '', (options[:html_options] || {}).merge(id: options[:id])) +
304
+ content_tag(:span, class: 'easy-multiselect-tag-container', data: { cy: "container_old_autocomplete--#{name}" }) do
305
+ search_field_tag('', '', (options[:html_options] || {}).merge(id: options[:id], data: { cy: "search_old_autocomplete--#{name}" })) +
303
306
  late_javascript_tag("$('##{options[:id]}').easymultiselect({multiple: #{options[:multiple]}, rootElement: #{options[:rootElement].to_json}, inputName: '#{name}', preload: #{options[:preload]}, combo: #{options[:combo]}, source: #{source}, selected: #{selected_values.to_json}, select_first_value: #{options[:select_first_value]}, load_immediately: #{options[:load_immediately]}, autocomplete_options: #{(options[:jquery_auto_complete_options]||{}).to_json} });")
304
307
  end
305
308
  end
@@ -1,8 +1,26 @@
1
1
  <div class="module box <%= renderer.container_class %>"<%=raw renderer.saving_state_enabled? && %Q{ data-toggle="#{renderer.id}"} || nil %>>
2
2
  <%= content_tag(:div, class: 'module-heading ' + renderer.heading_class, onclick: (renderer.collapsible? && 'EasyToggler.toggle(this.nextElementSibling, event)' || nil)) do %>
3
- <%= content_tag(:span, ' ', class: 'expander module-toggler') if renderer.collapsible? %>
4
3
  <%= content_tag(renderer.heading_tag, renderer.heading, class: renderer.icon) %>
5
- <%= content_tag(:span, renderer.heading_links, class: 'module-heading-links') if renderer.heading_links.presence %>
4
+ <% if renderer.heading_links.presence %>
5
+ <div class="module-heading-links">
6
+ <a class="module-heading-links__control icon-more-horiz control--<%= renderer.id %>" title="<%= l(:button_heading_links) %>" aria-label="<%= l(:button_heading_links) %>" role="button"></a>
7
+ <ul class="module-heading-links__tooltip tooltip tooltip--<%= renderer.id %>">
8
+ <%= renderer.heading_links %>
9
+ <% if renderer.collapsible? -%>
10
+ <li><span href="#" class="icon-chevron-up module__expander" data-cy="expander__toggle--module" title="Expander" aria-label="Expander" role="button">&nbsp;</span></li>
11
+ <% end -%>
12
+ </ul>
13
+ <script>
14
+ EASY.schedule.require(function(){
15
+ $('.control--<%= renderer.id %>').toggleable({
16
+ observer: EASY.defaultClickObserver,
17
+ content: $('.tooltip--<%= renderer.id %>')
18
+ })},function () {
19
+ return EASY.defaultClickObserver;
20
+ })
21
+ </script>
22
+ </div>
23
+ <% end -%>
6
24
  <% end if renderer.heading.present? %>
7
25
  <div class="module-content" id="<%= renderer.id %>"<%=raw renderer.collapsed? && %q{ style="display:none"} || nil %>>
8
26
  <%= content -%>
@@ -1,7 +1,9 @@
1
+ <% ActiveSupport::Deprecation.warn "Jasmine will be removed from redmine_extensions in next version" %>
2
+
1
3
  <% if params[:jasmine] %>
2
4
  <script type="application/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/3.1.0/jasmine.js"></script>
3
5
  <script type="application/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/3.1.0/jasmine-html.js"></script>
4
6
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jasmine/3.1.0/jasmine.css">
5
7
  <%= javascript_include_tag('redmine_extensions/jasmine_lib/jasmine_lib.js') %>
6
8
  <%= stylesheet_link_tag('redmine_extensions/jasmine.css') %>
7
- <% end %>
9
+ <% end %>
@@ -2,7 +2,7 @@
2
2
  <%% if @<%= model_name_underscored %> && !@<%= model_name_underscored %>.new_record? %>
3
3
  <%%= content_tag(:li, link_to(l(:button_edit), edit_polymorphic_path([@project, @<%= model_name_underscored %>]), title: l(:button_edit), class: 'icon icon-edit button')) %>
4
4
  <%% end %>
5
- <%% unless @<%= model_name_underscored %> %>
5
+ <%% if @<%= model_name_underscored %>.nil? %>
6
6
  <%%= content_tag(:li, link_to(l(:button_<%= model_name_underscored %>_new), new_polymorphic_path([@project, :<%= model_name_underscored %>]), title: l(:title_<%= model_name_underscored %>_new), class: 'icon icon-add button button-positive')) %>
7
7
  <%% end %>
8
8
  <%%= content_tag(:li, link_to(l(:label_<%= model_name_pluralize_underscored %>), polymorphic_path([@project, :<%= model_name_pluralize_underscored %>], set_filter: '1'), title: l(:label_<%= model_name_pluralize_underscored %>), class: 'icon icon-folder button')) %>
@@ -8,10 +8,9 @@ require_relative './query_output'
8
8
 
9
9
  module RedmineExtensions
10
10
  class Engine < ::Rails::Engine
11
-
12
11
  config.generators do |g|
13
- g.test_framework :rspec, :fixture => false
14
- g.fixture_replacement :factory_girl, :dir => 'spec/factories'
12
+ g.test_framework :rspec, fixture: false
13
+ g.fixture_replacement :factory_girl, dir: 'spec/factories'
15
14
  g.assets false
16
15
  g.helper false
17
16
  end
@@ -30,7 +29,7 @@ module RedmineExtensions
30
29
  end
31
30
  end
32
31
 
33
- #config.to_prepare goes after Reloader.to_prepare
32
+ # config.to_prepare goes after Reloader.to_prepare
34
33
  RedmineExtensions::Reloader.to_prepare do
35
34
  RedmineExtensions::QueryOutput.register_output RedmineExtensions::QueryOutputs::ListOutput
36
35
  RedmineExtensions::QueryOutput.register_output RedmineExtensions::QueryOutputs::TilesOutput
@@ -39,7 +38,7 @@ module RedmineExtensions
39
38
  ApplicationController.include RedmineExtensions::RenderingHelper
40
39
  end
41
40
 
42
- initializer 'redmine_extensions.initialize' do |app|
41
+ initializer 'redmine_extensions.initialize' do |_app|
43
42
  ActionDispatch::Routing::RouteSet::Generator.prepend RedmineExtensions::RailsPatches::RouteSetGeneratorPatch
44
43
  end
45
44
 
@@ -52,17 +51,15 @@ module RedmineExtensions
52
51
  if true
53
52
  js_dir = app.root.join('public', 'javascripts', 'redmine_extensions')
54
53
  FileUtils.mkdir(js_dir) unless File.directory?(js_dir)
55
- Dir.glob( root.join('app', 'assets', 'javascripts', 'redmine_extensions', '*.js') ) do |js_file|
56
- begin
57
- FileUtils.cp(js_file, app.root.join('public', 'javascripts', 'redmine_extensions'))
58
- rescue
59
- end
54
+ Dir.glob(root.join('app', 'assets', 'javascripts', 'redmine_extensions', '*.js')) do |js_file|
55
+ FileUtils.cp(js_file, app.root.join('public', 'javascripts', 'redmine_extensions'))
56
+ rescue StandardError
60
57
  end
61
58
  end
62
59
  end
63
60
 
64
61
  # include helpers
65
- initializer 'redmine_extensions.rails_patching', before: :load_config_initializers do |app|
62
+ initializer 'redmine_extensions.rails_patching', before: :load_config_initializers do |_app|
66
63
  ActiveSupport.on_load(Rails::VERSION::MAJOR >= 5 ? :action_controller_base : :action_controller) do
67
64
  helper RedmineExtensions::ApplicationHelper
68
65
  # helper RedmineExtensions::EasyQueryHelper
@@ -78,17 +75,10 @@ module RedmineExtensions
78
75
  initializer 'redmine_extensions.initialize_easy_plugins', after: :load_config_initializers do
79
76
  require_relative './hooks'
80
77
 
81
- unless Redmine::Plugin.installed?(:easy_extensions)
82
- ActiveSupport.run_load_hooks(:easyproject, self)
83
- end
78
+ ActiveSupport.run_load_hooks(:easyproject, self) unless Redmine::Plugin.installed?(:easy_extensions)
84
79
 
85
80
  require_relative './easy_entity_formatters/easy_entity_formatter'
86
81
  end
87
82
 
88
- # initializer :add_html_formatting do |app|
89
- # require_relative "./html_formatting"
90
- # Redmine::WikiFormatting.register(:HTML, RedmineExtensions::HTMLFormatting::Formatter, RedmineExtensions::HTMLFormatting::Helper)
91
- # end
92
-
93
83
  end
94
84
  end
@@ -47,14 +47,14 @@ module RedmineExtensions
47
47
  # => :after => 'Project'
48
48
  # => :last
49
49
  # => :if => Proc.new{ Object.const_defined?(:EasyBudgetSheetQuery) }
50
- def self.register_patch(original_klasses_to_patch, patching_module, options={})
50
+ def self.register_patch(original_klasses_to_patch, patching_module, options = {})
51
51
  return if @@reloading_code
52
52
 
53
53
  options ||= {}
54
54
 
55
55
  begin
56
56
  const = patching_module.constantize
57
- @@patches_locations[patching_module] = const.methods(false).map{|m| const.method(m) }.first.source_location.first
57
+ @@patches_locations[patching_module] = const.methods(false).map { |m| const.method(m) }.first.source_location.first
58
58
  rescue
59
59
  # [0] is register_*_patch
60
60
  from_location = caller_locations(2..2).first
@@ -71,7 +71,7 @@ module RedmineExtensions
71
71
  raise ArgumentError, 'EasyPatchManager->register_patch: The \'original_klass_to_patch\' have to be a string or array of strings!'
72
72
  end
73
73
 
74
- raise ArgumentError, "EasyPatchManager->register_patch: The \'patching_module\' (#{patching_module}) already exists!" if EasyPatch.all_patching_modules.include?( patching_module )
74
+ raise ArgumentError, "EasyPatchManager->register_patch: The \'patching_module\' (#{patching_module}) already exists!" if EasyPatch.all_patching_modules.include?(patching_module)
75
75
 
76
76
  if options[:section]
77
77
  section = options.delete(:section).to_sym
@@ -81,47 +81,47 @@ module RedmineExtensions
81
81
  raise ArgumentError, "EasyPatchManager->register_patch: The section (#{section}) must be one of x#{@@registered_patches.keys.join(', ')}x " unless @@registered_patches.key?(section)
82
82
 
83
83
  original_klasses_to_patch.each do |original_klass_to_patch|
84
- pcollection = @@registered_patches[section].move_and_get_or_insert( original_klass_to_patch, options )
84
+ pcollection = @@registered_patches[section].move_and_get_or_insert(original_klass_to_patch, options)
85
85
  pcollection << EasyPatch.new(original_klass_to_patch, patching_module, options)
86
86
  end
87
87
  end
88
- private_class_method :register_patch
89
88
 
89
+ private_class_method :register_patch
90
90
 
91
- def self.register_ruby_patch(original_klass_to_patch, patching_module, options={})
92
- register_patch(original_klass_to_patch, patching_module, {:section => :ruby}.merge(options))
91
+ def self.register_ruby_patch(original_klass_to_patch, patching_module, options = {})
92
+ register_patch(original_klass_to_patch, patching_module, { section: :ruby }.merge(options))
93
93
  end
94
94
 
95
- def self.register_rails_patch(original_klass_to_patch, patching_module, options={})
96
- register_patch(original_klass_to_patch, patching_module, {:section => :rails}.merge(options))
95
+ def self.register_rails_patch(original_klass_to_patch, patching_module, options = {})
96
+ register_patch(original_klass_to_patch, patching_module, { section: :rails }.merge(options))
97
97
  end
98
98
 
99
- def self.register_redmine_plugin_patch(original_klass_to_patch, patching_module, options={})
100
- register_patch(original_klass_to_patch, patching_module, {:section => :redmine_plugins}.merge(options))
99
+ def self.register_redmine_plugin_patch(original_klass_to_patch, patching_module, options = {})
100
+ register_patch(original_klass_to_patch, patching_module, { :section => :redmine_plugins }.merge(options))
101
101
  end
102
102
 
103
- def self.register_other_patch(original_klass_to_patch, patching_module, options={})
104
- register_patch(original_klass_to_patch, patching_module, {:section => :others}.merge(options))
103
+ def self.register_other_patch(original_klass_to_patch, patching_module, options = {})
104
+ register_patch(original_klass_to_patch, patching_module, { :section => :others }.merge(options))
105
105
  end
106
106
 
107
- def self.register_concern_patch(original_klass_to_patch, patching_module, options={})
108
- register_patch(original_klass_to_patch, patching_module, {:section => :concerns}.merge(options))
107
+ def self.register_concern_patch(original_klass_to_patch, patching_module, options = {})
108
+ register_patch(original_klass_to_patch, patching_module, { :section => :concerns }.merge(options))
109
109
  end
110
110
 
111
- def self.register_controller_patch(original_klass_to_patch, patching_module, options={})
112
- register_patch(original_klass_to_patch, patching_module, {:section => :controllers}.merge(options))
111
+ def self.register_controller_patch(original_klass_to_patch, patching_module, options = {})
112
+ register_patch(original_klass_to_patch, patching_module, { :section => :controllers }.merge(options))
113
113
  end
114
114
 
115
- def self.register_helper_patch(original_klass_to_patch, patching_module, options={})
116
- register_patch(original_klass_to_patch, patching_module, {:section => :helpers}.merge(options))
115
+ def self.register_helper_patch(original_klass_to_patch, patching_module, options = {})
116
+ register_patch(original_klass_to_patch, patching_module, { :section => :helpers }.merge(options))
117
117
  end
118
118
 
119
- def self.register_model_patch(original_klass_to_patch, patching_module, options={})
120
- register_patch(original_klass_to_patch, patching_module, {:section => :models}.merge(options))
119
+ def self.register_model_patch(original_klass_to_patch, patching_module, options = {})
120
+ register_patch(original_klass_to_patch, patching_module, { :section => :models }.merge(options))
121
121
  end
122
122
 
123
- def self.register_patch_to_be_first(original_klass_to_patch, patching_module, options={})
124
- register_patch(original_klass_to_patch, patching_module, {:section => :force_first}.merge(options))
123
+ def self.register_patch_to_be_first(original_klass_to_patch, patching_module, options = {})
124
+ register_patch(original_klass_to_patch, patching_module, { :section => :force_first }.merge(options))
125
125
  end
126
126
 
127
127
  def self.register_easy_page_helper(*helper_or_helpers_klass_name)
@@ -208,28 +208,28 @@ module RedmineExtensions
208
208
  end
209
209
 
210
210
  def [](name)
211
- pcollection = @patches_collections.detect{|patch_col| patch_col.name == name }
211
+ pcollection = @patches_collections.detect { |patch_col| patch_col.name == name }
212
212
  end
213
213
 
214
214
  def include_patch?(name)
215
- !!@patches_collections.detect{|patch_col| patch_col.name == name }
215
+ !!@patches_collections.detect { |patch_col| patch_col.name == name }
216
216
  end
217
217
 
218
- def move_and_get_or_insert( name, options )
219
- pcollection = @patches_collections.detect{|patch_col| patch_col.name == name }
220
- founded_order = find_order( options )
218
+ def move_and_get_or_insert(name, options)
219
+ pcollection = @patches_collections.detect { |patch_col| patch_col.name == name }
220
+ founded_order = find_order(options)
221
221
  if pcollection
222
222
  if founded_order
223
223
  pcollection.order = founded_order
224
224
  update_order_by(pcollection)
225
225
  end
226
226
  else
227
- pcollection = insert( name, founded_order )
227
+ pcollection = insert(name, founded_order)
228
228
  end
229
229
  pcollection
230
230
  end
231
231
 
232
- def find_order( options )
232
+ def find_order(options)
233
233
  if options.delete(:first)
234
234
  return 1
235
235
  elsif before = options.delete(:before)
@@ -240,7 +240,7 @@ module RedmineExtensions
240
240
  actual = nil
241
241
  before_patch = self[before_class_name]
242
242
  actual = before_patch.order if before_patch
243
- if actual && ( !min || actual < min )
243
+ if actual && (!min || actual < min)
244
244
  min = actual
245
245
  end
246
246
  end
@@ -277,7 +277,7 @@ module RedmineExtensions
277
277
 
278
278
  private
279
279
 
280
- def push_back( collection )
280
+ def push_back(collection)
281
281
  # => ambitious, if it is private method...
282
282
  # raise ArgumentError, "Section already contains a collection #{collection.name}" if @patches_collections.detect{ |coll| collection.name == coll.name }
283
283
  @patches_collections << collection
@@ -287,16 +287,16 @@ module RedmineExtensions
287
287
  @last_order += 1
288
288
  end
289
289
 
290
- def insert( name, order = nil )
290
+ def insert(name, order = nil)
291
291
  final_order = order || last_order
292
- collection = EasyPatchesCollection.new( name, final_order )
293
- push_back( collection )
294
- update_order_by( collection ) if order
292
+ collection = EasyPatchesCollection.new(name, final_order)
293
+ push_back(collection)
294
+ update_order_by(collection) if order
295
295
  collection
296
296
  end
297
297
 
298
- def update_order_by( collection )
299
- @patches_collections.select {|patch_coll| ( patch_coll.name != collection.name ) && ( patch_coll.order >= collection.order ) }.each do |col|
298
+ def update_order_by(collection)
299
+ @patches_collections.select { |patch_coll| (patch_coll.name != collection.name) && (patch_coll.order >= collection.order) }.each do |col|
300
300
  col.order = col.order + 1
301
301
  end
302
302
  @patches_collections.sort!
@@ -347,7 +347,6 @@ module RedmineExtensions
347
347
 
348
348
  end
349
349
 
350
-
351
350
  class EasyPatch
352
351
 
353
352
  def self.all_patching_modules
@@ -374,9 +373,7 @@ module RedmineExtensions
374
373
  end
375
374
 
376
375
  def apply_patch
377
- if (cond = @options[:if]) && cond.respond_to?(:call)
378
- return unless cond.call
379
- end
376
+ return if (cond = @options[:if]) && cond.respond_to?(:call) && !cond.call
380
377
 
381
378
  pm_klass = easy_constantize(patching_module)
382
379
  # pm_klass.class_eval { unloadable }
@@ -392,10 +389,13 @@ module RedmineExtensions
392
389
  oktp_klass.include pm_klass
393
390
  end
394
391
  end
392
+ rescue NameError => e
393
+ patch_location = Module.const_source_location(patching_module)
394
+ raise NameError, "#{e.message} in #{patch_location}"
395
395
  end
396
396
 
397
397
  def easy_constantize(name)
398
- const = name.constantize
398
+ name.constantize
399
399
  rescue NameError
400
400
  if RedmineExtensions::PatchManager.patches_locations.has_key?(name)
401
401
  RedmineExtensions::PatchManager.with_reloading_code do
@@ -1,3 +1,5 @@
1
1
  module RedmineExtensions
2
- VERSION = '0.4.4'
2
+
3
+ VERSION = '0.5.1'
4
+
3
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redmine_extensions
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.4
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Easy Software Ltd
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-06-17 00:00:00.000000000 Z
11
+ date: 2022-06-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -16,20 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '4.2'
20
- - - "<"
21
- - !ruby/object:Gem::Version
22
- version: '6.2'
19
+ version: '6.1'
23
20
  type: :runtime
24
21
  prerelease: false
25
22
  version_requirements: !ruby/object:Gem::Requirement
26
23
  requirements:
27
24
  - - ">="
28
25
  - !ruby/object:Gem::Version
29
- version: '4.2'
30
- - - "<"
31
- - !ruby/object:Gem::Version
32
- version: '6.2'
26
+ version: '6.1'
33
27
  description: Redmine Extensions provide many extended functionalities for Redmine
34
28
  project.
35
29
  email:
@@ -39,6 +33,7 @@ extensions: []
39
33
  extra_rdoc_files: []
40
34
  files:
41
35
  - LICENSE
36
+ - README.md
42
37
  - Rakefile
43
38
  - app/assets/javascripts/redmine_extensions/application.js
44
39
  - app/assets/javascripts/redmine_extensions/blocking.js
@@ -166,10 +161,6 @@ files:
166
161
  - lib/redmine_extensions/engine.rb
167
162
  - lib/redmine_extensions/export/easy_other_formats_builder.rb
168
163
  - lib/redmine_extensions/hooks.rb
169
- - lib/redmine_extensions/html_formatting.rb
170
- - lib/redmine_extensions/html_formatting/formatter.rb
171
- - lib/redmine_extensions/html_formatting/helper.rb
172
- - lib/redmine_extensions/html_formatting/internals.rb
173
164
  - lib/redmine_extensions/migration.rb
174
165
  - lib/redmine_extensions/patch_manager.rb
175
166
  - lib/redmine_extensions/query_output.rb
@@ -185,13 +176,10 @@ files:
185
176
  - lib/redmine_extensions/version.rb
186
177
  - lib/tasks/redmine_extensions_tasks.rake
187
178
  - spec/factories/easy_settings.rb
188
- - spec/features/autocomplete_spec.rb
189
- - spec/features/jasmine_spec.rb
190
179
  - spec/init_rails.rb
191
180
  - spec/models/easy_setting_spec.rb
192
181
  - spec/presenters/easy_settings/params_wrapper_spec.rb
193
182
  - spec/spec_helper.rb
194
- - spec/support/plugin_generator.rb
195
183
  homepage: https://www.easyredmine.com
196
184
  licenses:
197
185
  - GPL-2.0
@@ -204,24 +192,21 @@ required_ruby_version: !ruby/object:Gem::Requirement
204
192
  requirements:
205
193
  - - ">="
206
194
  - !ruby/object:Gem::Version
207
- version: '2.5'
195
+ version: '2.7'
208
196
  required_rubygems_version: !ruby/object:Gem::Requirement
209
197
  requirements:
210
198
  - - ">="
211
199
  - !ruby/object:Gem::Version
212
200
  version: '0'
213
201
  requirements: []
214
- rubygems_version: 3.3.11
202
+ rubygems_version: 3.2.33
215
203
  signing_key:
216
204
  specification_version: 4
217
- summary: Redmine Extensions is set of usefull features for Redmine. Main focus is
218
- on development helpers, but many users can find it helpfull
205
+ summary: Redmine Extensions is set of useful features for Redmine. Main focus is on
206
+ development helpers, but many users can find it helpfull
219
207
  test_files:
220
208
  - spec/factories/easy_settings.rb
221
- - spec/features/autocomplete_spec.rb
222
- - spec/features/jasmine_spec.rb
223
209
  - spec/init_rails.rb
224
210
  - spec/models/easy_setting_spec.rb
225
211
  - spec/presenters/easy_settings/params_wrapper_spec.rb
226
212
  - spec/spec_helper.rb
227
- - spec/support/plugin_generator.rb
@@ -1,86 +0,0 @@
1
- module RedmineExtensions
2
- module HTMLFormatting
3
- class Formatter < String
4
- include ActionView::Helpers::TagHelper
5
-
6
- RULES = [:tidy_html_from_editor, :rinku_auto_link, :inline_auto_link, :inline_auto_mailto]
7
-
8
- def to_html(*rules, &block)
9
- ret = self.dup
10
- RULES.each do |rule_name|
11
- ret = (method(rule_name).call(ret) || ret)
12
- end
13
- ret
14
- end
15
-
16
- private
17
-
18
- AUTO_LINK_RE = %r{
19
- ( # leading text
20
- #<\w+.*?>| # leading HTML tag, or
21
- [^=<>!:'"/]| # leading punctuation, or
22
- \{\{\w+\(| # inside a macro?
23
- ^ # beginning of line
24
- )
25
- (
26
- (?:https?://)| # protocol spec, or
27
- (?:s?ftps?://)|
28
- (?:www\.)| # www.*
29
- (?:smb://)|
30
- (?:file://)
31
- )
32
- (
33
- (\S+?) # url
34
- (\/)? # slash
35
- )
36
- ((?:&gt;)?|[^\w\=\/;\(\)]*?) # post
37
- (?=<|\s|&nbsp;|$)
38
- }x unless const_defined?(:AUTO_LINK_RE)
39
-
40
- def rinku_auto_link(text)
41
- Rinku.auto_link(text) if defined?(Rinku)
42
- end
43
-
44
- # Turns all urls into clickable links (code from Rails).
45
- def inline_auto_link(text, regex_rules = AUTO_LINK_RE)
46
- text.gsub!(regex_rules) do
47
- all, leading, proto, url, post = $&, $1, $2, $3, $6
48
-
49
- if leading =~ /<a\s/i || leading =~ /![<>=]?/ || leading =~ /\{\{\w+\(/
50
- #don't replace URL's that are already linked
51
- #and URL's prefixed with ! !> !< != (textile images)
52
- all
53
- else
54
- #Idea below : an URL with unbalanced parethesis and
55
- #ending by ')' is put into external parenthesis
56
- if ( url[-1]==?) and ((url.count("(") - url.count(")")) < 0 ) )
57
- url=url[0..-2] # discard closing parenth from url
58
- post = ")"+post # add closing parenth to post
59
- end
60
-
61
- tag = content_tag('a', proto + url, :href => "#{proto == 'www.' ? "http://#{proto}" : proto}#{url}", :class => 'external', :target => '_blank')
62
- %(#{leading}#{tag}#{post})
63
- end
64
- end
65
- end
66
-
67
- # Turns all email addresses into clickable links (code from Rails).
68
- def inline_auto_mailto(text)
69
- text.gsub!(/([\w\.!#\$%\-+.]+@[A-Za-z0-9\-]+(\.[A-Za-z0-9\-]+)+)/) do
70
- mail = $1
71
- if text.match(/<a\b[^>]*>(.*)(#{Regexp.escape(mail)})(.*)<\/a>/)
72
- mail
73
- else
74
- content_tag('a', mail, :href => "mailto:#{mail}", :class => "email")
75
- end
76
- end
77
- end
78
-
79
- # Tidy html. Fix html tags for correct show pages.
80
- def tidy_html_from_editor(text)
81
- Nokogiri::HTML::DocumentFragment.parse(text).to_html
82
- end
83
-
84
- end
85
- end
86
- end
@@ -1,73 +0,0 @@
1
- module RedmineExtensions
2
- module HTMLFormatting
3
- module Helper
4
-
5
- def wikitoolbar_for(field_id, options={})
6
- heads_for_wiki_formatter
7
-
8
- custom_settings = options.delete(:custom)
9
- options[:toolbar] ||= EasySetting.value('ckeditor_toolbar_config') || 'Basic'
10
- options[:lang] ||= User.current.language
11
- options[:lang] = Setting.default_language if options[:lang].blank?
12
- options[:language] = options[:lang] if options[:lang].present?
13
-
14
- # Syntax higlight
15
- if EasySetting.value('ckeditor_syntax_highlight_enabled')
16
- options[:codeSnippet_theme] ||= EasyCKEditor.syntaxt_higlight_template
17
- else
18
- if options[:removePlugins]
19
- options[:removePlugins] << ','
20
- else
21
- options[:removePlugins] = ''
22
- end
23
-
24
- options[:removePlugins] << 'codesnippet'
25
- end
26
-
27
- hook_settings = call_hook(:helper_ckeditor_wikitoolbar_for_add_option, {:field_id => field_id, :options => options})
28
-
29
- ck_options = options.collect{|k,v| "#{k}:'#{v}'"}
30
- ck_options << custom_settings unless custom_settings.blank?
31
- ck_options << hook_settings unless hook_settings.to_s.blank?
32
-
33
- reminder_confirm = options[:attachment_reminder_message] ? options[:attachment_reminder_message] : l(:text_easy_attachment_reminder_confirm)
34
- reminderjs = options[:attachment_reminder] ? "$('##{field_id}').addClass('set_attachment_reminder').data('ck', true).data('reminder_words', \"#{j(Attachment.attachment_reminder_words)}\").data('reminder_confirm', '#{j(reminder_confirm)}'); " : ''
35
-
36
- js = "var ta_editor = CKEDITOR.instances['#{field_id}']; if (ta_editor) {CKEDITOR.remove(ta_editor);} CKEDITOR.replace('#{field_id}',{#{ck_options.join(',')}});"
37
- js << "window.enableWarnLeavingUnsaved = '#{User.current.pref.warn_on_leaving_unsaved}';"
38
-
39
- javascript_tag(reminderjs + js)
40
- end
41
-
42
- def initial_page_content(page)
43
- end
44
-
45
- def heads_for_wiki_formatter
46
- unless @heads_for_wiki_formatter_included
47
- header = javascript_include_tag('redmine_extensions/ckeditor/ckeditor')
48
-
49
- # Syntax higlight
50
- if EasySetting.value('ckeditor_syntax_highlight_enabled')
51
- header << stylesheet_link_tag(EasyCKEditor.syntaxt_higlight_css)
52
- header << javascript_include_tag(EasyCKEditor.syntaxt_higlight_js)
53
-
54
- # Pre block have custom css attributes
55
- # .pre-hljs will set them to default
56
- header << javascript_tag(%{
57
- $(document).ready(function() {
58
- $('pre code').each(function(i, block) {
59
- hljs.highlightBlock(block);
60
- $(block).parent().addClass('pre-default');
61
- });
62
- });
63
- })
64
- end
65
-
66
- content_for(:header_tags, header)
67
- @heads_for_wiki_formatter_included = true
68
- end
69
-
70
- end
71
- end
72
- end
73
- end
@@ -1,23 +0,0 @@
1
- module EasyCKEditor
2
-
3
- def self.syntaxt_higlight_default_template
4
- @syntaxt_higlight_default_template ||= 'github'
5
- end
6
-
7
- def self.syntaxt_higlight_templates
8
- @syntaxt_higlight_templates ||= ['github', 'googlecode', 'idea', 'monokai', 'monokai_sublime', 'railscasts']
9
- end
10
-
11
- def self.syntaxt_higlight_template
12
- EasySetting.value('ckeditor_syntax_highlight_theme') || syntaxt_higlight_default_template
13
- end
14
-
15
- def self.syntaxt_higlight_css
16
- "/plugin_assets/ckeditor/javascripts/ckeditor/plugins/codesnippet/lib/highlight/styles/#{syntaxt_higlight_template}"
17
- end
18
-
19
- def self.syntaxt_higlight_js
20
- @syntaxt_higlight_js ||= "/plugin_assets/ckeditor/javascripts/ckeditor/plugins/codesnippet/lib/highlight/highlight.pack.js"
21
- end
22
-
23
- end
@@ -1,3 +0,0 @@
1
- require_relative './html_formatting/internals'
2
- require_relative './html_formatting/formatter'
3
- require_relative './html_formatting/helper'
@@ -1,17 +0,0 @@
1
- RSpec.describe 'autocomplete', type: :feature, js: true, logged: :admin do
2
-
3
- describe 'render' do
4
- it 'generate default autocomplete' do
5
- visit '/dummy_autocompletes'
6
- expect(page).to have_css('input#default[type="search"]')
7
- expect(page).to have_css('input[type="hidden"][name="default"][value="value1"]', visible: false)
8
- end
9
-
10
- it 'generate autocomplete_field in form_for' do
11
- visit '/dummy_autocompletes'
12
- expect(page).to have_css('input#dummy_entities_autocomplete[type="search"]')
13
- expect(page).to have_css('input[type="hidden"][name="dummy_entity[array_of_dummies][]"][value="value1"]', visible: false)
14
- end
15
- end
16
-
17
- end
@@ -1,9 +0,0 @@
1
- RSpec.describe 'jasmine', type: :feature, js: true, logged: :admin do
2
-
3
- it 'run tests' do
4
- visit "/dummy_entities?jasmine=true"
5
- expect(page).to have_css('.jasmine-bar')
6
- expect(page.evaluate_script('window.jasmineHelper.parseResult();')).to eq('success')
7
- end
8
-
9
- end
@@ -1,111 +0,0 @@
1
- require 'rails/generators'
2
-
3
- module PluginGenerator
4
- def self.generate_test_plugin!
5
- Rails::Generators.invoke 'redmine_extensions:plugin', ['DummyPlugin'], behavior: :revoke, destination_root: Rails.root
6
- Rails::Generators.invoke 'redmine_extensions:plugin', ['DummyPlugin'], behavior: :invoke, destination_root: Rails.root
7
- generate_autocomplete!
8
- end
9
-
10
- def self.generate_autocomplete!
11
- generate_dummy_entity!
12
- generate_entities_view!
13
- generate_autocomplete_controller!
14
- generate_autocomplete_routes!
15
- generate_autocomplete_view!
16
- end
17
-
18
- def self.generate_dummy_entity!
19
- File.open( Rails.root.join('plugins', 'dummy_plugin', 'db', 'migrate', '20162010160230_create_dummy_entities.rb'), 'w' ) do |file|
20
- file.write( <<-END_RUBY )
21
- class CreateDummyEntities < ActiveRecord::Migration[4.2]
22
- def change
23
- create_table :dummy_entities do |t|
24
- t.string :name
25
- t.integer :value
26
- t.references :project, index: true
27
- t.text :array_of_dummies
28
- end
29
- end
30
- end
31
- END_RUBY
32
- end
33
-
34
- File.open( Rails.root.join('plugins', 'dummy_plugin', 'app', 'models', 'dummy_entity.rb'), 'w' ) do |file|
35
- file.write( <<-END_RUBY )
36
- class DummyEntity < ActiveRecord::Base
37
- include Redmine::SafeAttributes
38
- safe_attributes 'name',
39
- 'value',
40
- 'project_id',
41
- 'array_of_dummies'
42
-
43
- serialize :array_of_dummies, Array
44
- end
45
- END_RUBY
46
- end
47
-
48
- File.open(Rails.root.join('plugins', 'dummy_plugin', 'app', 'controllers', 'dummy_entities_controller.rb'), 'w') do |file|
49
- file.write( <<-END_RUBY )
50
- class DummyEntitiesController < ApplicationController
51
- def index
52
- end
53
-
54
- def create
55
- @entity = DummyEntity.new
56
- @entity.safe_attributes = params[:dummy_entity]
57
- @entity.save
58
- end
59
- end
60
- END_RUBY
61
- end
62
- end
63
-
64
- def self.generate_autocomplete_controller!
65
- File.open(Rails.root.join('plugins', 'dummy_plugin', 'app', 'controllers', 'dummy_autocompletes_controller.rb'), 'w') do |file|
66
- file.write( <<-END_RUBY )
67
- class DummyAutocompletesController < ApplicationController
68
- def index
69
- end
70
- end
71
- END_RUBY
72
- end
73
- end
74
-
75
- def self.generate_autocomplete_routes!
76
- File.open(Rails.root.join('plugins', 'dummy_plugin', 'config', 'routes.rb'), 'w') do |file|
77
- file.write( <<-END_ROUTES )
78
- resources :dummy_autocompletes
79
- resources :dummy_entities
80
- END_ROUTES
81
- end
82
- end
83
-
84
- def self.generate_autocomplete_view!
85
- dir = Rails.root.join('plugins', 'dummy_plugin', 'app', 'views', 'dummy_autocompletes')
86
- Dir.mkdir dir
87
- File.open(dir.join('index.html.erb'), 'w') do |file|
88
- file.write( <<-END_ERB )
89
- <%= form_tag('/dummy_autocompletes', id: 'autocompletes_form') do %>
90
- <%= autocomplete_field_tag('default', ['value1', 'value2'], ['value1']) %>
91
- <% end %>
92
-
93
- <%= form_for(DummyEntity.new(array_of_dummies: ['value1'])) do |f| %>
94
- <%= f.autocomplete_field(:array_of_dummies, ['value1', 'value2'], {}, id: 'dummy_entities_autocomplete') %>
95
- <% end %>
96
- END_ERB
97
- end
98
- end
99
-
100
- def self.generate_entities_view!
101
- dir = Rails.root.join('plugins', 'dummy_plugin', 'app', 'views', 'dummy_entities')
102
- Dir.mkdir dir
103
- File.open(dir.join('index.html.erb'), 'w') do |file|
104
- file.write( <<-END_ERB )
105
- <% DummyEntity.all.each do |entity| %>
106
- <%= entity.name %>: <%= entity.value %>
107
- <% end %>
108
- END_ERB
109
- end
110
- end
111
- end