active_scaffold_vho 3.0.26 → 3.0.27
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +42 -0
- data/Gemfile +1 -10
- data/Gemfile.lock +78 -10
- data/Rakefile +19 -17
- data/active_scaffold_vho.gemspec +14 -324
- data/frontends/default/javascripts/jquery/active_scaffold.js +23 -13
- data/frontends/default/javascripts/prototype/active_scaffold.js +22 -14
- data/frontends/default/stylesheets/stylesheet.css +1 -1
- data/frontends/default/views/_list.html.erb +2 -1
- data/frontends/default/views/_list_messages.html.erb +2 -2
- data/frontends/default/views/_list_pagination.html.erb +3 -6
- data/frontends/default/views/_list_record_columns.html.erb +1 -1
- data/lib/active_scaffold/actions/list.rb +7 -6
- data/lib/active_scaffold/active_record_permissions.rb +25 -0
- data/lib/active_scaffold/attribute_params.rb +5 -2
- data/lib/active_scaffold/bridges/shared/date_bridge.rb +3 -3
- data/lib/active_scaffold/bridges/tiny_mce/public/javascripts/prototype/tiny_mce_bridge.js +1 -1
- data/lib/active_scaffold/config/core.rb +8 -1
- data/lib/active_scaffold/config/field_search.rb +22 -1
- data/lib/active_scaffold/data_structures/column.rb +19 -2
- data/lib/active_scaffold/finder.rb +19 -30
- data/lib/active_scaffold/helpers/human_condition_helpers.rb +4 -2
- data/lib/active_scaffold/helpers/list_column_helpers.rb +9 -2
- data/lib/active_scaffold/locale/de.yml +118 -0
- data/lib/active_scaffold/locale/en.yml +115 -0
- data/lib/active_scaffold/version.rb +1 -1
- data/lib/active_scaffold.rb +0 -1
- data/test/mock_app/public/stylesheets/active_scaffold/default/stylesheet.css +1 -1
- metadata +102 -62
- data/lib/active_scaffold/locale/de.rb +0 -120
- data/lib/active_scaffold/locale/en.rb +0 -119
@@ -119,7 +119,7 @@ $(document).ready(function() {
|
|
119
119
|
});
|
120
120
|
$('a.as_cancel').live('ajax:beforeSend', function(event, xhr, settings) {
|
121
121
|
var as_cancel = $(this);
|
122
|
-
var action_link = ActiveScaffold.
|
122
|
+
var action_link = ActiveScaffold.find_action_link(as_cancel);
|
123
123
|
var refresh_data = as_cancel.attr('data-refresh');
|
124
124
|
|
125
125
|
if (action_link && action_link.position && refresh_data === 'true' && action_link.refresh_url) {
|
@@ -159,19 +159,27 @@ $(document).ready(function() {
|
|
159
159
|
ActiveScaffold.report_500_response(as_scaffold);
|
160
160
|
return true;
|
161
161
|
});
|
162
|
-
$('a
|
162
|
+
$('div.active-scaffold-footer .pagination a').live('ajax:before',function(event) {
|
163
163
|
var as_paginate = $(this);
|
164
|
+
var loading_indicator = as_paginate.closest('.pagination').find('img.loading-indicator').first();
|
164
165
|
var history_controller_id = as_paginate.attr('data-page-history');
|
165
166
|
if (history_controller_id) addActiveScaffoldPageToHistory(as_paginate.attr('href'), history_controller_id);
|
166
|
-
|
167
|
+
|
168
|
+
if (loading_indicator == null || loading_indicator.length == 0) {
|
169
|
+
var table_loading_indicator = as_paginate.closest('div.active-scaffold').find('div.actions img.loading-indicator').first();
|
170
|
+
loading_indicator = table_loading_indicator.clone();
|
171
|
+
loading_indicator.attr('id', null);
|
172
|
+
as_paginate.closest('.pagination').prepend(loading_indicator);
|
173
|
+
}
|
174
|
+
loading_indicator.css('visibility','visible');
|
167
175
|
return true;
|
168
176
|
});
|
169
|
-
$('a
|
177
|
+
$('div.active-scaffold-footer .pagination a').live('ajax:failure', function(event) {
|
170
178
|
var as_scaffold = $(this).closest('.active-scaffold');
|
171
179
|
ActiveScaffold.report_500_response(as_scaffold);
|
172
180
|
return true;
|
173
181
|
});
|
174
|
-
$('a
|
182
|
+
$('div.active-scaffold-footer .pagination a').live('ajax:complete', function(event) {
|
175
183
|
$(this).prevAll('img.loading-indicator').css('visibility','hidden');
|
176
184
|
return true;
|
177
185
|
});
|
@@ -661,7 +669,7 @@ var ActiveScaffold = {
|
|
661
669
|
},
|
662
670
|
|
663
671
|
report_500_response: function(active_scaffold_id) {
|
664
|
-
server_error = $(active_scaffold_id).find('td.messages-container p.server-error');
|
672
|
+
server_error = $(active_scaffold_id).find('td.messages-container p.server-error').filter(":first");
|
665
673
|
if (!$(server_error).is(':visible')) {
|
666
674
|
server_error.show();
|
667
675
|
}
|
@@ -1099,7 +1107,7 @@ ActiveScaffold.ActionLink.Abstract = Class.extend({
|
|
1099
1107
|
this.adapter.addClass('as_adapter');
|
1100
1108
|
this.adapter.data('action_link', this);
|
1101
1109
|
},
|
1102
|
-
wrap_with_adapter_html: function(content) {
|
1110
|
+
wrap_with_adapter_html: function(content, should_refresh_data) {
|
1103
1111
|
// players_view class missing
|
1104
1112
|
var id_string = null;
|
1105
1113
|
var close_label = this.scaffold().attr('data-closelabel');
|
@@ -1115,7 +1123,7 @@ ActiveScaffold.ActionLink.Abstract = Class.extend({
|
|
1115
1123
|
id_string = this.target.attr('id').replace('list', 'nested');
|
1116
1124
|
}
|
1117
1125
|
|
1118
|
-
return '<tr class="inline-adapter" id="' + id_string + '"><td colspan="99" class="inline-adapter-cell"><div class="' + this.action + '-view ' + controller + '-view view"><a class="inline-adapter-close as_cancel" title="' + close_label + '" data-remote="true" data-refresh="
|
1126
|
+
return '<tr class="inline-adapter" id="' + id_string + '"><td colspan="99" class="inline-adapter-cell"><div class="' + this.action + '-view ' + controller + '-view view"><a class="inline-adapter-close as_cancel" title="' + close_label + '" data-remote="true" data-refresh="' + should_refresh_data + '" href="">' + close_label +'</a>' + content + '</div></td></tr>'
|
1119
1127
|
}
|
1120
1128
|
});
|
1121
1129
|
|
@@ -1153,6 +1161,7 @@ ActiveScaffold.ActionLink.Record = ActiveScaffold.ActionLink.Abstract.extend({
|
|
1153
1161
|
},
|
1154
1162
|
|
1155
1163
|
insert: function(content) {
|
1164
|
+
var should_refresh_data = (typeof(this.refresh_ur)== 'undefined');
|
1156
1165
|
this.close_previous_adapter();
|
1157
1166
|
|
1158
1167
|
if (this.position == 'replace') {
|
@@ -1161,12 +1170,12 @@ ActiveScaffold.ActionLink.Record = ActiveScaffold.ActionLink.Abstract.extend({
|
|
1161
1170
|
}
|
1162
1171
|
|
1163
1172
|
if (this.position == 'after') {
|
1164
|
-
this.target.after(this.wrap_with_adapter_html(content));
|
1173
|
+
this.target.after(this.wrap_with_adapter_html(content, should_refresh_data));
|
1165
1174
|
ActiveScaffold.trigger_load_events(this.target.next().find('[data-as_load]'));
|
1166
1175
|
this.set_adapter(this.target.next());
|
1167
1176
|
}
|
1168
1177
|
else if (this.position == 'before') {
|
1169
|
-
this.target.before(this.wrap_with_adapter_html(content));
|
1178
|
+
this.target.before(this.wrap_with_adapter_html(content, should_refresh_data));
|
1170
1179
|
ActiveScaffold.trigger_load_events(this.target.prev().find('[data-as_load]'));
|
1171
1180
|
this.set_adapter(this.target.prev());
|
1172
1181
|
}
|
@@ -1201,12 +1210,13 @@ ActiveScaffold.ActionLink.Record = ActiveScaffold.ActionLink.Abstract.extend({
|
|
1201
1210
|
},
|
1202
1211
|
|
1203
1212
|
set_opened: function() {
|
1213
|
+
var should_refresh_data = (typeof(this.refresh_ur)== 'undefined');
|
1204
1214
|
if (this.position == 'after') {
|
1205
|
-
var new_adapter = ActiveScaffold.replace(this.target.next(), this.wrap_with_adapter_html(this.target.next().children(':first-child').html()), true);
|
1215
|
+
var new_adapter = ActiveScaffold.replace(this.target.next(), this.wrap_with_adapter_html(this.target.next().children(':first-child').html(), should_refresh_data), true);
|
1206
1216
|
this.set_adapter(new_adapter);
|
1207
1217
|
}
|
1208
1218
|
else if (this.position == 'before') {
|
1209
|
-
var new_adapter = ActiveScaffold.replace(this.target.prev(), this.wrap_with_adapter_html(this.target.prev().children(':first-child').html()), true);
|
1219
|
+
var new_adapter = ActiveScaffold.replace(this.target.prev(), this.wrap_with_adapter_html(this.target.prev().children(':first-child').html(), should_refresh_data), true);
|
1210
1220
|
this.set_adapter(new_adapter);
|
1211
1221
|
}
|
1212
1222
|
this.disable();
|
@@ -1227,7 +1237,7 @@ ActiveScaffold.Actions.Table = ActiveScaffold.Actions.Abstract.extend({
|
|
1227
1237
|
ActiveScaffold.ActionLink.Table = ActiveScaffold.ActionLink.Abstract.extend({
|
1228
1238
|
insert: function(content) {
|
1229
1239
|
if (this.position == 'top') {
|
1230
|
-
this.target.prepend(this.wrap_with_adapter_html(content));
|
1240
|
+
this.target.prepend(this.wrap_with_adapter_html(content, false));
|
1231
1241
|
ActiveScaffold.trigger_load_events(this.target.children().first().find('[data-as_load]'));
|
1232
1242
|
this.set_adapter(this.target.children().first());
|
1233
1243
|
}
|
@@ -209,21 +209,27 @@ document.observe("dom:loaded", function() {
|
|
209
209
|
}
|
210
210
|
return true;
|
211
211
|
});
|
212
|
-
document.on('ajax:before', 'a
|
212
|
+
document.on('ajax:before', 'div.active-scaffold-footer .pagination a', function(event) {
|
213
213
|
var as_paginate = event.findElement();
|
214
|
-
var loading_indicator = as_paginate.up().down('img.loading-indicator');
|
214
|
+
var loading_indicator = as_paginate.up(1).down('img.loading-indicator');
|
215
215
|
var history_controller_id = as_paginate.readAttribute('data-page-history');
|
216
216
|
|
217
217
|
if (history_controller_id) addActiveScaffoldPageToHistory(as_paginate.readAttribute('href'), history_controller_id);
|
218
|
-
if (loading_indicator
|
218
|
+
if (loading_indicator == null) {
|
219
|
+
var table_loading_indicator = as_paginate.up('div.active-scaffold').down('div.actions').down('img.loading-indicator');
|
220
|
+
loading_indicator = table_loading_indicator.cloneNode(true);
|
221
|
+
loading_indicator.id = null;
|
222
|
+
as_paginate.up(1).insert({top: loading_indicator});
|
223
|
+
}
|
224
|
+
loading_indicator.style.visibility = 'visible';
|
219
225
|
return true;
|
220
226
|
});
|
221
|
-
document.on('ajax:failure', 'a
|
227
|
+
document.on('ajax:failure', 'div.active-scaffold-footer .pagination a', function(event) {
|
222
228
|
var as_scaffold = event.findElement('.active-scaffold');
|
223
229
|
ActiveScaffold.report_500_response(as_scaffold);
|
224
230
|
return true;
|
225
231
|
});
|
226
|
-
document.on('ajax:complete', 'a
|
232
|
+
document.on('ajax:complete', 'div.active-scaffold-footer .pagination a', function(event) {
|
227
233
|
var as_paginate = event.findElement();
|
228
234
|
var loading_indicator = as_paginate.up().down('img.loading-indicator');
|
229
235
|
|
@@ -354,12 +360,12 @@ document.observe("dom:loaded", function() {
|
|
354
360
|
});
|
355
361
|
document.on('ajax:before', 'form.as_form', function(event) {
|
356
362
|
var as_form = event.findElement('form');
|
357
|
-
|
363
|
+
as_form.fire('as:form_submit');
|
358
364
|
return true;
|
359
365
|
});
|
360
366
|
document.on('submit', 'form.as_form[data-remote!="true"]', function(event) {
|
361
367
|
var as_form = event.findElement('form');
|
362
|
-
|
368
|
+
as_form.fire('as:form_submit');
|
363
369
|
return true;
|
364
370
|
});
|
365
371
|
ActiveScaffold.trigger_load_events($$('[data-as_load]'));
|
@@ -934,7 +940,7 @@ ActiveScaffold.ActionLink.Abstract = Class.create({
|
|
934
940
|
this.adapter.store('action_link', this);
|
935
941
|
},
|
936
942
|
|
937
|
-
wrap_with_adapter_html: function(content) {
|
943
|
+
wrap_with_adapter_html: function(content, should_refresh_data) {
|
938
944
|
// players_view class missing
|
939
945
|
var id_string = null;
|
940
946
|
var close_label = this.scaffold().readAttribute('data-closelabel');
|
@@ -950,7 +956,7 @@ ActiveScaffold.ActionLink.Abstract = Class.create({
|
|
950
956
|
id_string = this.target.readAttribute('id').replace('list', 'nested');
|
951
957
|
}
|
952
958
|
|
953
|
-
return '<tr class="inline-adapter" id="' + id_string + '"><td colspan="99" class="inline-adapter-cell"><div class="' + this.action + '-view ' + controller + '-view view"><a class="inline-adapter-close as_cancel" title="' + close_label + '" data-remote="true" data-refresh="
|
959
|
+
return '<tr class="inline-adapter" id="' + id_string + '"><td colspan="99" class="inline-adapter-cell"><div class="' + this.action + '-view ' + controller + '-view view"><a class="inline-adapter-close as_cancel" title="' + close_label + '" data-remote="true" data-refresh="' + should_refresh_data + '" href="">' + close_label +'</a>' + content + '</div></td></tr>'
|
954
960
|
}
|
955
961
|
});
|
956
962
|
|
@@ -983,6 +989,7 @@ ActiveScaffold.ActionLink.Record = Class.create(ActiveScaffold.ActionLink.Abstra
|
|
983
989
|
},
|
984
990
|
|
985
991
|
insert: function(content) {
|
992
|
+
var should_refresh_data = (typeof(this.refresh_ur)== 'undefined');
|
986
993
|
this.close_previous_adapter();
|
987
994
|
|
988
995
|
if (this.position == 'replace') {
|
@@ -991,12 +998,12 @@ ActiveScaffold.ActionLink.Record = Class.create(ActiveScaffold.ActionLink.Abstra
|
|
991
998
|
}
|
992
999
|
|
993
1000
|
if (this.position == 'after') {
|
994
|
-
this.target.insert({after:this.wrap_with_adapter_html(content)});
|
1001
|
+
this.target.insert({after:this.wrap_with_adapter_html(content, should_refresh_data)});
|
995
1002
|
ActiveScaffold.trigger_load_events(this.target.next().select('[data-as_load]'));
|
996
1003
|
this.set_adapter(this.target.next());
|
997
1004
|
}
|
998
1005
|
else if (this.position == 'before') {
|
999
|
-
this.target.insert({before:this.wrap_with_adapter_html(content)});
|
1006
|
+
this.target.insert({before:this.wrap_with_adapter_html(content, should_refresh_data)});
|
1000
1007
|
ActiveScaffold.trigger_load_events(this.target.previous().select('[data-as_load]'));
|
1001
1008
|
this.set_adapter(this.target.previous());
|
1002
1009
|
}
|
@@ -1029,12 +1036,13 @@ ActiveScaffold.ActionLink.Record = Class.create(ActiveScaffold.ActionLink.Abstra
|
|
1029
1036
|
},
|
1030
1037
|
|
1031
1038
|
set_opened: function() {
|
1039
|
+
var should_refresh_data = (typeof(this.refresh_ur)== 'undefined');
|
1032
1040
|
if (this.position == 'after') {
|
1033
|
-
var new_adapter = ActiveScaffold.replace(this.target.next(), this.wrap_with_adapter_html(this.target.next().childElements().first().innerHTML), true);
|
1041
|
+
var new_adapter = ActiveScaffold.replace(this.target.next(), this.wrap_with_adapter_html(this.target.next().childElements().first().innerHTML, should_refresh_data), true);
|
1034
1042
|
this.set_adapter(new_adapter);
|
1035
1043
|
}
|
1036
1044
|
else if (this.position == 'before') {
|
1037
|
-
var new_adapter = ActiveScaffold.replace(this.target.previous(), this.wrap_with_adapter_html(this.target.previous().childElements().first().innerHTML), true);
|
1045
|
+
var new_adapter = ActiveScaffold.replace(this.target.previous(), this.wrap_with_adapter_html(this.target.previous().childElements().first().innerHTML, should_refresh_data), true);
|
1038
1046
|
this.set_adapter(new_adapter);
|
1039
1047
|
}
|
1040
1048
|
this.disable();
|
@@ -1055,7 +1063,7 @@ ActiveScaffold.Actions.Table = Class.create(ActiveScaffold.Actions.Abstract, {
|
|
1055
1063
|
ActiveScaffold.ActionLink.Table = Class.create(ActiveScaffold.ActionLink.Abstract, {
|
1056
1064
|
insert: function(content) {
|
1057
1065
|
if (this.position == 'top') {
|
1058
|
-
this.target.insert({top:this.wrap_with_adapter_html(content)});
|
1066
|
+
this.target.insert({top:this.wrap_with_adapter_html(content, false)});
|
1059
1067
|
ActiveScaffold.trigger_load_events(this.target.immediateDescendants().first().select('[data-as_load]'));
|
1060
1068
|
this.set_adapter(this.target.immediateDescendants().first());
|
1061
1069
|
}
|
@@ -8,7 +8,7 @@
|
|
8
8
|
<%= render :partial => 'list_messages', :locals => {:columns => columns} %>
|
9
9
|
<tbody class="records" id="<%= active_scaffold_tbody_id %>">
|
10
10
|
<% if !@records.empty? -%>
|
11
|
-
<%= render :partial => 'list_record', :collection => @
|
11
|
+
<%= render :partial => 'list_record', :collection => @records, :locals => { :hidden => false, :columns => columns, :action_links => active_scaffold_config.action_links.member} %>
|
12
12
|
<% end -%>
|
13
13
|
<% if columns.any? {|c| c.calculation?} -%>
|
14
14
|
<%= render :partial => 'list_calculations', :locals => {:columns => columns} %>
|
@@ -16,3 +16,4 @@
|
|
16
16
|
</tbody>
|
17
17
|
</table>
|
18
18
|
<%= render :partial => 'list_pagination' %>
|
19
|
+
<% save_current_page_num %>
|
@@ -11,7 +11,7 @@
|
|
11
11
|
<p class="filtered-message" <%= ' style="display:none;" '.html_safe unless @filtered %>>
|
12
12
|
<%= @filtered.is_a?(Array) ? render(:partial => 'human_conditions', :locals => {:columns => @filtered}) : as_(active_scaffold_config.list.filtered_message) %>
|
13
13
|
</p>
|
14
|
-
<p id="<%= empty_message_id %>" class="empty-message" <%= ' style="display:none;" '.html_safe unless @
|
14
|
+
<p id="<%= empty_message_id %>" class="empty-message" <%= ' style="display:none;" '.html_safe unless @records.empty? %>>
|
15
15
|
<%= as_(active_scaffold_config.list.no_entries_message) %>
|
16
16
|
</p>
|
17
17
|
</td>
|
@@ -23,7 +23,7 @@
|
|
23
23
|
action_links.add(search_link) -%>
|
24
24
|
<%= render :partial => 'list_actions', :locals => {:record => record, :url_options => params_for(:escape => false, :search => ''), :action_links => action_links.member} %>
|
25
25
|
<% else %>
|
26
|
-
<td class='actions'><%= '<p class="empty-message"> </p>'.html_safe if @
|
26
|
+
<td class='actions'><%= '<p class="empty-message"> </p>'.html_safe if @records.empty? %></td>
|
27
27
|
<% end -%>
|
28
28
|
|
29
29
|
</tr>
|
@@ -1,11 +1,8 @@
|
|
1
1
|
<% if active_scaffold_config.list.pagination -%>
|
2
2
|
<div class="active-scaffold-footer">
|
3
|
-
<% unless
|
4
|
-
<div class="active-scaffold-found"><span class="active-scaffold-records"><%= @
|
3
|
+
<% unless active_scaffold_config.list.pagination == :infinite -%>
|
4
|
+
<div class="active-scaffold-found"><span class="active-scaffold-records"><%= @records.total_count -%></span> <%=as_(:found, :count => @records.total_count) %></div>
|
5
5
|
<% end -%>
|
6
|
-
|
7
|
-
<%= render :partial => 'list_pagination_links', :locals => { :current_page => @page } if @page.pager.infinite? || @page.pager.number_of_pages > 1 %>
|
8
|
-
</div>
|
9
|
-
<br clear="both" /><%# a hack for the Rico Corner problem %>
|
6
|
+
<%= paginate @records, :window => active_scaffold_config.list.page_links_window, :params => params_for(:action => :index), :remote => true %>
|
10
7
|
</div>
|
11
8
|
<% end -%>
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<% columns.each do |column| %>
|
2
|
-
<% authorized = record.
|
2
|
+
<% authorized = record.authorized_for_read_column?(column.name) -%>
|
3
3
|
<% column_value = authorized ? get_column_value(record, column) : active_scaffold_config.list.empty_field_text -%>
|
4
4
|
|
5
5
|
<td class="<%= column_class(column, column_value, record) %>" >
|
@@ -3,6 +3,7 @@ module ActiveScaffold::Actions
|
|
3
3
|
def self.included(base)
|
4
4
|
base.before_filter :list_authorized_filter, :only => [:index, :row]
|
5
5
|
base.helper_method :list_columns
|
6
|
+
base.helper_method :save_current_page_num
|
6
7
|
end
|
7
8
|
|
8
9
|
def index
|
@@ -73,12 +74,8 @@ module ActiveScaffold::Actions
|
|
73
74
|
})
|
74
75
|
end
|
75
76
|
|
76
|
-
|
77
|
-
|
78
|
-
page = page.pager.last
|
79
|
-
active_scaffold_config.list.user.page = page.number
|
80
|
-
end
|
81
|
-
@page, @records = page, page.items
|
77
|
+
@records = find_page(options);
|
78
|
+
@records
|
82
79
|
end
|
83
80
|
|
84
81
|
def each_record_in_page
|
@@ -174,6 +171,10 @@ module ActiveScaffold::Actions
|
|
174
171
|
(default_formats + active_scaffold_config.formats).uniq
|
175
172
|
end
|
176
173
|
|
174
|
+
def save_current_page_num
|
175
|
+
active_scaffold_config.list.user.page = @records.current_page unless active_scaffold_config.list.pagination == false
|
176
|
+
end
|
177
|
+
|
177
178
|
private
|
178
179
|
def list_authorized_filter
|
179
180
|
raise ActiveScaffold::ActionNotAllowed unless list_authorized?
|
@@ -64,6 +64,7 @@ module ActiveRecordPermissions
|
|
64
64
|
def self.included(base)
|
65
65
|
base.extend SecurityMethods
|
66
66
|
base.send :include, SecurityMethods
|
67
|
+
base.class_attribute :auth_column_read_methods
|
67
68
|
end
|
68
69
|
|
69
70
|
# Because any class-level queries get delegated to the instance level via a new record,
|
@@ -110,6 +111,30 @@ module ActiveRecordPermissions
|
|
110
111
|
return ActiveRecordPermissions.default_permission
|
111
112
|
end
|
112
113
|
|
114
|
+
def authorized_for_read_column?(column)
|
115
|
+
self.class.auth_column_read_methods ||= {}
|
116
|
+
methods = self.class.auth_column_read_methods[column]
|
117
|
+
if methods.nil?
|
118
|
+
method = column_and_crud_type_security_method(column, :read)
|
119
|
+
methods = if method && respond_to?(method)
|
120
|
+
[method]
|
121
|
+
else
|
122
|
+
[column_security_method(column),
|
123
|
+
crud_type_security_method(:read)].compact.select {|m| respond_to?(m)}
|
124
|
+
end
|
125
|
+
self.class.auth_column_read_methods[column] = methods
|
126
|
+
end
|
127
|
+
|
128
|
+
# if any method returns false, then return false
|
129
|
+
return false if methods.any? {|m| !send(m)}
|
130
|
+
|
131
|
+
# if any method actually exists then it must've returned true, so return true
|
132
|
+
return true unless methods.empty?
|
133
|
+
|
134
|
+
# if no method exists, return the default permission
|
135
|
+
return ActiveRecordPermissions.default_permission
|
136
|
+
end
|
137
|
+
|
113
138
|
private
|
114
139
|
|
115
140
|
def column_security_method(column)
|
@@ -135,8 +135,11 @@ module ActiveScaffold
|
|
135
135
|
# convert empty strings into nil. this works better with 'null => true' columns (and validations),
|
136
136
|
# and 'null => false' columns should just convert back to an empty string.
|
137
137
|
# ... but we can at least check the ConnectionAdapter::Column object to see if nulls are allowed
|
138
|
-
|
139
|
-
|
138
|
+
if value.is_a? String and value.empty? and !column.column.nil? and column.column.null
|
139
|
+
nil
|
140
|
+
else
|
141
|
+
column.stripped_value(value)
|
142
|
+
end
|
140
143
|
end
|
141
144
|
end
|
142
145
|
|
@@ -73,13 +73,13 @@ module ActiveScaffold
|
|
73
73
|
range_type, range = value[:range].downcase.split('_')
|
74
74
|
format = active_scaffold_human_condition_date_bridge_range_format(range_type, range)
|
75
75
|
from, to = controller.class.date_bridge_from_to(column, value)
|
76
|
-
"#{column.active_record_class.human_attribute_name(column.name)} = #{as_(value[:range].downcase).downcase} (#{I18n.l(from, :format => format)})"
|
76
|
+
"#{column.active_record_class.human_attribute_name(column.name)} = #{as_(value[:range].downcase).downcase} (#{I18n.l(from, :format => format)})" unless from.nil?
|
77
77
|
when 'PAST', 'FUTURE'
|
78
78
|
from, to = controller.class.date_bridge_from_to(column, value)
|
79
|
-
"#{column.active_record_class.human_attribute_name(column.name)} #{as_('BETWEEN'.downcase).downcase} #{I18n.l(from)} - #{I18n.l(to)}"
|
79
|
+
"#{column.active_record_class.human_attribute_name(column.name)} #{as_('BETWEEN'.downcase).downcase} #{I18n.l(from)} - #{I18n.l(to)}" unless from.nil? || to.nil?
|
80
80
|
else
|
81
81
|
from, to = controller.class.date_bridge_from_to(column, value)
|
82
|
-
"#{column.active_record_class.human_attribute_name(column.name)} #{as_(value[:opt].downcase).downcase} #{I18n.l(from)} #{value[:opt] == 'BETWEEN' ? '- ' + I18n.l(to) : ''}"
|
82
|
+
"#{column.active_record_class.human_attribute_name(column.name)} #{as_(value[:opt].downcase).downcase} #{I18n.l(from)} #{value[:opt] == 'BETWEEN' ? '- ' + I18n.l(to) : ''}" unless from.nil? || (value[:opt] == 'BETWEEN' && to.nil?)
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
@@ -7,7 +7,7 @@ document.on('as:form_loaded', 'form.as_form', function(event) {
|
|
7
7
|
});
|
8
8
|
document.on('as:form_submit', 'form.as_form', function(event) {
|
9
9
|
var as_form = event.findElement('form');
|
10
|
-
if (as_form.
|
10
|
+
if (as_form.select('textarea.mceEditor').length > 0) {
|
11
11
|
tinyMCE.triggerSave();
|
12
12
|
}
|
13
13
|
return true;
|
@@ -167,7 +167,14 @@ module ActiveScaffold::Config
|
|
167
167
|
klass = "ActiveScaffold::Config::#{titled_name}".constantize rescue nil
|
168
168
|
if klass
|
169
169
|
if @actions.include? underscored_name
|
170
|
-
|
170
|
+
@action_configs[name] ||= klass.new(self)
|
171
|
+
eigenclass = class << self; self; end
|
172
|
+
eigenclass.class_eval do
|
173
|
+
define_method(name) do
|
174
|
+
@action_configs[name]
|
175
|
+
end
|
176
|
+
end
|
177
|
+
return send(name)
|
171
178
|
else
|
172
179
|
raise "#{titled_name} is not enabled. Please enable it or remove any references in your configuration (e.g. config.#{underscored_name}.columns = [...])."
|
173
180
|
end
|
@@ -6,6 +6,7 @@ module ActiveScaffold::Config
|
|
6
6
|
@core = core_config
|
7
7
|
|
8
8
|
@text_search = self.class.text_search
|
9
|
+
@or_delimiter = self.class.or_delimiter
|
9
10
|
|
10
11
|
# start with the ActionLink defined globally
|
11
12
|
@link = self.class.link.clone
|
@@ -28,6 +29,11 @@ module ActiveScaffold::Config
|
|
28
29
|
cattr_accessor :text_search
|
29
30
|
@@text_search = :full
|
30
31
|
|
32
|
+
# delimiter to seperate or search string such us: name = Paul,Bernd,Klaus
|
33
|
+
# will search for Paul Or Bernd Or Klaus
|
34
|
+
cattr_accessor :or_delimiter
|
35
|
+
@@or_delimiter = ','
|
36
|
+
|
31
37
|
# instance-level configuration
|
32
38
|
# ----------------------------
|
33
39
|
|
@@ -50,18 +56,33 @@ module ActiveScaffold::Config
|
|
50
56
|
# * false: LIKE ?
|
51
57
|
# Default is :full
|
52
58
|
attr_accessor :text_search
|
59
|
+
|
60
|
+
attr_accessor :or_delimiter
|
53
61
|
|
54
62
|
# the ActionLink for this action
|
55
63
|
attr_accessor :link
|
56
64
|
|
57
65
|
# rarely searched columns may be placed in a hidden subgroup
|
58
|
-
|
66
|
+
def optional_columns=(optionals)
|
59
67
|
@optional_columns= Array(optionals)
|
60
68
|
end
|
61
69
|
|
62
70
|
def optional_columns
|
63
71
|
@optional_columns ||= []
|
64
72
|
end
|
73
|
+
|
74
|
+
# columns which should support or searches
|
75
|
+
# eg like 'x' or ... like 'y'
|
76
|
+
def or_columns=(or_columns)
|
77
|
+
@or_columns = Array(or_columns)
|
78
|
+
end
|
79
|
+
|
80
|
+
def or_columns
|
81
|
+
unless @or_columns
|
82
|
+
self.or_columns = @core.columns.collect{|c| c.name if @core.columns._inheritable.include?(c.name) and c.searchable? and c.column and c.column.text?}.compact
|
83
|
+
end
|
84
|
+
@or_columns
|
85
|
+
end
|
65
86
|
|
66
87
|
# default search params
|
67
88
|
# default_params = {:title => {"from"=>"test", "to"=>"", "opt"=>"%?%"}}
|
@@ -181,6 +181,17 @@ module ActiveScaffold::DataStructures
|
|
181
181
|
# to modify the default order of columns
|
182
182
|
attr_accessor :weight
|
183
183
|
|
184
|
+
# whether the field should be stripped when search values or form values are read for this value
|
185
|
+
attr_writer :stripable
|
186
|
+
def stripable?
|
187
|
+
@stripable
|
188
|
+
end
|
189
|
+
|
190
|
+
def stripped_value(value)
|
191
|
+
stripable? ? value.strip : value
|
192
|
+
end
|
193
|
+
|
194
|
+
|
184
195
|
# to set how many associated records a column with plural association must show in list
|
185
196
|
cattr_accessor :associated_limit
|
186
197
|
@@associated_limit = 3
|
@@ -228,6 +239,11 @@ module ActiveScaffold::DataStructures
|
|
228
239
|
def plural_association?
|
229
240
|
self.association and [:has_many, :has_and_belongs_to_many].include? self.association.macro
|
230
241
|
end
|
242
|
+
|
243
|
+
def belongs_to_association?
|
244
|
+
self.association && self.association.macro == :belongs_to
|
245
|
+
end
|
246
|
+
|
231
247
|
def through_association?
|
232
248
|
self.association and self.association.options[:through]
|
233
249
|
end
|
@@ -278,6 +294,7 @@ module ActiveScaffold::DataStructures
|
|
278
294
|
@options = {:format => :i18n_number} if @column.try(:number?)
|
279
295
|
@form_ui = :checkbox if @column and @column.type == :boolean
|
280
296
|
@form_ui = :textarea if @column and @column.type == :text
|
297
|
+
@stripable = true if @column and @column.text?
|
281
298
|
@allow_add_existing = true
|
282
299
|
@form_ui = self.class.association_form_ui if @association && self.class.association_form_ui
|
283
300
|
|
@@ -311,7 +328,7 @@ module ActiveScaffold::DataStructures
|
|
311
328
|
self.sort = false
|
312
329
|
else
|
313
330
|
if self.singular_association?
|
314
|
-
self.sort = {:method => "#{self.name}.to_label"}
|
331
|
+
self.sort = {:method => "#{self.name}.nil? ? '' : #{self.name}.to_label"}
|
315
332
|
elsif self.plural_association?
|
316
333
|
self.sort = {:method => "#{self.name}.join(',')"}
|
317
334
|
else
|
@@ -322,7 +339,7 @@ module ActiveScaffold::DataStructures
|
|
322
339
|
|
323
340
|
def initialize_search_sql
|
324
341
|
self.search_sql = unless self.virtual?
|
325
|
-
if association.nil?
|
342
|
+
if association.nil? || self.belongs_to_association?
|
326
343
|
self.field.to_s
|
327
344
|
elsif !self.polymorphic_association?
|
328
345
|
[association.klass.table_name, association.klass.primary_key].collect! do |str|
|
@@ -83,21 +83,28 @@ module ActiveScaffold
|
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
86
|
+
|
86
87
|
def condition_for_range(column, value, like_pattern = nil)
|
87
88
|
if !value.is_a?(Hash)
|
88
89
|
if column.column.nil? || column.column.text?
|
89
|
-
["#{column.search_sql} #{ActiveScaffold::Finder.like_operator} ?", like_pattern.sub('?', value)]
|
90
|
+
["#{column.search_sql} #{ActiveScaffold::Finder.like_operator} ?", like_pattern.sub('?', column.stripped_value(value))]
|
90
91
|
else
|
91
92
|
["#{column.search_sql} = ?", column.column.type_cast(value)]
|
92
93
|
end
|
93
94
|
elsif value[:from].blank?
|
94
95
|
nil
|
95
96
|
elsif ActiveScaffold::Finder::StringComparators.values.include?(value[:opt])
|
96
|
-
|
97
|
+
if(active_scaffold_config.field_search.or_columns.include? column.name)
|
98
|
+
search_values = column.stripped_value(value[:from]).split(active_scaffold_config.field_search.or_delimiter).compact
|
99
|
+
sql_prepared_statement = search_values.collect {|search_value| "#{column.search_sql} #{ActiveScaffold::Finder.like_operator} ?"}.join(' OR ')
|
100
|
+
[sql_prepared_statement] + search_values.collect{|search_value| value[:opt].sub('?', column.stripped_value(search_value))}
|
101
|
+
else
|
102
|
+
["#{column.search_sql} #{ActiveScaffold::Finder.like_operator} ?", value[:opt].sub('?', column.stripped_value(value[:from]))]
|
103
|
+
end
|
97
104
|
elsif value[:opt] == 'BETWEEN'
|
98
|
-
["#{column.search_sql} BETWEEN ? AND ?", value[:from], value[:to]]
|
105
|
+
["#{column.search_sql} BETWEEN ? AND ?", column.stripped_value(value[:from]), column.stripped_value(value[:to])]
|
99
106
|
elsif ActiveScaffold::Finder::NumericComparators.include?(value[:opt])
|
100
|
-
["#{column.search_sql} #{value[:opt]} ?", value[:from]]
|
107
|
+
["#{column.search_sql} #{value[:opt]} ?", column.stripped_value(value[:from])]
|
101
108
|
else
|
102
109
|
nil
|
103
110
|
end
|
@@ -243,7 +250,7 @@ module ActiveScaffold
|
|
243
250
|
return record
|
244
251
|
end
|
245
252
|
|
246
|
-
# returns a
|
253
|
+
# returns a records relation for the current page
|
247
254
|
# options may include:
|
248
255
|
# * :sorting - a Sorting DataStructure (basically an array of hashes of field => direction, e.g. [{:field1 => 'asc'}, {:field2 => 'desc'}]). please note that multi-column sorting has some limitations: if any column in a multi-field sort uses method-based sorting, it will be ignored. method sorting only works for single-column sorting.
|
249
256
|
# * :per_page
|
@@ -256,6 +263,7 @@ module ActiveScaffold
|
|
256
263
|
full_includes = (active_scaffold_includes.blank? ? nil : active_scaffold_includes)
|
257
264
|
options[:per_page] ||= 999999999
|
258
265
|
options[:page] ||= 1
|
266
|
+
#TODO not supported by kaminari
|
259
267
|
options[:count_includes] ||= full_includes unless search_conditions.nil?
|
260
268
|
|
261
269
|
klass = beginning_of_chain
|
@@ -264,37 +272,19 @@ module ActiveScaffold
|
|
264
272
|
finder_options = { :order => options[:sorting].try(:clause),
|
265
273
|
:where => search_conditions,
|
266
274
|
:joins => joins_for_finder,
|
267
|
-
:includes => options[:
|
275
|
+
:includes => add_association_to_includes_for_sorting(options[:sorting], full_includes)}
|
268
276
|
|
269
277
|
|
270
278
|
finder_options.merge! custom_finder_options
|
271
279
|
|
272
|
-
# NOTE: we must use :include in the count query, because some conditions may reference other tables
|
273
|
-
count_query = append_to_query(klass, finder_options.reject{|k, v| [:select, :order].include?(k)})
|
274
|
-
count = count_query.count unless options[:pagination] == :infinite
|
275
|
-
|
276
|
-
# Converts count to an integer if ActiveRecord returned an OrderedHash
|
277
|
-
# that happens when finder_options contains a :group key
|
278
|
-
count = count.length if count.is_a? ActiveSupport::OrderedHash
|
279
|
-
|
280
|
-
full_includes = add_association_to_includes_for_sorting(options[:sorting], full_includes)
|
281
|
-
|
282
|
-
finder_options.merge! :includes => full_includes
|
283
|
-
|
284
280
|
# we build the paginator differently for method- and sql-based sorting
|
285
|
-
if options[:sorting]
|
286
|
-
|
287
|
-
sorted_collection = sort_collection_by_column(append_to_query(klass, finder_options).all, *options[:sorting].first)
|
288
|
-
sorted_collection = sorted_collection.slice(offset, per_page) if options[:pagination]
|
289
|
-
sorted_collection
|
290
|
-
end
|
281
|
+
records = if options[:sorting] && options[:sorting].sorts_by_method?
|
282
|
+
Kaminari.paginate_array(sort_collection_by_column(append_to_query(klass, finder_options).all, *options[:sorting].first))
|
291
283
|
else
|
292
|
-
|
293
|
-
finder_options.merge!(:offset => offset, :limit => per_page) if options[:pagination]
|
294
|
-
append_to_query(klass, finder_options).all
|
295
|
-
end
|
284
|
+
append_to_query(klass, finder_options)
|
296
285
|
end
|
297
|
-
|
286
|
+
records = records.page(options[:page]).per(options[:per_page]) if options[:pagination]
|
287
|
+
records
|
298
288
|
end
|
299
289
|
|
300
290
|
# if someone excludes association from includes in configuration
|
@@ -349,7 +339,6 @@ module ActiveScaffold
|
|
349
339
|
|
350
340
|
# TODO: this should reside on the column, not the controller
|
351
341
|
def sort_collection_by_column(collection, column, order)
|
352
|
-
Rails.logger.info("das hier ja was bin im sort_collection")
|
353
342
|
sorter = column.sort[:method]
|
354
343
|
collection = collection.sort_by { |record|
|
355
344
|
value = (sorter.is_a? Proc) ? record.instance_eval(&sorter) : record.instance_eval(sorter)
|