redmine_extensions 0.3.7 → 0.4.0.beta
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 +4 -4
- data/app/assets/javascripts/redmine_extensions/redmine_extensions.js +10 -33
- data/app/helpers/redmine_extensions/application_helper.rb +8 -10
- data/app/models/easy_setting.rb +1 -1
- data/app/presenters/redmine_extensions/easy_setting_presenter.rb +1 -1
- data/lib/generators/redmine_extensions/entity/entity_generator.rb +2 -2
- data/lib/generators/redmine_extensions/entity/templates/_form.html.erb.erb +27 -24
- data/lib/generators/redmine_extensions/entity/templates/_list.html.erb.erb +48 -47
- data/lib/generators/redmine_extensions/entity/templates/_sidebar.html.erb.erb +8 -8
- data/lib/generators/redmine_extensions/entity/templates/context_menu.html.erb.erb +10 -11
- data/lib/generators/redmine_extensions/entity/templates/edit.html.erb.erb +3 -3
- data/lib/generators/redmine_extensions/entity/templates/edit.js.erb.erb +4 -4
- data/lib/generators/redmine_extensions/entity/templates/index.api.rsb.erb +2 -2
- data/lib/generators/redmine_extensions/entity/templates/index.html.erb.erb +2 -2
- data/lib/generators/redmine_extensions/entity/templates/index.js.erb.erb +2 -2
- data/lib/generators/redmine_extensions/entity/templates/new.html.erb.erb +4 -4
- data/lib/generators/redmine_extensions/entity/templates/new.js.erb.erb +4 -4
- data/lib/generators/redmine_extensions/entity/templates/show.html.erb.erb +6 -6
- data/lib/generators/redmine_extensions/entity/templates/show.js.erb.erb +2 -2
- data/lib/redmine_extensions/easy_query_helpers/outputs.rb +2 -2
- data/lib/redmine_extensions/easy_settings/mapper.rb +1 -1
- data/lib/redmine_extensions/engine.rb +8 -6
- data/lib/redmine_extensions/migration.rb +1 -1
- data/lib/redmine_extensions/patch_manager.rb +5 -13
- data/lib/redmine_extensions/version.rb +1 -1
- data/spec/features/autocomplete_spec.rb +2 -2
- metadata +8 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 186ecf1e1604893d9fda643e2b589dbada90b4319c0da5d7a5c2c0f3c53eb176
|
4
|
+
data.tar.gz: f956c9668a5926ba5012902dfb2a1c88d2dd020f7ea06428310e3ef3963e9cff
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ac84a447270e5d19538c99c5fc6d4dcd95ac936de8645c179ebd497d27d09ff65f2def4d24ee5f1b80aa9ac4d78289feca73edfe1242ac94d4a136e03dd50804
|
7
|
+
data.tar.gz: ca999dfd768ba7df0f23f45f5508136eeebd4b09fdef1a92383ec26d0c4d6e3d950252b420913e804eafde49498b00e55122773f490dfce1bb4b53a6de8ea7a4
|
@@ -88,9 +88,9 @@ EasyGem.schedule.require(function () {
|
|
88
88
|
},
|
89
89
|
activate_on_input_click: true,
|
90
90
|
load_immediately: false,
|
91
|
-
show_toggle_button: true,
|
92
91
|
select_first_value: true,
|
93
|
-
autocomplete_options: {}
|
92
|
+
autocomplete_options: {},
|
93
|
+
multiselectOnChange: null // onchange of multiselect input function
|
94
94
|
},
|
95
95
|
|
96
96
|
_create: function () {
|
@@ -102,7 +102,7 @@ EasyGem.schedule.require(function () {
|
|
102
102
|
if (Array.isArray(this.options.source)) {
|
103
103
|
this.options.preload = true;
|
104
104
|
this._initData(this.options.source);
|
105
|
-
} else if (this.options.preload && this.options.load_immediately)
|
105
|
+
} else if ( (this.options.preload || this.options.select_first_value) && this.options.load_immediately ) {
|
106
106
|
this.load();
|
107
107
|
} else if (this.selectedValues) {
|
108
108
|
this.setValue(this.selectedValues);
|
@@ -119,9 +119,6 @@ EasyGem.schedule.require(function () {
|
|
119
119
|
this.valueElement = $('<span></span>');
|
120
120
|
this.tag.after(this.valueElement);
|
121
121
|
|
122
|
-
if (this.options.show_toggle_button)
|
123
|
-
this._createToggleButton();
|
124
|
-
|
125
122
|
this.valueElement.entityArray({
|
126
123
|
inputNames: this.inputName,
|
127
124
|
afterRemove: function (entity) {
|
@@ -138,31 +135,11 @@ EasyGem.schedule.require(function () {
|
|
138
135
|
this.element.css('margin-right', 0);
|
139
136
|
}
|
140
137
|
},
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
var $elem = $(this);
|
147
|
-
evt.preventDefault();
|
148
|
-
that.load(function () {
|
149
|
-
var select = $('<select>').prop('multiple', true).prop('size', 5).prop('name', that.inputName);
|
150
|
-
var option;
|
151
|
-
$.each(that.possibleValues, function (i, v) {
|
152
|
-
option = $('<option>').prop('value', v.id).text(v.value);
|
153
|
-
option.prop('selected', that.getValue().indexOf(v.id) > -1);
|
154
|
-
select.append(option);
|
155
|
-
});
|
156
|
-
var $container = $elem.closest('.easy-multiselect-tag-container');
|
157
|
-
$container.find(':input').prop('disabled', true);
|
158
|
-
$container.children().hide();
|
159
|
-
$container.append(select);
|
160
|
-
that.valueElement = select;
|
161
|
-
that.expanded = true;
|
162
|
-
});
|
163
|
-
});
|
164
|
-
this.element.parent().addClass('input-append');
|
165
|
-
this.element.after(this.link_ac_toggle);
|
138
|
+
setMultiselectOnChange: function (fn) {
|
139
|
+
this.options.multiselectOnChange = fn;
|
140
|
+
},
|
141
|
+
multiselectOnChange: function(select, fn) {
|
142
|
+
if (fn) select.on("change", fn);
|
166
143
|
},
|
167
144
|
|
168
145
|
_createAutocomplete: function () {
|
@@ -278,7 +255,7 @@ EasyGem.schedule.require(function () {
|
|
278
255
|
this.valuesLoaded = true;
|
279
256
|
|
280
257
|
this.selectedValues = this.selectedValues ? this.selectedValues : [];
|
281
|
-
if (this.selectedValues.length === 0 && this.options.
|
258
|
+
if (this.selectedValues.length === 0 && this.options.select_first_value && this.possibleValues.length > 0) {
|
282
259
|
this.selectedValues.push(this.possibleValues[0]['id']);
|
283
260
|
}
|
284
261
|
|
@@ -373,7 +350,7 @@ EasyGem.schedule.require(function () {
|
|
373
350
|
for (var i = values.length - 1; i >= 0; i--) {
|
374
351
|
if (values[i] instanceof Object && !Array.isArray(values[i]) && values[i] !== null) {
|
375
352
|
selected.push(values[i]);
|
376
|
-
} else if (this.options.preload) {
|
353
|
+
} else if (this.options.preload || this.options.select_first_value) {
|
377
354
|
var that = this;
|
378
355
|
if (!Array.isArray(that.possibleValues))
|
379
356
|
return;
|
@@ -20,7 +20,7 @@ module RedmineExtensions
|
|
20
20
|
else
|
21
21
|
presenter = RedmineExtensions::BasePresenter.present(model, self, options)
|
22
22
|
end
|
23
|
-
if
|
23
|
+
if block
|
24
24
|
yield presenter
|
25
25
|
else
|
26
26
|
presenter
|
@@ -110,7 +110,7 @@ module RedmineExtensions
|
|
110
110
|
|
111
111
|
def late_javascript_tag(content_or_options_with_block = nil, html_options = {}, &block)
|
112
112
|
content =
|
113
|
-
if
|
113
|
+
if block
|
114
114
|
html_options = content_or_options_with_block if content_or_options_with_block.is_a?(Hash)
|
115
115
|
capture(&block)
|
116
116
|
else
|
@@ -183,8 +183,8 @@ module RedmineExtensions
|
|
183
183
|
|
184
184
|
def container_class
|
185
185
|
s = (@container_class.presence || css_classes[:container]).to_s
|
186
|
-
s
|
187
|
-
s
|
186
|
+
s += ' collapsible' if collapsible?
|
187
|
+
s += ' collapsed' if collapsed?
|
188
188
|
|
189
189
|
s
|
190
190
|
end
|
@@ -264,7 +264,6 @@ module RedmineExtensions
|
|
264
264
|
# * +load_immediately+ - tells if values should be loaded immediatelly after page loaded, or wait for first use of the field.
|
265
265
|
# Warning! if this option is false, selected values passed in first format will be ignored till it is loaded.
|
266
266
|
# Please use second format for proper functionality.
|
267
|
-
# * +show_toggle_button+ - only valid with <tt>multiple: true, preload: true</tt> options set. Shows toggle button to expand select to the multiselect tag.
|
268
267
|
# * +select_first_value+ - if selectd_values are empty, with this option first available value will be selected.
|
269
268
|
# Available only with <tt>preload: true</tt> option.
|
270
269
|
# With <tt>load_immediately: false</tt> it will appear kinda weird for user because it will select the value after user starts to interact with input.
|
@@ -272,7 +271,7 @@ module RedmineExtensions
|
|
272
271
|
# * +rootElement+ - Has sence only if jsonpath is used for available values. It tells if the json response has values wrapped under root element.
|
273
272
|
# For response like <tt>{projects: [[<name>, <id>], [<name2>, <id2>]]}</tt> user option <tt>rootElement: 'projects'</tt>
|
274
273
|
def autocomplete_field_tag(name, jsonpath_or_array, selected_values, options = {})
|
275
|
-
options.reverse_merge!({select_first_value: false,
|
274
|
+
options.reverse_merge!({select_first_value: false, load_immediately: false, preload: true, multiple: true, combo: false})
|
276
275
|
options[:id] ||= sanitize_to_id(name)
|
277
276
|
|
278
277
|
selected_values ||= []
|
@@ -284,8 +283,8 @@ module RedmineExtensions
|
|
284
283
|
end
|
285
284
|
|
286
285
|
content_tag(:span, :class => 'easy-multiselect-tag-container') do
|
287
|
-
|
288
|
-
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},
|
286
|
+
search_field_tag('', '', (options[:html_options] || {}).merge(id: options[:id])) +
|
287
|
+
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} });")
|
289
288
|
end
|
290
289
|
end
|
291
290
|
|
@@ -297,13 +296,12 @@ module RedmineExtensions
|
|
297
296
|
# HTML options can be passed as a hash with +html_options+. These options will be passed to the input element.
|
298
297
|
#
|
299
298
|
# ==== Examples
|
300
|
-
# autocomplete_field(:issue, :tag_ids, Tag.all.pluck(:name, :id), multiple: true
|
299
|
+
# autocomplete_field(:issue, :tag_ids, Tag.all.pluck(:name, :id), multiple: true)
|
301
300
|
# # => <span class="easy-multiselect-tag-container"> \
|
302
301
|
# <input type="text" id="issue_tags" /> \
|
303
302
|
# <button type="button" tabindex="-1" class="..." role="button" ...>
|
304
303
|
# <span class="ui-button-icon-primary ui-icon ui-icon-triangle-1-s"></span><span class="ui-button-text"> </span>
|
305
304
|
# </button>
|
306
|
-
# <a class="icon icon-add clear-link"></a> # toggle button to the multiselect tag from show_toggle_button option
|
307
305
|
# ...(wraping service tags)
|
308
306
|
# <input type="hidden" name="issue[tag_ids][]" value="#{@issue.tag_ids.first}" />
|
309
307
|
# <input type="hidden" name="issue[tag_ids][]" value="#{@issue.tag_ids.second}" />
|
data/app/models/easy_setting.rb
CHANGED
@@ -119,7 +119,7 @@ module RedmineExtensions
|
|
119
119
|
end
|
120
120
|
|
121
121
|
def method_missing(meth, *attrs)
|
122
|
-
if @plugin && @plugin.settings[:easy_settings] && @plugin.settings[:easy_settings].
|
122
|
+
if @plugin && @plugin.settings[:easy_settings] && @plugin.settings[:easy_settings].key?(meth.to_sym)
|
123
123
|
EasySetting.value(prefix+meth.to_s, project_id)
|
124
124
|
else
|
125
125
|
super
|
@@ -385,7 +385,7 @@ module RedmineExtensions
|
|
385
385
|
end
|
386
386
|
|
387
387
|
def name_column
|
388
|
-
'name' if string_columns.
|
388
|
+
'name' if string_columns.key?('name')
|
389
389
|
string_columns.keys.first
|
390
390
|
end
|
391
391
|
|
@@ -394,7 +394,7 @@ module RedmineExtensions
|
|
394
394
|
end
|
395
395
|
|
396
396
|
def description_column
|
397
|
-
'description' if text_columns.
|
397
|
+
'description' if text_columns.key?('description')
|
398
398
|
text_columns.keys.first
|
399
399
|
end
|
400
400
|
|
@@ -1,38 +1,38 @@
|
|
1
1
|
<%%= fields_for :<%= model_name_underscored %>, <%= model_name_underscored %> do |f| %>
|
2
2
|
<%- if project? -%>
|
3
3
|
<%% if <%= model_name_underscored %>.safe_attribute?('project_id') && !@project %>
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
<p>
|
5
|
+
<%%= f.label :project_id, ::<%= model_name %>.human_attribute_name(:project_id) %>
|
6
|
+
<%%= f.select :project_id, Project.allowed_to(:manage_<%= model_name_pluralize_underscored %>).collect{|x| [x.name, x.id]}, include_blank: true %>
|
7
|
+
</p>
|
8
8
|
<%% end %>
|
9
9
|
<%- end -%>
|
10
10
|
<%- safe_columns.each do |column_name, column_options| -%>
|
11
11
|
<%% if <%= model_name_underscored %>.safe_attribute?('<%= column_name %>') %>
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
12
|
+
<p>
|
13
|
+
<%%= f.label :<%= column_name %>, ::<%= model_name %>.human_attribute_name(:<%= column_name %>) %>
|
14
|
+
<%- if column_options[:query_type] == 'string' || column_options[:query_type] == 'integer' -%>
|
15
|
+
<%%= f.text_field :<%= column_name %> %>
|
16
|
+
<%- elsif column_options[:query_type] == 'list' || column_options[:query_type] == 'list_optional' -%>
|
17
|
+
<%%= f.select :<%= column_name %>, <%= column_options[:class] %>.all.collect{|x| [x.<%= column_options[:list_class_name] %>, x.id]}.sort, include_blank: true %>
|
18
|
+
<%- elsif column_options[:query_type] == 'text' -%>
|
19
|
+
<%%= f.text_area :<%= column_name %>, cols: 60, rows: (<%= model_name_underscored %>.<%= column_name %>.blank? ? 10 : [[10, <%= model_name_underscored %>.<%= column_name %>.length / 50].max, 100].min), accesskey: accesskey(:edit), class: 'wiki-edit' %>
|
20
|
+
<%%= wikitoolbar_for '<%= model_name_underscored %>_<%= column_name %>' %>
|
21
|
+
<%- elsif column_options[:query_type] == 'boolean' -%>
|
22
|
+
<%%= f.radio_button :<%= column_name %>, false %>
|
23
|
+
<%- else -%>
|
24
|
+
<%%= f.text_field :<%= column_name %> %>
|
25
|
+
<%- end -%>
|
26
|
+
</p>
|
27
27
|
<%% end %>
|
28
28
|
<%- end -%>
|
29
29
|
<% associations.each do |assoc| %>
|
30
30
|
<%- next if assoc[1][:type] == 'has_many' -%>
|
31
31
|
<% association_name = assoc[0] %>
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
32
|
+
<p>
|
33
|
+
<%%= f.label l(:label_<%= association_name %>) %>
|
34
|
+
<%%= f.select :<%= association_name %>_id, <%= association_name.camelcase %>.visible.sorted.map{ |<%= association_name %>| [<%= association_name %>.to_s, <%= association_name %>.id]} %>
|
35
|
+
</p>
|
36
36
|
<% end %>
|
37
37
|
<%- if acts_as_customizable? -%>
|
38
38
|
<%% custom_field_values = <%= model_name_underscored %>.visible_custom_field_values %>
|
@@ -43,6 +43,9 @@
|
|
43
43
|
<%% end %>
|
44
44
|
<%- end -%>
|
45
45
|
<%- if acts_as_attachable? -%>
|
46
|
-
<p id="attachments_form"
|
46
|
+
<p id="attachments_form">
|
47
|
+
<label><%%= l(:label_attachment_plural) %></label>
|
48
|
+
<%%= render partial: 'attachments/form', locals: { container: <%= model_name_underscored %> } %>
|
49
|
+
</p>
|
47
50
|
<%- end -%>
|
48
51
|
<%% end %>
|
@@ -1,5 +1,5 @@
|
|
1
|
-
<%%= form_tag({}, :
|
2
|
-
<%%= hidden_field_tag 'back_url', url_for(:
|
1
|
+
<%%= form_tag({}, data: {cm_url: context_menu_<%= model_name_pluralize_underscored %>_path}) do %>
|
2
|
+
<%%= hidden_field_tag 'back_url', url_for(params: request.query_parameters), id: nil %>
|
3
3
|
<div class="autoscroll">
|
4
4
|
<table class="list odd-even entities">
|
5
5
|
<thead>
|
@@ -15,55 +15,56 @@
|
|
15
15
|
</tr>
|
16
16
|
</thead>
|
17
17
|
<tbody>
|
18
|
-
<%% grouped_query_results(entities, @query) do |entity, group_name, group_count, group_totals|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
<%% end %>
|
34
|
-
<tr id="entity_id_<%%= entity.id %>" class="entity <%%= cycle('odd', 'even') %> hascontextmenu">
|
35
|
-
<td class="checkbox hide-when-print"><%%= check_box_tag("ids[]", entity.id, false, id: nil) %></td>
|
36
|
-
<%% @query.inline_columns.each do |column| %>
|
37
|
-
<%%= content_tag('td', column_content(column, entity), class: column.css_classes) %>
|
18
|
+
<%% grouped_query_results(entities, @query) do |entity, group_name, group_count, group_totals| %>
|
19
|
+
<%% if group_name %>
|
20
|
+
<%% reset_cycle %>
|
21
|
+
<tr class="group open">
|
22
|
+
<td colspan="<%%= @query.inline_columns.size + 2 %>">
|
23
|
+
<span class="expander" onclick="toggleRowGroup(this);"> </span>
|
24
|
+
<span class="name"><%%= group_name %></span>
|
25
|
+
<%% if group_count %>
|
26
|
+
<span class="count"><%%= group_count %></span>
|
27
|
+
<%% end %>
|
28
|
+
<span class="totals"><%%= group_totals %></span>
|
29
|
+
<%%= link_to_function("#{l(:button_collapse_all)}/#{l(:button_expand_all)}",
|
30
|
+
'toggleAllRowGroups(this)', class: 'toggle-all') %>
|
31
|
+
</td>
|
32
|
+
</tr>
|
38
33
|
<%% end %>
|
39
|
-
<
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
<tr class="<%%= current_cycle %>">
|
55
|
-
<td colspan="<%%= @query.inline_columns.size + 1 %>" class="<%%= column.css_classes %>">
|
56
|
-
<%% if query.block_columns.count > 1 %>
|
57
|
-
<span><%%= column.caption %></span>
|
34
|
+
<tr id="entity_id_<%%= entity.id %>" class="entity <%%= cycle('odd', 'even') %> hascontextmenu">
|
35
|
+
<td class="checkbox hide-when-print"><%%= check_box_tag('ids[]', entity.id, false, id: nil) %></td>
|
36
|
+
<%% @query.inline_columns.each do |column| %>
|
37
|
+
<%%= content_tag('td', column_content(column, entity), class: column.css_classes) %>
|
38
|
+
<%% end %>
|
39
|
+
<td class="buttons">
|
40
|
+
<%% if entity.editable_by?(User.current) %>
|
41
|
+
<%%= link_to l(:button_edit), edit_<%= model_name_underscored %>_path(entity),
|
42
|
+
title: l(:button_edit),
|
43
|
+
class: 'icon-only icon-edit' %>
|
44
|
+
<%%= link_to l(:button_delete), <%= model_name_underscored %>_path(entity),
|
45
|
+
data: {confirm: l(:text_are_you_sure)},
|
46
|
+
method: :delete,
|
47
|
+
title: l(:button_delete),
|
48
|
+
class: 'icon-only icon-del' %>
|
58
49
|
<%% end %>
|
59
|
-
<%%= text %>
|
60
50
|
</td>
|
61
51
|
</tr>
|
62
|
-
<%%
|
63
|
-
|
64
|
-
|
52
|
+
<%% @query.block_columns.each do |column| %>
|
53
|
+
<%% if (text = column_content(column, entity)) && text.present? %>
|
54
|
+
<tr class="<%%= current_cycle %>">
|
55
|
+
<td colspan="<%%= @query.inline_columns.size + 1 %>" class="<%%= column.css_classes %>">
|
56
|
+
<%% if query.block_columns.count > 1 %>
|
57
|
+
<span><%%= column.caption %></span>
|
58
|
+
<%% end %>
|
59
|
+
<%%= text %>
|
60
|
+
</td>
|
61
|
+
</tr>
|
62
|
+
<%% end %>
|
63
|
+
<%% end %>
|
64
|
+
<%% end %>
|
65
65
|
</tbody>
|
66
66
|
</table>
|
67
67
|
</div>
|
68
|
-
|
69
|
-
|
68
|
+
<%% end %>
|
69
|
+
|
70
|
+
<%%= context_menu %>
|
@@ -1,9 +1,9 @@
|
|
1
1
|
<ul>
|
2
|
-
<%% if @<%= model_name_underscored %> && !@<%= model_name_underscored %>.new_record? %>
|
3
|
-
|
4
|
-
<%% end %>
|
5
|
-
<%% if @<%= model_name_underscored %>.nil? %>
|
6
|
-
|
7
|
-
<%% end %>
|
8
|
-
|
9
|
-
</ul>
|
2
|
+
<%% if @<%= model_name_underscored %> && !@<%= model_name_underscored %>.new_record? %>
|
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
|
+
<%% end %>
|
5
|
+
<%% if @<%= model_name_underscored %>.nil? %>
|
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
|
+
<%% end %>
|
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')) %>
|
9
|
+
</ul>
|
@@ -1,21 +1,20 @@
|
|
1
1
|
<ul>
|
2
|
-
<%% if @<%= model_name_underscored %>
|
3
|
-
|
4
|
-
<%% end %>
|
5
|
-
<%% if @safe_attributes.include? 'status'
|
2
|
+
<%% if @<%= model_name_underscored %> %>
|
3
|
+
<li><%%= context_menu_link l(:button_edit), edit_<%= model_name_underscored %>_path(@<%= model_name_underscored %>), class: 'icon icon-edit', disabled: !@can[:edit] %></li>
|
4
|
+
<%% end %>
|
5
|
+
<%% if @safe_attributes.include? 'status' %>
|
6
6
|
<li class="folder">
|
7
|
-
<a href="#" class="submenu icon icon-issue-status" onclick="return false;"><%%= l(:field_status)
|
7
|
+
<a href="#" class="submenu icon icon-issue-status" onclick="return false;"><%%= l(:field_status) %></a>
|
8
8
|
<ul>
|
9
|
-
<%% <%= model_name %>.statuses.keys.each do |
|
9
|
+
<%% <%= model_name %>.statuses.keys.each do |status| %>
|
10
10
|
<li>
|
11
|
-
<%%= context_menu_link l("<%= model_name_underscored %>.statuses.#{
|
12
|
-
selected: (@selected[:status] == s), disabled: !@can[:edit], confirm: l(:text_are_you_sure) %>
|
11
|
+
<%%= context_menu_link l("<%= model_name_underscored %>.statuses.#{status}"), bulk_update_<%= model_name_underscored %>_path(id: @<%= model_name_underscored %>_ids, <%= model_name_underscored %>: { status: status }, back_url: @back), method: :put, selected: (@selected[:status] == status), disabled: !@can[:edit], confirm: l(:text_are_you_sure) %>
|
13
12
|
</li>
|
14
|
-
<%% end
|
13
|
+
<%% end %>
|
15
14
|
</ul>
|
16
15
|
</li>
|
17
16
|
<%% end %>
|
18
|
-
<li><%%= context_menu_link l(:button_delete), <%= model_name_underscored %>_path(id: @<%= model_name_underscored %>_ids, back_url: @back), method: :delete, data: {confirm: l(:text_are_you_sure)}, class: 'icon icon-del', disabled: !@can[:delete] %></li>
|
17
|
+
<li><%%= context_menu_link l(:button_delete), <%= model_name_underscored %>_path(id: @<%= model_name_underscored %>_ids, back_url: @back), method: :delete, data: { confirm: l(:text_are_you_sure) }, class: 'icon icon-del', disabled: !@can[:delete] %></li>
|
19
18
|
|
20
|
-
<%%= call_hook(:view_<%= model_name_pluralize_underscored %>_context_menu_end, {<%= model_name_underscored %>: @<%= model_name_underscored %>, <%= model_name_pluralize_underscored %>: @<%= model_name_pluralize_underscored %>, can: @can, back: @back, project: @project}) %>
|
19
|
+
<%%= call_hook(:view_<%= model_name_pluralize_underscored %>_context_menu_end, { <%= model_name_underscored %>: @<%= model_name_underscored %>, <%= model_name_pluralize_underscored %>: @<%= model_name_pluralize_underscored %>, can: @can, back: @back, project: @project }) %>
|
21
20
|
</ul>
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<%%= title l(:heading_<%= model_name_underscored %>_edit) %>
|
2
2
|
|
3
|
-
<%%= form_for([@project, @<%= model_name_underscored %>], html: {multipart: <%= acts_as_attachable? %>, id: '<%= model_name_underscored %>_form', class: 'tabular', remote: request.xhr?}) do |f| %>
|
3
|
+
<%%= form_for([@project, @<%= model_name_underscored %>], html: { multipart: <%= acts_as_attachable? %>, id: '<%= model_name_underscored %>_form', class: 'tabular', remote: request.xhr? }) do |f| %>
|
4
4
|
<%%= error_messages_for @<%= model_name_underscored %> %>
|
5
5
|
|
6
6
|
<div class="box">
|
@@ -15,5 +15,5 @@
|
|
15
15
|
<%% end %>
|
16
16
|
<%% ### PAGE CUSTOMS ########################################################## %>
|
17
17
|
<%% content_for :sidebar do %>
|
18
|
-
<%%= render :
|
19
|
-
<%% end %>
|
18
|
+
<%%= render partial: '<%= model_name_pluralize_underscored %>/sidebar' %>
|
19
|
+
<%% end %>
|
@@ -2,14 +2,14 @@ var modal = $("#ajax-modal");
|
|
2
2
|
modal.html("<%%= j render(template: '<%= model_name_pluralize_underscored %>/edit', formats: [:html]) %>");
|
3
3
|
showModal(modal.attr("id"));
|
4
4
|
var submitButton = {
|
5
|
-
text:"<%%=j l(:button_update)
|
6
|
-
title:"<%%=j l(:button_update)
|
5
|
+
text:"<%%=j l(:button_update) %>",
|
6
|
+
title:"<%%=j l(:button_update) %>",
|
7
7
|
click: function() {$(this).find('form').submit()},
|
8
8
|
'class': 'button-positive'
|
9
9
|
};
|
10
10
|
var closeButton = {
|
11
|
-
text: "<%%=j l(:button_close)
|
12
|
-
title: "<%%=j l(:button_close)
|
11
|
+
text: "<%%=j l(:button_close) %>",
|
12
|
+
title: "<%%=j l(:button_close) %>",
|
13
13
|
click: function() {$(this).dialog('close');},
|
14
14
|
'class': 'button'
|
15
15
|
};
|
@@ -1,3 +1,3 @@
|
|
1
1
|
api.array :<%= model_name_pluralize_underscored %>, api_meta(total_count: @entity_count, offset: @offset, limit: @limit) do
|
2
|
-
render(@entities, {api: api})
|
3
|
-
end
|
2
|
+
render(@entities, { api: api })
|
3
|
+
end
|
@@ -4,7 +4,7 @@
|
|
4
4
|
<%%= context_menu context_menu_<%= model_name_pluralize_underscored %>_path(project_id: @project) %>
|
5
5
|
<%% content_for :sidebar do %>
|
6
6
|
<%%= render partial: '<%= model_name_pluralize_underscored %>/sidebar' %>
|
7
|
-
<%%= render partial: 'sidebar/saved_easyqueries_by_type', locals: {query_class: @query.class, project: @project} %>
|
7
|
+
<%%= render partial: 'sidebar/saved_easyqueries_by_type', locals: { query_class: @query.class, project: @project } %>
|
8
8
|
<%% end %>
|
9
9
|
<% else %>
|
10
10
|
<div class="contextual">
|
@@ -27,4 +27,4 @@
|
|
27
27
|
<span class="pagination"><%%= pagination_links_full @entity_pages, @entity_count %></span>
|
28
28
|
<%% end %>
|
29
29
|
<%% end %>
|
30
|
-
<% end %>
|
30
|
+
<% end %>
|
@@ -2,8 +2,8 @@ var modal = $("#ajax-modal");
|
|
2
2
|
modal.html("<%%= j render(template: '<%= model_name_pluralize_underscored %>/index', formats: [:html]) %>");
|
3
3
|
showModal(modal.attr("id"));
|
4
4
|
var closeButton = {
|
5
|
-
text: "<%%=j l(:button_close)
|
6
|
-
title: "<%%=j l(:button_close)
|
5
|
+
text: "<%%=j l(:button_close) %>",
|
6
|
+
title: "<%%=j l(:button_close) %>",
|
7
7
|
click: function() {$(this).dialog('close');},
|
8
8
|
'class': 'button'
|
9
9
|
};
|
@@ -1,10 +1,10 @@
|
|
1
1
|
<%%= title l(:heading_<%= model_name_underscored %>_new) %>
|
2
2
|
|
3
|
-
<%%= form_for([@project, @<%= model_name_underscored %>], html: {multipart: <%= acts_as_attachable? %>, id: '<%= model_name_underscored %>_form', class: 'tabular', remote: request.xhr?}) do |f| %>
|
3
|
+
<%%= form_for([@project, @<%= model_name_underscored %>], html: { multipart: <%= acts_as_attachable? %>, id: '<%= model_name_underscored %>_form', class: 'tabular', remote: request.xhr? }) do |f| %>
|
4
4
|
<%%= error_messages_for @<%= model_name_underscored %> %>
|
5
5
|
|
6
6
|
<div class="box">
|
7
|
-
<%%= render partial: 'form', locals: {<%= model_name_underscored %>: @<%= model_name_underscored %>} %>
|
7
|
+
<%%= render partial: 'form', locals: { <%= model_name_underscored %>: @<%= model_name_underscored %> } %>
|
8
8
|
</div>
|
9
9
|
|
10
10
|
<%% if !request.xhr? %>
|
@@ -15,5 +15,5 @@
|
|
15
15
|
<%% end %>
|
16
16
|
<%% ### PAGE CUSTOMS ########################################################## %>
|
17
17
|
<%% content_for :sidebar do %>
|
18
|
-
<%%= render :
|
19
|
-
<%% end %>
|
18
|
+
<%%= render partial: '<%= model_name_pluralize_underscored %>/sidebar' %>
|
19
|
+
<%% end %>
|
@@ -2,14 +2,14 @@ var modal = $("#ajax-modal");
|
|
2
2
|
modal.html("<%%= j render(template: '<%= model_name_pluralize_underscored %>/new', formats: [:html]) %>");
|
3
3
|
showModal(modal.attr("id"));
|
4
4
|
var submitButton = {
|
5
|
-
text:"<%%=j l(:button_create)
|
6
|
-
title:"<%%=j l(:button_create)
|
5
|
+
text:"<%%=j l(:button_create) %>",
|
6
|
+
title:"<%%=j l(:button_create) %>",
|
7
7
|
click: function() {$(this).find('form').submit()},
|
8
8
|
'class': 'button-positive'
|
9
9
|
};
|
10
10
|
var closeButton = {
|
11
|
-
text: "<%%=j l(:button_close)
|
12
|
-
title: "<%%=j l(:button_close)
|
11
|
+
text: "<%%=j l(:button_close) %>",
|
12
|
+
title: "<%%=j l(:button_close) %>",
|
13
13
|
click: function() {$(this).dialog('close');},
|
14
14
|
'class': 'button'
|
15
15
|
};
|
@@ -22,9 +22,9 @@
|
|
22
22
|
<%% end %>
|
23
23
|
<%- if acts_as_customizable? -%>
|
24
24
|
<hr />
|
25
|
-
<%%= render partial: 'redmine_extensions/custom_field_rows', :
|
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
|
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? %>
|
@@ -38,13 +38,13 @@
|
|
38
38
|
<%% end %>
|
39
39
|
<%- end -%>
|
40
40
|
<%- if acts_as_attachable? -%>
|
41
|
-
<%% if @<%= model_name_underscored %>.attachments.any?
|
41
|
+
<%% if @<%= model_name_underscored %>.attachments.any? %>
|
42
42
|
<hr />
|
43
|
-
<%%= link_to_attachments @<%= model_name_underscored %>, :
|
43
|
+
<%%= link_to_attachments @<%= model_name_underscored %>, thumbnails: true %>
|
44
44
|
<%% end %>
|
45
45
|
<%- end -%>
|
46
46
|
</div>
|
47
47
|
<%% ### PAGE CUSTOMS ########################################################## %>
|
48
48
|
<%% content_for :sidebar do %>
|
49
|
-
<%%= render :
|
50
|
-
<%% end %>
|
49
|
+
<%%= render partial: '<%= model_name_pluralize_underscored %>/sidebar' %>
|
50
|
+
<%% end %>
|
@@ -2,8 +2,8 @@ var modal = $("#ajax-modal");
|
|
2
2
|
modal.html("<%%= j render(template: '<%= model_name_pluralize_underscored %>/show', formats: [:html]) %>");
|
3
3
|
showModal(modal.attr("id"));
|
4
4
|
var closeButton = {
|
5
|
-
text: "<%%=j l(:button_close)
|
6
|
-
title: "<%%=j l(:button_close)
|
5
|
+
text: "<%%=j l(:button_close) %>",
|
6
|
+
title: "<%%=j l(:button_close) %>",
|
7
7
|
click: function() {$(this).dialog('close');},
|
8
8
|
'class': 'button'
|
9
9
|
};
|
@@ -69,12 +69,12 @@ module RedmineExtensions
|
|
69
69
|
end
|
70
70
|
|
71
71
|
def render_edit
|
72
|
-
outputs.map{ |output| output.render_edit }.join
|
72
|
+
outputs.map{ |output| output.render_edit }.join.html_safe
|
73
73
|
end
|
74
74
|
|
75
75
|
def render_data
|
76
76
|
if outputs.any?
|
77
|
-
outputs.map{ |output| output.render_data }.join
|
77
|
+
outputs.map{ |output| output.render_data }.join.html_safe
|
78
78
|
else
|
79
79
|
view_context.l(:label_no_output)
|
80
80
|
end
|
@@ -20,11 +20,13 @@ module RedmineExtensions
|
|
20
20
|
config.eager_load_paths << config.root.join('app', 'models', 'easy_queries')
|
21
21
|
|
22
22
|
initializer 'redmine_extensions.assets' do
|
23
|
-
config.assets
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
23
|
+
if config.respond_to?(:assets)
|
24
|
+
config.assets.precompile << 'redmine_extensions/applications.js'
|
25
|
+
config.assets.precompile << 'redmine_extensions/blocking.js'
|
26
|
+
unless Rails.env.production?
|
27
|
+
config.assets.precompile << 'redmine_extensions/jasmine_lib/jasmine_lib.js'
|
28
|
+
config.assets.precompile << 'redmine_extensions/jasmine.css'
|
29
|
+
end
|
28
30
|
end
|
29
31
|
end
|
30
32
|
|
@@ -61,7 +63,7 @@ module RedmineExtensions
|
|
61
63
|
|
62
64
|
# include helpers
|
63
65
|
initializer 'redmine_extensions.rails_patching', before: :load_config_initializers do |app|
|
64
|
-
ActiveSupport.on_load(Rails
|
66
|
+
ActiveSupport.on_load(Rails::VERSION::MAJOR >= 5 ? :action_controller_base : :action_controller) do
|
65
67
|
helper RedmineExtensions::ApplicationHelper
|
66
68
|
# helper RedmineExtensions::EasyQueryHelper
|
67
69
|
end
|
@@ -57,7 +57,7 @@ module RedmineExtensions
|
|
57
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
|
-
from_location = caller_locations
|
60
|
+
from_location = caller_locations(2..2).first
|
61
61
|
@@patches_locations[patching_module] = from_location.absolute_path
|
62
62
|
end
|
63
63
|
|
@@ -78,7 +78,7 @@ module RedmineExtensions
|
|
78
78
|
end
|
79
79
|
section ||= :others
|
80
80
|
|
81
|
-
raise ArgumentError, "EasyPatchManager->register_patch: The section (#{section}) must be one of x#{@@registered_patches.keys.join(', ')}x " unless @@registered_patches.
|
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
84
|
pcollection = @@registered_patches[section].move_and_get_or_insert( original_klass_to_patch, options )
|
@@ -191,17 +191,13 @@ module RedmineExtensions
|
|
191
191
|
# raise ArgumentError, 'Section order has to be a integer!' unless order.is_a?(Numeric)
|
192
192
|
# @name = name
|
193
193
|
# @order = order
|
194
|
-
@patches_collections =
|
194
|
+
@patches_collections = []
|
195
195
|
@last_order = 0
|
196
196
|
end
|
197
197
|
|
198
198
|
def each(&block)
|
199
199
|
@patches_collections.each do |patch_collection|
|
200
|
-
|
201
|
-
block.call patch_collection
|
202
|
-
else
|
203
|
-
yield patch_collection
|
204
|
-
end
|
200
|
+
yield patch_collection
|
205
201
|
end
|
206
202
|
end
|
207
203
|
|
@@ -335,11 +331,7 @@ module RedmineExtensions
|
|
335
331
|
def each(&block)
|
336
332
|
|
337
333
|
@patches.each do |patch|
|
338
|
-
|
339
|
-
block.call patch
|
340
|
-
else
|
341
|
-
yield patch
|
342
|
-
end
|
334
|
+
yield patch
|
343
335
|
end
|
344
336
|
|
345
337
|
end
|
@@ -3,13 +3,13 @@ RSpec.describe 'autocomplete', type: :feature, js: true, logged: :admin do
|
|
3
3
|
describe 'render' do
|
4
4
|
it 'generate default autocomplete' do
|
5
5
|
visit '/dummy_autocompletes'
|
6
|
-
expect(page).to have_css('input#default[type="
|
6
|
+
expect(page).to have_css('input#default[type="search"]')
|
7
7
|
expect(page).to have_css('input[type="hidden"][name="default"][value="value1"]', visible: false)
|
8
8
|
end
|
9
9
|
|
10
10
|
it 'generate autocomplete_field in form_for' do
|
11
11
|
visit '/dummy_autocompletes'
|
12
|
-
expect(page).to have_css('input#dummy_entities_autocomplete[type="
|
12
|
+
expect(page).to have_css('input#dummy_entities_autocomplete[type="search"]')
|
13
13
|
expect(page).to have_css('input[type="hidden"][name="dummy_entity[array_of_dummies][]"][value="value1"]', visible: false)
|
14
14
|
end
|
15
15
|
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
|
+
version: 0.4.0.beta
|
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: 2021-01-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -19,7 +19,7 @@ dependencies:
|
|
19
19
|
version: '4.2'
|
20
20
|
- - "<"
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: '6'
|
22
|
+
version: '6.2'
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -29,7 +29,7 @@ dependencies:
|
|
29
29
|
version: '4.2'
|
30
30
|
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: '6'
|
32
|
+
version: '6.2'
|
33
33
|
description: Redmine Extensions provide many extended functionalities for Redmine
|
34
34
|
project.
|
35
35
|
email:
|
@@ -204,14 +204,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
204
204
|
requirements:
|
205
205
|
- - ">="
|
206
206
|
- !ruby/object:Gem::Version
|
207
|
-
version: '2.
|
207
|
+
version: '2.5'
|
208
208
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
209
209
|
requirements:
|
210
|
-
- - "
|
210
|
+
- - ">"
|
211
211
|
- !ruby/object:Gem::Version
|
212
|
-
version:
|
212
|
+
version: 1.3.1
|
213
213
|
requirements: []
|
214
|
-
rubygems_version: 3.0.
|
214
|
+
rubygems_version: 3.0.8
|
215
215
|
signing_key:
|
216
216
|
specification_version: 4
|
217
217
|
summary: Redmine Extensions is set of usefull features for Redmine. Main focus is
|