redmine_extensions 0.4.5 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1dae35cf1688bbeec5af825fe60a8b5ed1d12000e5e23759be72bb4eb5435126
4
- data.tar.gz: 94338355d5d639563b74e339a50d14e34b75e3214cdd461bd092f010370ae940
3
+ metadata.gz: 5f546239fc57393520a159c44ce22ff11a15065869488f1e65aafb8890d3f0ac
4
+ data.tar.gz: 8b1c89f27696a4013e95d9f6f1bf6ba87035af404bc78b3d323b27c94e508c3c
5
5
  SHA512:
6
- metadata.gz: 3c1f6057b2d1aa1dc5827dfec676bc0b8cfb888b8f1154b5e4ecaf77392cfda67e053477f9410a119f0129deeea6666de9649f84799eb33e64117f789c29f935
7
- data.tar.gz: 51d77d57dd4176d44230eb925e3ce830fd6b9f615991dee0856d040cc0e9f09c18d0819849996d06c83aa50033e880d9f741b1919f8f6b982aa7c973276fa056
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')) %>
@@ -24,7 +24,7 @@
24
24
  <hr />
25
25
  <%%= render partial: 'redmine_extensions/custom_field_rows', locals: { custom_field_values: @<%= model_name_underscored %>.visible_custom_field_values } %>
26
26
  <%- end -%>
27
- <%%= call_hook(:view_<%= model_name_pluralize_underscored %>_show_details_bottom, <%= model_name_underscored%>: @<%= model_name_underscored %>) %>
27
+ <%%= call_hook(:view_<%= model_name_pluralize_underscored %>_show_details_bottom, :<%= model_name_underscored%>: @<%= model_name_underscored %>) %>
28
28
  </table>
29
29
  <%- if description_column? -%>
30
30
  <%% if !@<%= model_name_underscored %>.<%= description_column %>.blank? %>
@@ -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.5'
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.5
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-29 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,7 +192,7 @@ 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
  - - ">="
@@ -214,14 +202,11 @@ requirements: []
214
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