activeadmin_addons 0.11.0 → 0.12.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/javascripts/activeadmin_addons/all.js.coffee +1 -0
- data/app/assets/javascripts/activeadmin_addons/selected-list.js +110 -0
- data/app/assets/stylesheets/activeadmin_addons/all.scss +1 -0
- data/app/assets/stylesheets/selected-list.scss +31 -0
- data/app/inputs/ajax_filter_input.rb +7 -1
- data/app/inputs/selected_list_input.rb +94 -0
- data/app/inputs/tags_input.rb +2 -2
- data/lib/activeadmin_addons/version.rb +1 -1
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f7b657178df2d8d9aa225ff46d4cd07e178a82e1
|
4
|
+
data.tar.gz: c439b4bb6dc8835f8264d80f9bad2e9786860551
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a3f1a38e47deaac87e470163dc80056f89cb1b446cc5c834f94883d541ce3d757041ed2dea7bbdf619f8ff5eb7005bbc3fc0f3e36c781d49eea612ec87fa89a2
|
7
|
+
data.tar.gz: 355f3a995e4771798d5ac0667037b45e356cab4541a98545587f7e33013f4b3886e137d147f586699ac9a8d8b2a444d9e85176457a2f2b32e2f646d9aff26310
|
@@ -0,0 +1,110 @@
|
|
1
|
+
//= require select2
|
2
|
+
//= require_self
|
3
|
+
|
4
|
+
$(function() {
|
5
|
+
setupSelectedList(document);
|
6
|
+
|
7
|
+
$(document).on('has_many_add:after', function(event, container){
|
8
|
+
setupSelectedList(container);
|
9
|
+
});
|
10
|
+
|
11
|
+
function setupSelectedList(container) {
|
12
|
+
$('.selected-list-container').click(function(event) {
|
13
|
+
var item = $(event.target);
|
14
|
+
if (item.hasClass('selected-item')) {
|
15
|
+
item.remove();
|
16
|
+
}
|
17
|
+
});
|
18
|
+
|
19
|
+
$('.selected-list', container).each(function(i, el) {
|
20
|
+
var url = $(el).data('url'),
|
21
|
+
fields = $(el).data('fields'),
|
22
|
+
displayName = $(el).data('display_name'),
|
23
|
+
width = $(el).data('width') || '100%',
|
24
|
+
method = $(el).data('method'),
|
25
|
+
model = $(el).data('model'),
|
26
|
+
prefix = model + '_' + method,
|
27
|
+
responseRoot = $(el).data('response_root'),
|
28
|
+
minimumInputLength = $(el).data('minimum_input_length'),
|
29
|
+
order = $(el).data('order') || (fields[0] + '_desc');
|
30
|
+
|
31
|
+
|
32
|
+
var selectOptions = {
|
33
|
+
width: width,
|
34
|
+
minimumInputLength: minimumInputLength,
|
35
|
+
allowClear: true,
|
36
|
+
multiple: true,
|
37
|
+
createSearchChoice: function() { return null; },
|
38
|
+
ajax: {
|
39
|
+
url: url,
|
40
|
+
dataType: 'json',
|
41
|
+
delay: 250,
|
42
|
+
cache: true,
|
43
|
+
data: function(term) {
|
44
|
+
var textQuery = { m: 'or' };
|
45
|
+
fields.forEach(function(field) {
|
46
|
+
textQuery[field + '_contains'] = term;
|
47
|
+
});
|
48
|
+
|
49
|
+
var query = {
|
50
|
+
order: order,
|
51
|
+
q: {
|
52
|
+
groupings: [textQuery],
|
53
|
+
combinator: 'and'
|
54
|
+
}
|
55
|
+
};
|
56
|
+
|
57
|
+
return query;
|
58
|
+
},
|
59
|
+
results: function(data, page) {
|
60
|
+
if(data.constructor == Object) {
|
61
|
+
data = data[responseRoot];
|
62
|
+
}
|
63
|
+
|
64
|
+
return {
|
65
|
+
results: jQuery.map(data, function(resource) {
|
66
|
+
return {
|
67
|
+
id: resource.id,
|
68
|
+
text: resource[displayName].toString()
|
69
|
+
};
|
70
|
+
})
|
71
|
+
};
|
72
|
+
},
|
73
|
+
},
|
74
|
+
};
|
75
|
+
|
76
|
+
function onItemSelected(event) {
|
77
|
+
var selectedItemsContainer = $("[id='" + prefix + "_selected_values']"),
|
78
|
+
itemName = model + '[' + method + '][]',
|
79
|
+
itemId = prefix + '_' + event.val;
|
80
|
+
|
81
|
+
if ($("#" + itemId).length > 0) {
|
82
|
+
return;
|
83
|
+
}
|
84
|
+
|
85
|
+
var item = $('<div>' + event.object.text + '</div>').attr({
|
86
|
+
class: 'selected-item',
|
87
|
+
id: itemId,
|
88
|
+
});
|
89
|
+
|
90
|
+
var hidden_input = $('<input>').attr({
|
91
|
+
name: itemName,
|
92
|
+
type: 'hidden',
|
93
|
+
value: event.val
|
94
|
+
});
|
95
|
+
|
96
|
+
item.appendTo(selectedItemsContainer);
|
97
|
+
hidden_input.appendTo(item);
|
98
|
+
}
|
99
|
+
|
100
|
+
function onSelectClosed() {
|
101
|
+
$(el).select2('val', '');
|
102
|
+
}
|
103
|
+
|
104
|
+
$(el).on('select2-selecting', onItemSelected);
|
105
|
+
$(el).on('select2-close', onSelectClosed);
|
106
|
+
|
107
|
+
$(el).select2(selectOptions);
|
108
|
+
});
|
109
|
+
}
|
110
|
+
});
|
@@ -0,0 +1,31 @@
|
|
1
|
+
$selected-list-btn-color: #AAA;
|
2
|
+
$selected-list-btn-hover-color: #333;
|
3
|
+
|
4
|
+
.selected-list-label {
|
5
|
+
display: inline-block;
|
6
|
+
}
|
7
|
+
|
8
|
+
.selected-list-container {
|
9
|
+
display: inline-block;
|
10
|
+
width: 80%;
|
11
|
+
|
12
|
+
.selected-item {
|
13
|
+
height: 25px;
|
14
|
+
}
|
15
|
+
}
|
16
|
+
|
17
|
+
.selected-item {
|
18
|
+
display: table;
|
19
|
+
cursor: pointer;
|
20
|
+
|
21
|
+
&::before {
|
22
|
+
color: $selected-list-btn-color;
|
23
|
+
content: '\2716\00a0\00a0';
|
24
|
+
}
|
25
|
+
|
26
|
+
&:hover {
|
27
|
+
&::before {
|
28
|
+
color: $selected-list-btn-hover-color;
|
29
|
+
}
|
30
|
+
}
|
31
|
+
}
|
@@ -31,7 +31,13 @@ class AjaxFilterInput < Formtastic::Inputs::StringInput
|
|
31
31
|
|
32
32
|
# rubocop:disable Style/RescueModifier
|
33
33
|
def get_selected_value(display_name)
|
34
|
-
|
34
|
+
association_name = method.to_s.chomp("_id")
|
35
|
+
association = @object.klass.reflect_on_association(association_name)
|
36
|
+
if association.options && association.options.keys.include?(:class_name)
|
37
|
+
filter_class = association.options[:class_name].constantize rescue @object.klass
|
38
|
+
else
|
39
|
+
filter_class = association_name.classify.constantize rescue @object.klass
|
40
|
+
end
|
35
41
|
selected_value = @object.conditions.find { |c| c.attributes.map(&:name).include?(method.to_s) }.values.first.value rescue nil
|
36
42
|
filter_class.find(selected_value).send(display_name) if !!selected_value
|
37
43
|
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
class SelectedListInput < Formtastic::Inputs::StringInput
|
2
|
+
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
3
|
+
def input_html_options
|
4
|
+
opts = {}
|
5
|
+
opts[:class] = ["selected-list"].concat([@options[:class]] || []).join(' ')
|
6
|
+
opts["data-model"] = model_name
|
7
|
+
opts["data-method"] = method
|
8
|
+
opts["data-url"] = @options[:url] || build_url
|
9
|
+
opts["data-response_root"] = @options[:response_root] || opts["data-url"].split('/').last
|
10
|
+
opts["data-fields"] = (@options[:fields] || ["name"]).to_json
|
11
|
+
opts["data-display_name"] = @options[:display_name] || "name"
|
12
|
+
opts["data-minimum_input_length"] = @options[:minimum_input_length] || 1
|
13
|
+
opts["data-width"] = @options[:width] if @options[:width]
|
14
|
+
opts["data-order"] = @options[:order_by] if @options[:order_by]
|
15
|
+
super.merge(opts)
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_html
|
19
|
+
input_wrapping do
|
20
|
+
[
|
21
|
+
builder.label(translated_attribute(method), class: "selected-list-label"),
|
22
|
+
render_control_wrapper
|
23
|
+
].flatten.join("\n").html_safe
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def render_control_wrapper
|
28
|
+
template.content_tag(:div, class: "selected-list-container") do
|
29
|
+
template.content_tag(label_html)
|
30
|
+
template.concat(render_items_list)
|
31
|
+
template.concat(builder.text_field(virtual_attr, input_html_options))
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def render_items_list
|
36
|
+
prefix = "#{model_name}_#{method}"
|
37
|
+
attr_name = "#{model_name}[#{method}][]"
|
38
|
+
template.content_tag(:div, id: "#{prefix}_selected_values", class: "selected-values") do
|
39
|
+
template.concat(
|
40
|
+
builder.hidden_field(method, id: "#{prefix}_empty", name: attr_name, value: nil)
|
41
|
+
)
|
42
|
+
@object.send(method).each do |item_id|
|
43
|
+
template.concat(render_item_label(prefix, attr_name, item_id))
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def render_item_label(prefix, attr_name, item_id)
|
49
|
+
attr_id = "#{prefix}_#{item_id}"
|
50
|
+
div_config = { id: attr_id, class: "selected-item" }
|
51
|
+
template.content_tag(:div, div_config) do
|
52
|
+
template.concat(item_label(item_id))
|
53
|
+
template.concat(builder.hidden_field(nil, id: nil, name: attr_name, value: item_id))
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def item_label(item_id)
|
58
|
+
selected_items.find { |item| item.id == item_id }.send(@options[:display_name] || "name")
|
59
|
+
end
|
60
|
+
|
61
|
+
def selected_items
|
62
|
+
@selected_items ||= @object.send(relation_name)
|
63
|
+
end
|
64
|
+
|
65
|
+
def translated_attribute(attribute)
|
66
|
+
@object.class.human_attribute_name(attribute)
|
67
|
+
end
|
68
|
+
|
69
|
+
def model_name
|
70
|
+
@object.class.to_s.underscore.tr('/', '_')
|
71
|
+
end
|
72
|
+
|
73
|
+
def virtual_attr
|
74
|
+
attr_name = "#{method}_str".to_sym
|
75
|
+
@object.singleton_class.send(:attr_accessor, attr_name) unless @object.respond_to?(attr_name)
|
76
|
+
attr_name
|
77
|
+
end
|
78
|
+
|
79
|
+
def build_url
|
80
|
+
url = ["/"]
|
81
|
+
|
82
|
+
if ActiveAdmin.application.default_namespace.present?
|
83
|
+
url << "#{ActiveAdmin.application.default_namespace}/"
|
84
|
+
end
|
85
|
+
|
86
|
+
url << relation_name
|
87
|
+
|
88
|
+
url.join("")
|
89
|
+
end
|
90
|
+
|
91
|
+
def relation_name
|
92
|
+
method.to_s.chomp("_ids").tableize
|
93
|
+
end
|
94
|
+
end
|
data/app/inputs/tags_input.rb
CHANGED
@@ -30,7 +30,7 @@ class TagsInput < Formtastic::Inputs::StringInput
|
|
30
30
|
input_wrapping do
|
31
31
|
[
|
32
32
|
label_html,
|
33
|
-
|
33
|
+
render_selected_hidden_items,
|
34
34
|
builder.text_field(virtual_input_name, relation_tag_options)
|
35
35
|
].flatten.join("\n").html_safe
|
36
36
|
end
|
@@ -68,7 +68,7 @@ class TagsInput < Formtastic::Inputs::StringInput
|
|
68
68
|
attr_name.to_sym
|
69
69
|
end
|
70
70
|
|
71
|
-
def
|
71
|
+
def render_selected_hidden_items
|
72
72
|
prefix = "#{model_name}_#{method}"
|
73
73
|
attr_name = "#{model_name}[#{method}][]"
|
74
74
|
template.content_tag(:div, id: "#{prefix}_selected_values") do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activeadmin_addons
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.12.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Platanus
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2017-
|
14
|
+
date: 2017-05-28 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: railties
|
@@ -373,15 +373,18 @@ files:
|
|
373
373
|
- app/assets/javascripts/activeadmin_addons/config.js
|
374
374
|
- app/assets/javascripts/activeadmin_addons/date-time-picker.js
|
375
375
|
- app/assets/javascripts/activeadmin_addons/select2.js
|
376
|
+
- app/assets/javascripts/activeadmin_addons/selected-list.js
|
376
377
|
- app/assets/javascripts/palette-color-picker.js
|
377
378
|
- app/assets/stylesheets/activeadmin_addons/all.scss
|
378
379
|
- app/assets/stylesheets/palette-color-picker.scss
|
380
|
+
- app/assets/stylesheets/selected-list.scss
|
379
381
|
- app/inputs/ajax_filter_input.rb
|
380
382
|
- app/inputs/color_picker_input.rb
|
381
383
|
- app/inputs/date_time_picker_input.rb
|
382
384
|
- app/inputs/nested_select_input.rb
|
383
385
|
- app/inputs/range_select_input.rb
|
384
386
|
- app/inputs/search_select_input.rb
|
387
|
+
- app/inputs/selected_list_input.rb
|
385
388
|
- app/inputs/tags_input.rb
|
386
389
|
- lib/activeadmin_addons.rb
|
387
390
|
- lib/activeadmin_addons/active_admin_config.rb
|
@@ -420,7 +423,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
420
423
|
version: '0'
|
421
424
|
requirements: []
|
422
425
|
rubyforge_project:
|
423
|
-
rubygems_version: 2.
|
426
|
+
rubygems_version: 2.6.12
|
424
427
|
signing_key:
|
425
428
|
specification_version: 4
|
426
429
|
summary: Set of addons to help with the activeadmin ui
|