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 +5 -5
- data/app/assets/javascripts/redmine_extensions/blocking_module.js +95 -25
- data/app/assets/javascripts/redmine_extensions/easy_togglers.js +1 -1
- data/app/assets/javascripts/redmine_extensions/jasmine_lib/jasmine_helper.js +2 -7
- data/app/assets/javascripts/redmine_extensions/jasmine_tests/modules.js +164 -0
- data/app/assets/javascripts/redmine_extensions/redmine_extensions.js +1 -1
- data/app/views/easy_settings/edit.html.erb +1 -1
- data/db/migrate/20190206121100_remove_foreign_key_from_easy_settings.rb +11 -0
- data/lib/generators/redmine_extensions/entity/templates/index.api.rsb.erb +5 -5
- data/lib/generators/redmine_extensions/entity/templates/mail_added.html.erb.erb +1 -1
- data/lib/generators/redmine_extensions/entity/templates/mail_added.text.erb.erb +2 -2
- data/lib/generators/redmine_extensions/entity/templates/mail_updated.text.erb.erb +2 -2
- data/lib/generators/redmine_extensions/entity/templates/routes.rb.erb +12 -12
- data/lib/redmine_extensions/easy_settings/params_wrapper.rb +7 -1
- data/lib/redmine_extensions/engine.rb +1 -1
- data/lib/redmine_extensions/version.rb +1 -1
- metadata +13 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 5d23088d3d0f1dbefea12bcd0ded9bf06067c34f50e3bd4cadd8407e49ca0cfa
|
4
|
+
data.tar.gz: ce1030a05900dd45a6fe3afc959e819ccc5e45bda9ed8f65654dab561140994e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.<
|
7
|
+
/** @type {Array.<OptionWaiter|CallbackWaiter>} */
|
8
8
|
var waiters = [];
|
9
9
|
/** @type {Object.<String,String>} */
|
10
10
|
var urls = {};
|
11
11
|
|
12
|
-
|
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.<
|
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
|
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
|
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
|
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
|
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
|
214
|
-
*
|
215
|
-
*
|
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 {
|
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,
|
224
|
-
|
225
|
-
|
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 {
|
304
|
+
* @param {...*} options - options for module function OR function with module instances as arguments
|
236
305
|
*/
|
237
|
-
EasyGem.loadModule = function (moduleName,
|
238
|
-
|
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
|
-
|
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
|
+
});
|
@@ -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-
|
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' %>
|
@@ -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
|
-
|
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
|
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.
|
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:
|
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.
|
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/
|
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/
|
334
|
+
- spec/presenters/easy_settings/params_wrapper_spec.rb
|
335
|
+
- spec/features/autocomplete_spec.rb
|
336
|
+
- spec/features/jasmine_spec.rb
|