redmine_extensions 0.2.14 → 0.2.16

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
- 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