redmine_extensions 0.2.14 → 0.2.16

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
- SHA1:
3
- metadata.gz: 8b3425eda3edb8bd43328e8e60e35efa3ba60e81
4
- data.tar.gz: acfa3a5fb739bca124209fc00e262159a61f0b8a
2
+ SHA256:
3
+ metadata.gz: 5d23088d3d0f1dbefea12bcd0ded9bf06067c34f50e3bd4cadd8407e49ca0cfa
4
+ data.tar.gz: ce1030a05900dd45a6fe3afc959e819ccc5e45bda9ed8f65654dab561140994e
5
5
  SHA512:
6
- metadata.gz: fcec4043c01a6378f2a57d3d252e6e9c340d608105947fd434072bb6281d3aab0edeb0679fae766ca065529c8204cd3a9465ac3a66989e82b631e9cb50a741b3
7
- data.tar.gz: 8588f3ee85ec4a1bb91f355aa674281ec5792b945eab0ad28fcac6f48de7688712e29e211a0b74b99cc32e4983ec873c338e1f0d22963f1556147a4309d57e13
6
+ metadata.gz: ecf1c291b5c5ecbf2c4ece57696995494850a80029c4bb5c3b6c34086eb3a2ffa7afc765ec648a45859005ca916655ed7830e95d079a9e5bf9faee5cc401fb0a
7
+ data.tar.gz: af331f12bb00531e093a689feded32e1e825a1967404638bfa6e8815851016b94b29c4f257094ea45a0a4ec4c6493fa6a2ccda5ddf2cf39b9b31851b4d9f5308
@@ -4,12 +4,31 @@
4
4
  var moduleInstances = {};
5
5
  /** @type {Object.<String,EasyModule>} */
6
6
  var moduleDefinitions = {};
7
- /** @type {Array.<Waiter>} */
7
+ /** @type {Array.<OptionWaiter|CallbackWaiter>} */
8
8
  var waiters = [];
9
9
  /** @type {Object.<String,String>} */
10
10
  var urls = {};
11
11
 
12
- function Waiter(dependencies, callback) {
12
+ /**
13
+ * @param {Array.<String>} dependencies
14
+ * @param {Array} options
15
+ * @property {Array} options
16
+ * @property {Array.<String>} dependencies
17
+ * @constructor
18
+ */
19
+ function OptionWaiter(dependencies, options) {
20
+ this.dependencies = dependencies;
21
+ this.options = options;
22
+ }
23
+
24
+ /**
25
+ * @param {Array.<String>} dependencies
26
+ * @param {Function} callback
27
+ * @property {Function} callback
28
+ * @property {Array.<String>} dependencies
29
+ * @constructor
30
+ */
31
+ function CallbackWaiter(dependencies, callback) {
13
32
  this.dependencies = dependencies;
14
33
  this.callback = callback;
15
34
  }
@@ -17,7 +36,7 @@
17
36
  /**
18
37
  * @property {String} name
19
38
  * @property {Array.<String>} dependencies
20
- * @property {Array.<Waiter>} waiters
39
+ * @property {Array.<CallbackWaiter>} waiters
21
40
  * @constructor
22
41
  */
23
42
  function EasyModule(moduleName) {
@@ -35,6 +54,7 @@
35
54
  var instance = {};
36
55
  var waiters = this.waiters;
37
56
  for (var i = 0; i < waiters.length; i++) {
57
+ /** @type {CallbackWaiter} */
38
58
  var waiter = waiters[i];
39
59
  var instances = waiter.dependencies.map(function (moduleName) {
40
60
  return moduleInstances[moduleName];
@@ -67,7 +87,15 @@
67
87
  var instances = waiter.dependencies.map(function (moduleName) {
68
88
  return moduleInstances[moduleName];
69
89
  });
70
- waiter.callback.apply(window, instances);
90
+ if (waiter.callback) {
91
+ waiter.callback.apply(window, instances);
92
+ } else {
93
+ instances.forEach(function (instance) {
94
+ if (instance.call) {
95
+ instance.apply(window, waiter.options);
96
+ }
97
+ });
98
+ }
71
99
  }
72
100
 
73
101
  function executeWaiters() {
@@ -116,6 +144,24 @@
116
144
  }
117
145
  }
118
146
 
147
+ /**
148
+ * @param {Array.<String>} moduleNames
149
+ * @param {Array} options
150
+ */
151
+ function prepareModuleOrder(moduleNames, options) {
152
+ if (options.length === 1 && options[0].call) {
153
+ var waiter = new CallbackWaiter(moduleNames, options[0]);
154
+ } else {
155
+ waiter = new OptionWaiter(moduleNames, options);
156
+ }
157
+ if (checkDependencies(moduleNames)) {
158
+ executeWaiter(waiter);
159
+ } else {
160
+ waiters.push(waiter);
161
+ setTimeout(findMissingModules, 5000);
162
+ }
163
+ }
164
+
119
165
  /**
120
166
  *
121
167
  * @type {{urls: Object<String, String>, module: EasyGem.module.module, part: EasyGem.module.part, transform: EasyGem.module.transform, setUrl: EasyGem.module.setUrl}}
@@ -132,7 +178,11 @@
132
178
  urls: urls,
133
179
  /**
134
180
  * Define module in one separate file. Use this method as first line of the file
181
+ * Modules can be constructed by returning a function (simple one-method modules),
182
+ * returning Object (complex, but one-file modules)
183
+ * or by directly setting methods or properties with [this], because context is set to newly created module.
135
184
  * Module can be downloaded on-demand by loadModules() if url is provided by setUrl() function.
185
+ * [prerequisites] argument can be omitted if no prerequisites are required
136
186
  * @example
137
187
  * EasyGem.module.module("myModule", ["jQuery", "c3"], function($, c3) {
138
188
  * return {
@@ -141,18 +191,29 @@
141
191
  * }
142
192
  * }
143
193
  * }
194
+ * @example - same as above but simpler
195
+ * EasyGem.module.module("myModule", ["jQuery", "c3"], function($, c3) {
196
+ * this.init = function(){
197
+ * c3.init($("#graph"));
198
+ * }
199
+ * }
144
200
  * @param {String} moduleName
145
- * @param {Array.<String>} prerequisites - other modules needed for construction of module
146
- * @param {Function} getter - factory function
201
+ * @param {Array.<String>|Function} prerequisites - other modules needed for construction of module, can be omitted
202
+ * @param {Function} [getter] - factory function
147
203
  */
148
204
  module: function (moduleName, prerequisites, getter) {
149
205
  var module = moduleDefinitions[moduleName] = new EasyModule(moduleName);
206
+ if (getter === undefined) {
207
+ getter = prerequisites;
208
+ prerequisites = [];
209
+ }
150
210
  module.dependencies = prerequisites;
151
- module.waiters = [new Waiter(prerequisites, getter)];
211
+ module.waiters = [new CallbackWaiter(prerequisites, getter)];
152
212
  },
153
213
  /**
154
214
  * Define module part if module code is distributed into many separate files.
155
215
  * For dynamic loading by url, all files have to be combine by pipeline into one.
216
+ * You can append methods to module, just use [this].
156
217
  * Module is executed only if all [prerequisites] from all parts of the module is fulfilled, but only part's
157
218
  * [prerequisites] will be used as arguments for [getter].
158
219
  * [prerequisites] argument can be omitted if no prerequisites are required
@@ -166,12 +227,12 @@
166
227
  prerequisites = [];
167
228
  }
168
229
  var module = moduleDefinitions[moduleName];
169
- if (!module){
230
+ if (!module) {
170
231
  module = moduleDefinitions[moduleName] = new EasyModule(moduleName);
171
232
  module.waiters = [];
172
233
  module.dependencies = [];
173
234
  }
174
- module.waiters.push(new Waiter(prerequisites, getter));
235
+ module.waiters.push(new CallbackWaiter(prerequisites, getter));
175
236
  for (var i = 0; i < prerequisites.length; i++) {
176
237
  var prerequisite = prerequisites[i];
177
238
  if (module.dependencies.indexOf(prerequisite) === -1) {
@@ -210,35 +271,44 @@
210
271
  }
211
272
  };
212
273
  /**
213
- * Load specified modules and execute [callback].
214
- * Module instances are constructed if not constructed before.
215
- * Missing modules are downloaded if url is provided.
274
+ * Load [moduleNames] modules and do something afterward.
275
+ * Try to download the modules if url is provided by EasyGem.module.setUrl() or EasyGem.module.urls=.
276
+ * Downloaded (or already registered) modules are constructed and result is stored for further invocation of the module.
277
+ * There are two types of action after all module results are obtained.
278
+ * If [options] is only one function, this function is executed with the module results as the arguments.
279
+ * Otherwise, the module results, which are functions, are executed with [options] as the arguments.
280
+ * Error is thrown if any module hasn't been constructed in 5 seconds
216
281
  * @param {Array.<String>} moduleNames
217
- * @param {Function} callback - function with module instances as arguments
282
+ * @param {...*} options - options for module function OR function with module instances as arguments
218
283
  * @example
284
+ * // suitable for smaller modules with one method
285
+ * EasyGem.module.module("colorizeBackground", function() {
286
+ * return function(element, color) {
287
+ * element.style.backgroundColor = color;
288
+ * }
289
+ * });
290
+ * EasyGem.loadModules(["colorizeBackground"], document.getElementById("my_button"), "red");
291
+ * @example
292
+ * // suitable for modules with many methods
219
293
  * EasyGem.loadModules(["jQuery", "myModule"], function($, myModule) {
220
294
  * myModule.init($("#my_module_container"));
221
295
  * });
222
296
  */
223
- EasyGem.loadModules = function (moduleNames, callback) {
224
- var waiter = new Waiter(moduleNames, callback);
225
- if (checkDependencies(moduleNames)) {
226
- executeWaiter(waiter);
227
- } else {
228
- waiters.push(waiter);
229
- setTimeout(findMissingModules, 5000);
230
- }
297
+ EasyGem.loadModules = function (moduleNames, options) {
298
+ options = Array.prototype.slice.call(arguments, 1);
299
+ prepareModuleOrder(moduleNames, options);
231
300
  };
232
301
  /**
233
302
  * Same as EasyGem.loadModules, but only for one module.
234
303
  * @param {String} moduleName
235
- * @param {Function} callback - function with the module instance as first argument
304
+ * @param {...*} options - options for module function OR function with module instances as arguments
236
305
  */
237
- EasyGem.loadModule = function (moduleName, callback) {
238
- this.loadModules([moduleName], callback);
306
+ EasyGem.loadModule = function (moduleName, options) {
307
+ options = Array.prototype.slice.call(arguments, 1);
308
+ prepareModuleOrder([moduleName], options);
239
309
  };
240
310
  var transform = EasyGem.module.transform;
241
311
  transform("jQuery", "jQuery");
242
312
  transform("jQueryUI", "jQueryUI");
243
313
 
244
- })();
314
+ })();
@@ -1,4 +1,4 @@
1
- var EasyToggler = new function() {
1
+ window.EasyToggler = new function() {
2
2
  // EasyToggler storage store object where key is ID of container and value is 0 - for hidden default state or 1 - for shown default state
3
3
  // Example:
4
4
  // localStorage # => {"easy-toggle-state": {myDiv: 0, history: 1}} # where myDiv is by default hidden, and now will be shown as visible and history is vice versa
@@ -99,8 +99,7 @@
99
99
  var data = {
100
100
  _locks: [],
101
101
  _timeout: null,
102
- tags: {},
103
- topMenuHeight: 60
102
+ tags: {}
104
103
  };
105
104
  var start = function () {
106
105
  if (new Date() - data._timeout > 5000) {
@@ -230,12 +229,8 @@
230
229
  element = element[0];
231
230
  }
232
231
  if (!element) throw new Error("missing element");
233
- element.scrollIntoView();
232
+ element.scrollIntoView({block: "center", behavior: "instant"});
234
233
  var box = element.getBoundingClientRect();
235
- if (box.top < data.topMenuHeight) {
236
- window.scrollBy({top: -data.topMenuHeight});
237
- box = element.getBoundingClientRect();
238
- }
239
234
  var pointX = (box.left + box.right) / 2;
240
235
  var pointY = (box.top + box.bottom) / 2;
241
236
  var target = document.elementFromPoint(pointX, pointY);
@@ -0,0 +1,164 @@
1
+ describe("Modules", function () {
2
+ var nameCounter = 0;
3
+
4
+ function getName() {
5
+ return "jasmine_test_" + (nameCounter++);
6
+ }
7
+
8
+ function defineOptionModule(moduleName, context) {
9
+ EasyGem.module.module(moduleName, function () {
10
+ return function () {
11
+ context.add.apply(context, arguments);
12
+ }
13
+ });
14
+ }
15
+
16
+ function defineCallbackModule(moduleName, context) {
17
+ EasyGem.module.module(moduleName, function () {
18
+ return {
19
+ add: function () {
20
+ context.add.apply(context, arguments);
21
+ }
22
+ };
23
+ });
24
+ }
25
+
26
+ function resolveModules() {
27
+ EasyGem.module.setUrl("", null);
28
+ }
29
+
30
+ beforeEach(function () {
31
+ this.counter = 1;
32
+ var self = this;
33
+ this.count = function () {
34
+ self.counter++;
35
+ };
36
+ this.add = function (add) {
37
+ for (var i = 0; i < arguments.length; i++) {
38
+ self.counter += arguments[i];
39
+ }
40
+ };
41
+ });
42
+ describe("simple", function () {
43
+ it("works with option", function () {
44
+ var moduleName = getName();
45
+ defineOptionModule(moduleName, this);
46
+ expect(this.counter).toEqual(1);
47
+ EasyGem.loadModule(moduleName, 5);
48
+ expect(this.counter).toEqual(6);
49
+ });
50
+ it("works with callback", function () {
51
+ var moduleName = getName();
52
+ defineCallbackModule(moduleName, this);
53
+ expect(this.counter).toEqual(1);
54
+ EasyGem.loadModule(moduleName, function (module) {
55
+ module.add(5);
56
+ });
57
+ expect(this.counter).toEqual(6);
58
+ });
59
+ it("works with multiple options", function () {
60
+ var moduleName = getName();
61
+ defineOptionModule(moduleName, this);
62
+ expect(this.counter).toEqual(1);
63
+ EasyGem.loadModule(moduleName, 5, 9);
64
+ expect(this.counter).toEqual(15);
65
+ });
66
+ it("works with multiple options - loadModules", function () {
67
+ var moduleName = getName();
68
+ defineOptionModule(moduleName, this);
69
+ expect(this.counter).toEqual(1);
70
+ EasyGem.loadModules([moduleName], 5, 9);
71
+ expect(this.counter).toEqual(15);
72
+ });
73
+ });
74
+ describe("complex", function () {
75
+ describe("handle define after request", function () {
76
+ it("option", function () {
77
+ var moduleName = getName();
78
+ expect(this.counter).toEqual(1);
79
+ EasyGem.loadModule(moduleName, 8);
80
+ expect(this.counter).toEqual(1);
81
+ defineOptionModule(moduleName, this);
82
+ resolveModules();
83
+ expect(this.counter).toEqual(9);
84
+ });
85
+ it("callback", function () {
86
+ var moduleName = getName();
87
+ expect(this.counter).toEqual(1);
88
+ EasyGem.loadModule(moduleName, function (module) {
89
+ module.add(3);
90
+ });
91
+ expect(this.counter).toEqual(1);
92
+ defineCallbackModule(moduleName, this);
93
+ resolveModules();
94
+ expect(this.counter).toEqual(4);
95
+ });
96
+ });
97
+ describe("parts", function () {
98
+ it("define first", function () {
99
+ var moduleName = getName();
100
+ var self = this;
101
+ EasyGem.module.part(moduleName, [], function () {
102
+ this.add = function (option) {
103
+ self.add(option);
104
+ }
105
+ });
106
+ EasyGem.module.part(moduleName, function () {
107
+ this.addDouble = function (option) {
108
+ self.add(option * 2);
109
+ }
110
+ });
111
+ expect(this.counter).toEqual(1);
112
+ EasyGem.loadModule(moduleName, function (module) {
113
+ module.add(3);
114
+ module.addDouble(2);
115
+ });
116
+ expect(this.counter).toEqual(8);
117
+ });
118
+ it("request first", function () {
119
+ var moduleName = getName();
120
+ var self = this;
121
+ EasyGem.loadModule(moduleName, function (module) {
122
+ module.add(3);
123
+ module.addDouble(2);
124
+ });
125
+ expect(this.counter).toEqual(1);
126
+ EasyGem.module.part(moduleName, [], function () {
127
+ this.add = function (option) {
128
+ self.add(option);
129
+ }
130
+ });
131
+ expect(this.counter).toEqual(1);
132
+ EasyGem.module.part(moduleName, function () {
133
+ this.addDouble = function (option) {
134
+ self.add(option * 2);
135
+ }
136
+ });
137
+ resolveModules();
138
+ expect(this.counter).toEqual(8);
139
+ });
140
+ });
141
+ it("handle complex tree", function () {
142
+ var moduleName = getName();
143
+ var subModuleName1 = getName();
144
+ var subModuleName2 = getName();
145
+ EasyGem.module.module(moduleName, [subModuleName1, subModuleName2], function (sub1, sub2) {
146
+ this.sub1 = sub1;
147
+ this.sub2 = sub2;
148
+ });
149
+ expect(this.counter).toEqual(1);
150
+ EasyGem.loadModule(moduleName, function (module) {
151
+ module.sub1(2);
152
+ module.sub2.add(3);
153
+ });
154
+ resolveModules();
155
+ expect(this.counter).toEqual(1);
156
+ defineOptionModule(subModuleName1, this);
157
+ resolveModules();
158
+ expect(this.counter).toEqual(1);
159
+ defineCallbackModule(subModuleName2, this);
160
+ resolveModules();
161
+ expect(this.counter).toEqual(6);
162
+ });
163
+ });
164
+ });
@@ -1,4 +1,4 @@
1
- REDMINE_EXTENSIONS = {
1
+ window.REDMINE_EXTENSIONS = {
2
2
 
3
3
  toggleDiv: function (el_or_id) {
4
4
  var el;
@@ -4,7 +4,7 @@
4
4
  <%= render "easy_settings/#{@plugin.id}", easy_settings: @easy_settings, settings: @settings, form: f %>
5
5
 
6
6
  <div class="form-actions">
7
- <%= f.submit l(:button_update_easy_settings), class: 'button-1' %>
7
+ <%= f.submit l(:button_update_easy_settings), class: 'button-positive' %>
8
8
 
9
9
  <% if params[:back_url].present? %>
10
10
  <%= link_to l(:button_back), params[:back_url], class: 'button' %>
@@ -0,0 +1,11 @@
1
+ class RemoveForeignKeyFromEasySettings < RedmineExtensions::Migration
2
+ def up
3
+ begin
4
+ remove_foreign_key :easy_settings, :projects
5
+ rescue # rails 5 - if foreign_key_exists? :easy_settings, :projects
6
+ end
7
+ end
8
+
9
+ def down
10
+ end
11
+ end
@@ -1,5 +1,5 @@
1
- api.array :<%= model_name_pluralize_underscored %>, api_meta(total_count: @entity_count, offset: @offset, limit: @limit) do
2
- @entities.each do |<%= model_name_underscored %>|
3
- render_api_<%= model_name_underscored %>(api, <%= model_name_underscored %>)
4
- end
5
- end
1
+ api.array :<%= model_name_pluralize_underscored %>, api_meta(total_count: @entity_count, offset: @offset, limit: @limit) do
2
+ @entities.each do |<%= model_name_underscored %>|
3
+ render_api_<%= model_name_underscored %>(api, <%= model_name_underscored %>)
4
+ end
5
+ end
@@ -1 +1 @@
1
- <h1><%%= link_to(@<%= model_name_underscored %>.to_s, @<%= model_name_underscored %>_url) %></h1>
1
+ <h1><%%= link_to(@<%= model_name_underscored %>.to_s, @<%= model_name_underscored %>_url) %></h1>
@@ -1,2 +1,2 @@
1
- <%%= @<%= model_name_underscored %>.to_s %>
2
- <%%= @<%= model_name_underscored %>_url %>
1
+ <%%= @<%= model_name_underscored %>.to_s %>
2
+ <%%= @<%= model_name_underscored %>_url %>
@@ -1,2 +1,2 @@
1
- <%%= @<%= model_name_underscored %>.to_s %>
2
- <%%= @<%= model_name_underscored %>_url %>
1
+ <%%= @<%= model_name_underscored %>.to_s %>
2
+ <%%= @<%= model_name_underscored %>_url %>
@@ -1,13 +1,13 @@
1
- <% if project? %>
2
- resources :projects do
3
- resources :<%= model_name_pluralize_underscored %>
4
- end
5
- <% end %>
6
- resources :<%= model_name_pluralize_underscored %> do
7
- collection do
8
- get 'autocomplete'
9
- get 'bulk_edit'
10
- post 'bulk_update'
11
- get 'context_menu'
12
- end
1
+ <% if project? %>
2
+ resources :projects do
3
+ resources :<%= model_name_pluralize_underscored %>
4
+ end
5
+ <% end %>
6
+ resources :<%= model_name_pluralize_underscored %> do
7
+ collection do
8
+ get 'autocomplete'
9
+ get 'bulk_edit'
10
+ post 'bulk_update'
11
+ get 'context_menu'
12
+ end
13
13
  end
@@ -4,9 +4,15 @@ module EasySettings
4
4
  attr_reader :errors
5
5
 
6
6
  def self.from_params(raw_params, project: nil, prefix: nil)
7
- if !raw_params.is_a?(Hash) && !raw_params.is_a?(ActionController::Parameters)
7
+ case raw_params
8
+ when Hash
9
+ # OK
10
+ when ActionController::Parameters
11
+ raw_params = raw_params.to_unsafe_h
12
+ else
8
13
  raw_params = {}
9
14
  end
15
+
10
16
  new(raw_params, project, prefix)
11
17
  end
12
18
 
@@ -57,7 +57,7 @@ module RedmineExtensions
57
57
 
58
58
  # include helpers
59
59
  initializer 'redmine_extensions.rails_patching', before: :load_config_initializers do |app|
60
- ActiveSupport.on_load :action_controller do
60
+ ActiveSupport.on_load(Rails.version.start_with?('5') ? :action_controller_base : :action_controller) do
61
61
  helper RedmineExtensions::ApplicationHelper
62
62
  # helper RedmineExtensions::EasyQueryHelper
63
63
  end
@@ -1,3 +1,3 @@
1
1
  module RedmineExtensions
2
- VERSION = '0.2.14'
2
+ VERSION = '0.2.16'
3
3
  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.2.14
4
+ version: 0.2.16
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: 2018-08-13 00:00:00.000000000 Z
11
+ date: 2019-02-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -160,6 +160,7 @@ files:
160
160
  - app/assets/javascripts/redmine_extensions/jasmine_lib/jasmine_lib.js
161
161
  - app/assets/javascripts/redmine_extensions/jasmine_tests/extend.js
162
162
  - app/assets/javascripts/redmine_extensions/jasmine_tests/jasmine_tests.js
163
+ - app/assets/javascripts/redmine_extensions/jasmine_tests/modules.js
163
164
  - app/assets/javascripts/redmine_extensions/jquery.entityarray.js
164
165
  - app/assets/javascripts/redmine_extensions/redmine_extensions.js
165
166
  - app/assets/javascripts/redmine_extensions/render_polyfill.js
@@ -195,6 +196,7 @@ files:
195
196
  - config/routes.rb
196
197
  - db/migrate/20150705172511_create_easy_settings.rb
197
198
  - db/migrate/20160519161300_create_entity_assignments.rb
199
+ - db/migrate/20190206121100_remove_foreign_key_from_easy_settings.rb
198
200
  - lib/generators/redmine_extensions/entity/USAGE
199
201
  - lib/generators/redmine_extensions/entity/entity_generator.rb
200
202
  - lib/generators/redmine_extensions/entity/templates/_form.html.erb.erb
@@ -312,23 +314,23 @@ required_rubygems_version: !ruby/object:Gem::Requirement
312
314
  version: '0'
313
315
  requirements: []
314
316
  rubyforge_project:
315
- rubygems_version: 2.6.7
317
+ rubygems_version: 2.7.7
316
318
  signing_key:
317
319
  specification_version: 4
318
320
  summary: Redmine Extensions is set of usefull features for Redmine. Main focus is
319
321
  on development helpers, but many users can find it helpfull
320
322
  test_files:
323
+ - spec/rails_helper.rb
321
324
  - spec/factories/easy_queries.rb
325
+ - spec/factories/trackers.rb
326
+ - spec/factories/users.rb
322
327
  - spec/factories/easy_settings.rb
328
+ - spec/factories/time_entries.rb
323
329
  - spec/factories/issues.rb
324
330
  - spec/factories/projects.rb
325
- - spec/factories/time_entries.rb
326
- - spec/factories/trackers.rb
327
- - spec/factories/users.rb
328
- - spec/features/autocomplete_spec.rb
329
- - spec/features/jasmine_spec.rb
331
+ - spec/support/plugin_generator.rb
330
332
  - spec/models/easy_setting_spec.rb
331
- - spec/presenters/easy_settings/params_wrapper_spec.rb
332
- - spec/rails_helper.rb
333
333
  - spec/spec_helper.rb
334
- - spec/support/plugin_generator.rb
334
+ - spec/presenters/easy_settings/params_wrapper_spec.rb
335
+ - spec/features/autocomplete_spec.rb
336
+ - spec/features/jasmine_spec.rb