redmine_extensions 0.0.39 → 0.1.01
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 +30 -59
- data/app/controllers/easy_settings_controller.rb +1 -1
- data/app/helpers/redmine_extensions/application_helper.rb +108 -65
- data/app/helpers/redmine_extensions/rendering_helper.rb +5 -0
- data/app/presenters/easy_query_adapter_presenter.rb +50 -0
- data/app/views/common/_collapsible_module_layout.html.erb +13 -0
- data/app/views/easy_entity_assignments/_assignments_container.html.erb +10 -15
- data/app/views/easy_entity_assignments/_query_index.html.erb +2 -10
- data/app/views/easy_queries/_easy_query_tile.html.erb +7 -0
- data/app/views/easy_settings/edit.html.erb +1 -1
- data/config/routes.rb +3 -7
- data/lib/generators/redmine_extensions/entity/templates/_form.html.erb.erb +1 -1
- 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 +7 -7
- data/lib/generators/redmine_extensions/entity/templates/custom_field.rb.erb +7 -7
- data/lib/generators/redmine_extensions/entity/templates/edit.html.erb.erb +16 -16
- data/lib/generators/redmine_extensions/entity/templates/index.api.rsb.erb +5 -5
- data/lib/generators/redmine_extensions/entity/templates/index.html.erb.erb +4 -4
- 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/migration.rb.erb +9 -9
- data/lib/generators/redmine_extensions/entity/templates/new.html.erb.erb +16 -16
- data/lib/generators/redmine_extensions/entity/templates/query.rb.erb +1 -1
- data/lib/generators/redmine_extensions/entity/templates/routes.rb.erb +12 -12
- data/lib/generators/redmine_extensions/entity/templates/show.html.erb.erb +37 -37
- data/lib/redmine_extensions/easy_query_adapter.rb +107 -88
- data/lib/redmine_extensions/easy_query_helpers/outputs.rb +69 -0
- data/lib/redmine_extensions/engine.rb +11 -1
- data/lib/redmine_extensions/query_output.rb +41 -25
- data/lib/redmine_extensions/query_outputs/list_output.rb +14 -0
- data/lib/redmine_extensions/query_outputs/tile_output.rb +19 -0
- data/lib/redmine_extensions/redmine_patches/patches.rb +2 -3
- data/lib/redmine_extensions/version.rb +1 -1
- data/spec/redmine/bin/about +0 -0
- data/spec/redmine/bin/bundle +0 -0
- data/spec/redmine/bin/rails +0 -0
- data/spec/redmine/bin/rake +0 -0
- data/spec/redmine/extra/svn/reposman.rb +0 -0
- data/spec/redmine/public/dispatch.fcgi.example +0 -0
- data/spec/redmine/script/about +0 -0
- data/spec/redmine/script/rails +0 -0
- metadata +1978 -1972
- data/lib/redmine_extensions/query_outputs/table_output.rb +0 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 03e7f631e32d5cbbce9cfd94ab32c76a0e3fb93a
|
4
|
+
data.tar.gz: 5454a96009a0928de22a9c918f487468154f154e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9851babf744466f612e6ac074e5bfb27980e27c33dc8cae48c5d3c7c99793bfdd2f19a9f593b8f994f9518475aa3f4aff49138b1052f7c96a5471d081a7d3f60
|
7
|
+
data.tar.gz: 119f3556b21232044b91a4fb05bcc3f0f7b7d3b08df9c4fd61b18edde70ca13c760091818791066a63539218a5b942f250920d05136a5298713e530be21e460b
|
@@ -340,8 +340,6 @@ window.closeFlashMessage = (function($element){
|
|
340
340
|
this._initData(this.options.source);
|
341
341
|
} else if ( this.options.preload && this.options.load_immediately) {
|
342
342
|
this.load();
|
343
|
-
} else if ( this.selectedValues ) {
|
344
|
-
this.setValue( this.selectedValues );
|
345
343
|
}
|
346
344
|
},
|
347
345
|
|
@@ -389,7 +387,7 @@ window.closeFlashMessage = (function($element){
|
|
389
387
|
select.append(option);
|
390
388
|
});
|
391
389
|
$container = $elem.closest('.easy-multiselect-tag-container');
|
392
|
-
$container.
|
390
|
+
$container.children(':input').prop('disabled', true);
|
393
391
|
$container.children().hide();
|
394
392
|
$container.append(select);
|
395
393
|
that.valueElement = select;
|
@@ -409,7 +407,7 @@ window.closeFlashMessage = (function($element){
|
|
409
407
|
that.load(function(){
|
410
408
|
var matcher = new RegExp($.ui.autocomplete.escapeRegex(request.term), "i");
|
411
409
|
response($.grep(that.possibleValues, function(val, i) {
|
412
|
-
return ( !request.term || matcher.test(val.value)
|
410
|
+
return ( !that.options.multiple || !request.term || matcher.test(val.value));
|
413
411
|
}));
|
414
412
|
}, function(){
|
415
413
|
response();
|
@@ -482,16 +480,16 @@ window.closeFlashMessage = (function($element){
|
|
482
480
|
_formatData: function(data) {
|
483
481
|
return $.map(data, function(elem, i){
|
484
482
|
var id, value;
|
485
|
-
if (elem
|
486
|
-
|
487
|
-
|
488
|
-
} else if (elem instanceof Object) {
|
489
|
-
value = elem.value;
|
490
|
-
id = elem.id;
|
483
|
+
if( $.isArray(elem) ) {
|
484
|
+
value = elem[0];
|
485
|
+
id = elem[1];
|
491
486
|
} else {
|
492
|
-
|
493
|
-
|
494
|
-
|
487
|
+
id = value = elem;
|
488
|
+
}
|
489
|
+
if ( elem !== null && typeof elem === 'object' )
|
490
|
+
return elem;
|
491
|
+
else
|
492
|
+
return {value: value, id: id};
|
495
493
|
});
|
496
494
|
},
|
497
495
|
|
@@ -544,7 +542,6 @@ window.closeFlashMessage = (function($element){
|
|
544
542
|
name: value.value
|
545
543
|
});
|
546
544
|
this.element.trigger('change');
|
547
|
-
this.element.val('');
|
548
545
|
} else {
|
549
546
|
this.element.val(value.value);
|
550
547
|
this.valueElement.val(value.id);
|
@@ -554,7 +551,7 @@ window.closeFlashMessage = (function($element){
|
|
554
551
|
|
555
552
|
setValue: function(values) {
|
556
553
|
var that = this;
|
557
|
-
if( typeof values
|
554
|
+
if( typeof values == 'undefined' || !values )
|
558
555
|
return false;
|
559
556
|
|
560
557
|
if( this.options.preload ) {
|
@@ -562,63 +559,37 @@ window.closeFlashMessage = (function($element){
|
|
562
559
|
if( that.options.multiple ) {
|
563
560
|
that.valueElement.entityArray('clear');
|
564
561
|
}
|
565
|
-
that._setValues(values)
|
562
|
+
that._setValues(values)
|
566
563
|
});
|
567
564
|
} else {
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
that._setValues(values);
|
565
|
+
// TODO - where to get real text value?
|
566
|
+
this.element.val(values[0]);
|
567
|
+
this.valueElement.val(values[0]);
|
572
568
|
}
|
573
569
|
},
|
574
570
|
|
575
571
|
_setValues: function(values) {
|
576
|
-
var
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
if( values[i] instanceof Object && !Array.isArray(values[i]) && values[i] !== null ) {
|
585
|
-
selected.push( values[i] );
|
586
|
-
} else if( this.options.preload && Array.isArray(this.possibleValues) ) {
|
587
|
-
for(var j = this.possibleValues.length - 1; j >= 0; j-- ) {
|
588
|
-
if ( values[i] == this.possibleValues[j].id || values[i] == this.possibleValues[j].id.toString() ) {
|
589
|
-
selected.push(this.possibleValues[j]);
|
590
|
-
break;
|
591
|
-
}
|
572
|
+
var that = this;
|
573
|
+
$.each(that.possibleValues, function(i, val) {
|
574
|
+
if ( values.indexOf(val.id) > -1 || (values.indexOf(val.id.toString()) > -1)) {
|
575
|
+
if(that.options.multiple) {
|
576
|
+
that.valueElement.entityArray('add', { id: val.id, name: val.value });
|
577
|
+
} else {
|
578
|
+
that.element.val(val.value);
|
579
|
+
that.valueElement.val(val.id);
|
592
580
|
}
|
593
|
-
} else {
|
594
|
-
selected.push( {id: values[i], value: values[i]} );
|
595
|
-
}
|
596
|
-
}
|
597
|
-
for (var i = selected.length - 1; i >= 0; i--) {
|
598
|
-
if(this.options.multiple) {
|
599
|
-
this.valueElement.entityArray('add', { id: selected[i].id, name: selected[i].value });
|
600
|
-
} else {
|
601
|
-
this.element.val(selected[i].value);
|
602
|
-
this.valueElement.val(selected[i].id);
|
603
581
|
}
|
604
|
-
}
|
582
|
+
});
|
605
583
|
},
|
606
584
|
|
607
|
-
getValue: function(
|
608
|
-
|
609
|
-
|
610
|
-
result = this.valueElement.entityArray('getValue'); // entityArray
|
585
|
+
getValue: function() {
|
586
|
+
if( this.options.multiple && !this.expanded ) {
|
587
|
+
return this.valueElement.entityArray('getValue'); // entityArray
|
611
588
|
} else if ( this.options.multiple ) {
|
612
|
-
|
589
|
+
return this.valueElement.val(); //select multiple=true
|
613
590
|
} else {
|
614
|
-
|
615
|
-
}
|
616
|
-
if( with_label ) {
|
617
|
-
result = this.possibleValues.filter(function(el) {
|
618
|
-
return result.indexOf( el.id ) >= 0;
|
619
|
-
});
|
591
|
+
return [this.valueElement.val()]; // hidden field
|
620
592
|
}
|
621
|
-
return result;
|
622
593
|
}
|
623
594
|
|
624
595
|
});
|
@@ -25,7 +25,7 @@ class EasySettingsController < ApplicationController
|
|
25
25
|
Setting.send "plugin_#{@plugin.id}=", params[:settings] if params[:settings]
|
26
26
|
if @easy_settings.save
|
27
27
|
flash[:notice] = l(:notice_successful_update)
|
28
|
-
redirect_back_or_default edit_easy_setting_path(@easy_settings)
|
28
|
+
redirect_back_or_default redmine_extensions_engine.edit_easy_setting_path(@easy_settings)
|
29
29
|
else
|
30
30
|
render :edit
|
31
31
|
end
|
@@ -6,7 +6,7 @@ module RedmineExtensions
|
|
6
6
|
|
7
7
|
def plugin_settings_path(plugin, *attrs)
|
8
8
|
if plugin.is_a?(Redmine::Plugin) && (plugin.settings[:only_easy] || plugin.settings[:easy_settings])
|
9
|
-
edit_easy_setting_path(plugin, *attrs)
|
9
|
+
redmine_extensions_engine.edit_easy_setting_path(plugin, *attrs)
|
10
10
|
else
|
11
11
|
super
|
12
12
|
end
|
@@ -44,20 +44,21 @@ module RedmineExtensions
|
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
|
-
def
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
47
|
+
def query_for_entity(entity_class)
|
48
|
+
entity_class_name = entity_class.name
|
49
|
+
query_class = "Easy#{entity_class_name}Query".constantize rescue nil
|
50
|
+
return query_class if query_class && query_class < EasyQuery
|
51
|
+
query_class ||= "#{entity_class_name}Query".constantize rescue nil
|
52
|
+
end
|
53
53
|
|
54
|
-
|
55
|
-
|
54
|
+
def render_entity_assignments(entity, target_entity, options = {}, &block)
|
55
|
+
options ||= {}
|
56
|
+
collection_name = options.delete(:collection_name) || target_entity.name.pluralize.underscore
|
57
|
+
query_class = query_for_entity(target_entity)
|
56
58
|
|
57
|
-
|
58
|
-
end
|
59
|
+
return '' if !query_class || !entity.respond_to?(collection_name)
|
59
60
|
|
60
|
-
|
61
|
+
project = options.delete(:project)
|
61
62
|
|
62
63
|
query = query_class.new(:name => 'c_query')
|
63
64
|
query.project = project
|
@@ -68,9 +69,8 @@ module RedmineExtensions
|
|
68
69
|
|
69
70
|
entities_count = entities.size
|
70
71
|
options[:entities_count] = entities_count
|
71
|
-
|
72
72
|
options[:module_name] ||= "entity_#{entity.class.name.underscore}_#{entity.id}_#{collection_name}"
|
73
|
-
options[:heading] ||= l("label_#{
|
73
|
+
options[:heading] ||= l("label_#{query.entity}_plural", :default => 'Heading')
|
74
74
|
|
75
75
|
if options[:context_menus_path].nil?
|
76
76
|
options[:context_menus_path] = [
|
@@ -82,9 +82,11 @@ module RedmineExtensions
|
|
82
82
|
end
|
83
83
|
end
|
84
84
|
|
85
|
+
query.output = options[:display_style] || (entities_count > 3 ? 'list' : 'tile')
|
86
|
+
|
85
87
|
render(:partial => 'easy_entity_assignments/assignments_container', :locals => {
|
86
88
|
:entity => entity,
|
87
|
-
:query => query, :
|
89
|
+
:query => query, :project => project,
|
88
90
|
:entities => entities, :entities_count => entities_count, :options => options})
|
89
91
|
end
|
90
92
|
|
@@ -106,65 +108,106 @@ module RedmineExtensions
|
|
106
108
|
end
|
107
109
|
end
|
108
110
|
|
109
|
-
# options:
|
110
|
-
# => options[:heading] = text beside of plus button
|
111
|
-
# => options[:container_html] = a hash of html attributes
|
112
|
-
# => options[:default_button_state] = (true => expanded -), (false => collapsed +)
|
113
|
-
# => options[:ajax_call] = make ajax call for saving state (true => ajax call, false => no call, no save)
|
114
|
-
# => options[:wrapping_heading_element] = html element outside heading => h3, h4
|
115
|
-
def render_toggler(container_uniq_id, user = nil, options={}, &block)
|
116
|
-
user ||= User.current
|
117
|
-
options[:heading] ||= ''
|
118
|
-
options[:heading_links] ||= []
|
119
|
-
options[:heading_links] = [options[:heading_links]] if options[:heading_links] && !options[:heading_links].is_a?(Array)
|
120
|
-
options[:container_html] ||= {}
|
121
|
-
options[:default_button_state] = false #if is_mobile_device?
|
122
|
-
options[:default_button_state] = true if options[:default_button_state].nil?
|
123
|
-
options[:ajax_call] = true if options[:ajax_call].nil?
|
124
|
-
|
125
|
-
s = ''
|
126
|
-
if !options.key?(:no_heading_button)
|
127
|
-
options[:heading] << content_tag(:div, options[:heading_links].join(' ').html_safe, :class => 'module-heading-links') unless options[:heading_links].blank?
|
128
|
-
s << render_toggler_header(user, options[:heading].html_safe, container_uniq_id, options)
|
129
|
-
end
|
130
|
-
|
131
|
-
if options[:ajax_call] == false
|
132
|
-
expanded = options[:default_button_state]
|
133
|
-
else
|
134
|
-
expanded = true
|
135
|
-
end
|
136
111
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
112
|
+
# ==== Options
|
113
|
+
# * <tt>class: Hash or String</tt> - This option can be used to add custom CSS classes. It can be *String* or *Hash*.
|
114
|
+
# class: {heading: 'heading-additional-css', container: 'container-additional-css'}
|
115
|
+
# * <tt>heading_tag: name of HTML element of module heading</tt> - By default its its *h3*
|
116
|
+
# ** Aliases for this options are: wrapping_heading_element, header_tag
|
117
|
+
# * <tt>toggle: false</tt> - This disable toggle function (collapsible and remember)
|
118
|
+
# ** Aliases for this options are: collapsible, no_expander
|
119
|
+
# * <tt>remember: false</tt> - This disable remember function of toggle conatiner
|
120
|
+
# ** Aliases for this options are: ajax_call
|
121
|
+
#
|
122
|
+
def render_module_easy_box(id, heading, options = {}, &block) # with fallback to old
|
123
|
+
options[:toggle] = true unless options.key?(:toggle)
|
124
|
+
options[:remember] = options.delete(:ajax_call) if options.key?(:ajax_call)
|
125
|
+
options[:collapsible] = !options.delete(:no_expander) if options.key?(:no_expander)
|
126
|
+
|
127
|
+
renderer = EasyBoxRenderer.new(self, id, heading, options)
|
128
|
+
renderer.content = capture {yield renderer}
|
129
|
+
|
130
|
+
renderer.render
|
142
131
|
end
|
143
132
|
|
144
|
-
|
145
|
-
expander_options = options[:expander_options] || {}
|
146
|
-
wrapping_heading_element = options[:wrapping_heading_element] || 'h3'
|
147
|
-
wrapping_heading_element_classes = (options[:wrapping_heading_element_classes] || '') + ' module-heading'
|
148
|
-
wrapping_heading_element_styles = options[:wrapping_heading_element_styles]
|
149
|
-
ajax_call = options.delete(:ajax_call) ? 'true' : 'false'
|
133
|
+
EasyBoxRenderer = Struct.new(:view, :id, :heading, :options) do
|
150
134
|
|
151
|
-
|
135
|
+
attr_writer :container_class, :heading_class, :content_class
|
136
|
+
attr_writer :heading_links, :footer, :icon
|
137
|
+
attr_accessor :content
|
152
138
|
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
139
|
+
def container_class
|
140
|
+
s = (@container_class.presence || css_classes[:container]).to_s
|
141
|
+
s << ' collapsible' if collapsible?
|
142
|
+
s << ' collapsed' if collapsed?
|
143
|
+
|
144
|
+
s
|
145
|
+
end
|
146
|
+
|
147
|
+
def saving_state_enabled?
|
148
|
+
collapsible? && (options[:remember].nil? || !!options[:remember])
|
149
|
+
end
|
150
|
+
|
151
|
+
def heading_tag
|
152
|
+
(options[:wrapping_heading_element] || (options[:header_tag] || options[:heading_tag])).presence || 'h3'
|
153
|
+
end
|
154
|
+
|
155
|
+
def heading_class
|
156
|
+
(@heading_class || css_classes[:heading]).to_s
|
157
|
+
end
|
158
|
+
|
159
|
+
def icon
|
160
|
+
@icon ||= options[:icon] && " icon #{options[:icon]}"
|
161
|
+
end
|
162
|
+
|
163
|
+
def heading_links
|
164
|
+
if block_given?
|
165
|
+
@heading_links = view.capture { yield }
|
166
|
+
else
|
167
|
+
@heading_links.to_s.html_safe
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def collapsible?
|
172
|
+
return @collapsible unless @collapsible.nil?
|
173
|
+
@collapsible ||= !!options[:toggle] && (options[:collapsible].nil? || !!options[:collapsible])
|
174
|
+
end
|
175
|
+
|
176
|
+
def collapsed?
|
177
|
+
!!options[:default] || !!options[:collapsed] || !!options[:default_button_state]
|
178
|
+
end
|
179
|
+
|
180
|
+
def footer
|
181
|
+
if block_given?
|
182
|
+
@footer = view.capture { yield }
|
183
|
+
else
|
184
|
+
@footer.to_s.html_safe
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
def render
|
189
|
+
view.render({partial: 'common/collapsible_module_layout', locals: {renderer: self, content: content}} )
|
190
|
+
end
|
191
|
+
private
|
192
|
+
|
193
|
+
def css_classes
|
194
|
+
return @css_classes if @css_classes
|
195
|
+
if (css_class = options.delete(:class)).is_a?(Hash)
|
196
|
+
@css_classes = css_class
|
197
|
+
else
|
198
|
+
@css_classes = {
|
199
|
+
container: css_class,
|
200
|
+
heading: css_class,
|
201
|
+
content: css_class
|
202
|
+
}
|
203
|
+
end
|
161
204
|
end
|
162
205
|
|
163
|
-
html.html_safe
|
164
206
|
end
|
165
207
|
|
208
|
+
|
166
209
|
def autocomplete_field_tag(name, jsonpath_or_array, selected_values, options = {})
|
167
|
-
options.reverse_merge!({select_first_value: false, show_toggle_button: false, load_immediately: false
|
210
|
+
options.reverse_merge!({select_first_value: false, show_toggle_button: false, load_immediately: false})
|
168
211
|
options[:id] ||= sanitize_to_id(name)
|
169
212
|
|
170
213
|
selected_values ||= []
|
@@ -177,7 +220,7 @@ module RedmineExtensions
|
|
177
220
|
|
178
221
|
content_tag(:span, :class => 'easy-multiselect-tag-container') do
|
179
222
|
text_field_tag('', '', (options[:html_options] || {}).merge(id: options[:id])) +
|
180
|
-
javascript_tag("$('##{options[:id]}').easymultiselect({multiple:
|
223
|
+
javascript_tag("$('##{options[:id]}').easymultiselect({multiple: true, rootElement: #{options[:rootElement]}, inputName: '#{name}', preload: true, source: #{source}, selected: #{selected_values.to_json}, show_toggle_button: #{options[:show_toggle_button]}, select_first_value: #{options[:select_first_value]}, load_immediately: #{options[:load_immediately]}, autocomplete_options: #{(options[:jquery_auto_complete_options]||{}).to_json} });")
|
181
224
|
end
|
182
225
|
end
|
183
226
|
|
@@ -20,5 +20,10 @@ module RedmineExtensions
|
|
20
20
|
partial.prepend("#{prefixes.last}/")
|
21
21
|
render(*attrs)
|
22
22
|
end
|
23
|
+
|
24
|
+
def query_outputs(presenter_or_query, options={})
|
25
|
+
presenter = present(presenter_or_query, options) rescue RedmineExtensions::BasePresenter.new(presenter_or_query, self, options)
|
26
|
+
RedmineExtensions::EasyQueryHelpers::Outputs.new(presenter, self)
|
27
|
+
end
|
23
28
|
end
|
24
29
|
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
class EasyQueryAdapterPresenter < RedmineExtensions::BasePresenter
|
2
|
+
|
3
|
+
# --- GETTERS ---
|
4
|
+
attr_accessor :page_module, :row_limit
|
5
|
+
|
6
|
+
# should be defined in parent in future
|
7
|
+
def initialize(query, view_context=nil, options={})
|
8
|
+
super(query, view_context, options)
|
9
|
+
@query = query
|
10
|
+
|
11
|
+
@page_module = options[:page_module]
|
12
|
+
|
13
|
+
end
|
14
|
+
|
15
|
+
def entities(options={})
|
16
|
+
#can not fetch, cuz gantt is fetching enstead of nil
|
17
|
+
@entities ||= @options[:entities] || h.instance_variable_get(:@entities) #|| model.entities(options)
|
18
|
+
end
|
19
|
+
|
20
|
+
def entity_count(options={})
|
21
|
+
@entity_count ||= h.instance_variable_get(:@entity_count) || model.entity_count(options)
|
22
|
+
end
|
23
|
+
|
24
|
+
def entity_pages
|
25
|
+
@options[:entity_pages] || h.instance_variable_get(:@entity_pages)
|
26
|
+
end
|
27
|
+
|
28
|
+
def available_outputs
|
29
|
+
outputs.available_outputs
|
30
|
+
end
|
31
|
+
|
32
|
+
def outputs
|
33
|
+
@outputs ||= RedmineExtensions::EasyQueryHelpers::Outputs.new(self)
|
34
|
+
end
|
35
|
+
|
36
|
+
# ----- RENDERING HELPERS ----
|
37
|
+
|
38
|
+
def default_name
|
39
|
+
h.l(self.class.name.underscore, :scope => [:easy_query, :name])
|
40
|
+
end
|
41
|
+
|
42
|
+
def name
|
43
|
+
@name ||= options[:easy_query_name] || (model.new_record? ? default_name : model.name)
|
44
|
+
end
|
45
|
+
|
46
|
+
def filters_active?
|
47
|
+
model.filters.any?
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<div class="module box <%= renderer.container_class %>"<%=raw renderer.collapsible? && %Q{ data-toggle="#{renderer.id}"} || nil %>>
|
2
|
+
<%= content_tag(:div, class: 'module-heading ' + renderer.heading_class, onclick: (renderer.saving_state_enabled? && 'EasyToggler.toggle(this.nextElementSibling, event)' || nil)) do %>
|
3
|
+
<span class="expander module-toggler"> </span>
|
4
|
+
<%= content_tag(renderer.heading_tag, renderer.heading, class: renderer.icon) %>
|
5
|
+
<%= content_tag(:span, renderer.heading_links, class: 'module-heading-links') if renderer.heading_links %>
|
6
|
+
<% end %>
|
7
|
+
<div class="module-content" id="<%= renderer.id %>"<%=raw renderer.collapsed? && %q{ style="display:none"} || nil %>>
|
8
|
+
<%= content -%>
|
9
|
+
<%= content_tag(:div, class: 'module-content-footer') do %>
|
10
|
+
<%= renderer.footer %>
|
11
|
+
<% end if renderer.footer.present? %>
|
12
|
+
</div>
|
13
|
+
</div>
|
@@ -1,24 +1,20 @@
|
|
1
1
|
<%
|
2
|
-
|
3
|
-
heading = "#{options[:heading]} (#{entities_count})"
|
2
|
+
heading = "#{options[:heading]} (#{entities_count})"
|
4
3
|
%>
|
5
4
|
<% if entities_count > 0 %>
|
6
|
-
<div id="<%= options[:module_name] %>_container" class="entity_references_container easy-dropper-target easy-drop-issue
|
7
|
-
<%= call_hook(:view_easy_entity_assignemnt_top, :entity => entity, :query => query, :entities => entities, :options => options
|
8
|
-
<div class="box">
|
5
|
+
<div id="<%= options[:module_name] %>_container" class="entity_references_container easy-dropper-target easy-drop-issue" data-drop-action="<%= entity.class.name.underscore %>" data-entity-id="<%= entity.id %>" data-issue-show="1">
|
6
|
+
<%= call_hook(:view_easy_entity_assignemnt_top, :entity => entity, :query => query, :entities => entities, :options => options) %>
|
9
7
|
<%# entity_cards_params = {:module_name => options[:module_name], :project_id => project, :source_entity_type => entity.class.name, :source_entity_id => entity, :referenced_entity_type => referenced_entity_type, :referenced_collection_name => options[:referenced_collection_name]}.merge!(query.to_params) %>
|
10
8
|
<% entity_cards_params = {} %>
|
11
|
-
<%=
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
9
|
+
<%= render_module_easy_box(options[:module_name], heading+':', {class: {heading: entity_css_icon(query.entity), container: 'module-inside'}, default: false}) do |m| %>
|
10
|
+
<% m.heading_links do %>
|
11
|
+
<%= link_to('', {}, :class => 'icon-slab', :remote => true, :data => {:display => 'slab'}, :title => l(:title_easy_card_display_changer_tile)) %>
|
12
|
+
<%= link_to('', {}, :class => 'icon-bullet-list', :remote => true, :data => {:display => 'list'}, :title => l(:title_easy_card_display_changer_list)) %>
|
13
|
+
<% end %>
|
18
14
|
<%= render(:partial => 'easy_entity_assignments/query_index', :locals => {
|
19
15
|
:entity => entity,
|
20
|
-
:query => query,
|
21
|
-
:project => project, :options => options, :
|
16
|
+
:query => query,
|
17
|
+
:project => project, :options => options, :referenced_entities => entities}) %>
|
22
18
|
|
23
19
|
|
24
20
|
<% if options[:context_menus_path] && respond_to?(options[:context_menus_path]) %>
|
@@ -26,5 +22,4 @@
|
|
26
22
|
<% end %>
|
27
23
|
<% end %>
|
28
24
|
</div>
|
29
|
-
</div>
|
30
25
|
<% end %>
|
@@ -1,11 +1,3 @@
|
|
1
|
-
<%
|
2
|
-
<%=
|
3
|
-
<% elsif display_style == :tile %>
|
4
|
-
<div class="easy-entity-cards-container">
|
5
|
-
<div class="splitcontent">
|
6
|
-
<% entities.each do |referenced_entity| %>
|
7
|
-
<%# render_easy_entity_card(referenced_entity, entity, options.merge(:referenced_entities => referenced_entities)) %>
|
8
|
-
<% end %>
|
9
|
-
</div>
|
10
|
-
</div>
|
1
|
+
<% query_outputs(query, entities: referenced_entities, options: { hascontextmenu: true, disable_sort: true }).each do |output| %>
|
2
|
+
<%= output.render_data %>
|
11
3
|
<% end %>
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<%= form_for(@easy_settings, html: { class: 'form-box easy-setting-plugin-form' }) do |f| %>
|
1
|
+
<%= form_for([redmine_extensions_engine, @easy_settings], html: { class: 'form-box easy-setting-plugin-form' }) do |f| %>
|
2
2
|
<%= hidden_field_tag :back_url, params[:back_url] %>
|
3
3
|
|
4
4
|
<%= render "easy_settings/#{@easy_settings.plugin.id}", easy_settings: @easy_settings, settings: @settings, form: f %>
|
data/config/routes.rb
CHANGED
@@ -1,11 +1,7 @@
|
|
1
|
-
# Engine routes
|
2
1
|
RedmineExtensions::Engine.routes.draw do
|
3
|
-
resources :easy_settings, except: :destroy
|
4
|
-
end
|
5
|
-
|
6
|
-
# Redmine routes
|
7
|
-
Rails.application.routes.draw do
|
8
|
-
mount RedmineExtensions::Engine => '/redmine_extensions'
|
9
2
|
|
10
3
|
resources :easy_settings, except: :destroy
|
4
|
+
|
11
5
|
end
|
6
|
+
|
7
|
+
RedmineExtensions::Engine.automount!
|
@@ -1,9 +1,9 @@
|
|
1
|
-
<ul>
|
2
|
-
<%% if @<%= model_name_underscored %> && !@<%= model_name_underscored %>.new_record? %>
|
3
|
-
<li><%%= link_to l(:button_edit), edit_polymorphic_path([@project, @<%= model_name_underscored %>]), title: l(:button_edit), class: 'icon icon-edit' %></li>
|
4
|
-
<%% end %>
|
5
|
-
<%% if @<%= model_name_underscored %>.nil? %>
|
6
|
-
<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' %></li>
|
7
|
-
<%% end %>
|
8
|
-
<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' %></li>
|
1
|
+
<ul>
|
2
|
+
<%% if @<%= model_name_underscored %> && !@<%= model_name_underscored %>.new_record? %>
|
3
|
+
<li><%%= link_to l(:button_edit), edit_polymorphic_path([@project, @<%= model_name_underscored %>]), title: l(:button_edit), class: 'icon icon-edit' %></li>
|
4
|
+
<%% end %>
|
5
|
+
<%% if @<%= model_name_underscored %>.nil? %>
|
6
|
+
<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' %></li>
|
7
|
+
<%% end %>
|
8
|
+
<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' %></li>
|
9
9
|
</ul>
|
@@ -1,8 +1,8 @@
|
|
1
|
-
<ul>
|
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
|
-
<li><%%= context_menu_link l(:button_delete), <%= model_name_pluralize_underscored %>_path(ids: @<%= model_name_underscored %>_ids, back_url: @back), method: :delete, data: {confirm: l(:text_are_you_sure)}, class: 'icon icon-del', disabled: !@can[:delete] %></li>
|
6
|
-
|
7
|
-
<%%= 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}) %>
|
1
|
+
<ul>
|
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
|
+
<li><%%= context_menu_link l(:button_delete), <%= model_name_pluralize_underscored %>_path(ids: @<%= model_name_underscored %>_ids, back_url: @back), method: :delete, data: {confirm: l(:text_are_you_sure)}, class: 'icon icon-del', disabled: !@can[:delete] %></li>
|
6
|
+
|
7
|
+
<%%= 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}) %>
|
8
8
|
</ul>
|
@@ -1,7 +1,7 @@
|
|
1
|
-
class <%= model_name %>CustomField < CustomField
|
2
|
-
|
3
|
-
def type_name
|
4
|
-
:label_<%= @model_name_pluralize_underscored %>
|
5
|
-
end
|
6
|
-
|
7
|
-
end
|
1
|
+
class <%= model_name %>CustomField < CustomField
|
2
|
+
|
3
|
+
def type_name
|
4
|
+
:label_<%= @model_name_pluralize_underscored %>
|
5
|
+
end
|
6
|
+
|
7
|
+
end
|