activeadmin_addons 0.2.8 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 86137e56876a2c8cd92c7a5426a2d30d68e52106
4
- data.tar.gz: 27ec4aae8a07fcebab1cf94ea4f08400e20ba2ef
3
+ metadata.gz: d37787a741c58cce776cf85504379aae6eba7f4f
4
+ data.tar.gz: d0d8b6bdb18ed9d4b096d71994d4f766f3d771a8
5
5
  SHA512:
6
- metadata.gz: 5fc25ec8546c1c0176a2eaadb5646b0d0f0d62a6324816aa354c3c117a9ec9b1d51145a4df991171349b8005965a0e16783ec3a03d00674492f98b39f9770f1b
7
- data.tar.gz: d17dfcde0451c88c888cd4fb24c39f944f28ba3e93275c2b0d76a35297d1f909bee9f241cf9f90f9721aedd77f0945edb28f1490db518777eec27e2ed7e257af
6
+ metadata.gz: ec3fc574dc04e37b47e927561f6f7756ecb0b5c35c8f06e992ad1fe948c8b7c5091ff6d6400b587fd93bc320feb05977f00c4bc236202e4e778e77d2e07611ea
7
+ data.tar.gz: 043c5e56dbc3ce545e5264caf05ef8142fd634390b14bc842c5046ed5b1a2bdcdd58f33c0c77445028e3f60ca83b71eba60d4fbd5dd360b0df6b384d98e415cb
@@ -8,6 +8,8 @@ $(function() {
8
8
  $(document).on('has_many_add:after', setupSelect2);
9
9
 
10
10
  function setupSelect2() {
11
+ var INVALID_PARENT_ID = -1;
12
+
11
13
  $('.select2-tags').each(function(i, el) {
12
14
  $(el).select2({
13
15
  width: '80%',
@@ -27,53 +29,109 @@ $(function() {
27
29
  }
28
30
  });
29
31
 
32
+
30
33
  $('.select2-ajax').each(function(i, el) {
31
34
  var url = $(el).data('url');
32
35
  var fields = $(el).data('fields');
33
36
  var displayName = $(el).data('display_name');
37
+ var parent = $(el).data('parent');
38
+ var model = $(el).data('model');
39
+ var collection = $(el).data('collection');
34
40
  var minimumInputLength = $(el).data('minimum_input_length');
35
- var order = fields[0] + "_desc";
41
+ var order = fields[0] + '_desc';
42
+ var parentId = $(el).data('parent_id') || INVALID_PARENT_ID;
43
+ var selectInstance;
36
44
 
37
- $(el).select2({
45
+ var ajaxOptions = {
46
+ url: url,
47
+ dataType: 'json',
48
+ delay: 250,
49
+ data: function(term) {
50
+ var textQuery = { m: 'or' };
51
+ fields.forEach(function(field) {
52
+ textQuery[field + '_contains'] = term;
53
+ });
54
+
55
+ var query = {
56
+ order: order,
57
+ q: {
58
+ groupings: [textQuery],
59
+ combinator: 'and'
60
+ }
61
+ };
62
+
63
+ if (!!parent) {
64
+ query.q[parent + '_eq'] = parentId;
65
+ }
66
+
67
+ return query;
68
+ },
69
+ results: function(data, page) {
70
+ return {
71
+ results: jQuery.map(data, function(resource) {
72
+ return {
73
+ id: resource.id,
74
+ text: resource[displayName].toString()
75
+ };
76
+ })
77
+ };
78
+ },
79
+ cache: true
80
+ };
81
+
82
+ var collectionOptions = function(query) {
83
+ var data = { results: [] };
84
+
85
+ collection.forEach(function(record) {
86
+ var matched = fields.some(function(field) {
87
+ var regex = new RegExp(query.term, 'i');
88
+ return !!record[field] && !!record[field].match(regex);
89
+ });
90
+
91
+ if((!parent || record[parent] == parentId) && matched) {
92
+ data.results.push({ id: record.id, text: record[displayName].toString() });
93
+ }
94
+ });
95
+
96
+ query.callback(data);
97
+ };
98
+
99
+ var select2Config = {
38
100
  width: '80%',
101
+ containerCssClass: 'nested-select-container',
102
+ minimumInputLength: minimumInputLength,
39
103
  initSelection: function(element, callback) {
40
104
  var id = $(element).val();
41
- var text = $(element).data("selected") || "";
105
+ var text = $(element).data('selected') || '';
106
+ $(element).data('selected', '');
107
+
42
108
  callback({
43
109
  id: id,
44
110
  text: text
45
111
  });
46
- },
47
- ajax: {
48
- url: url,
49
- dataType: 'json',
50
- delay: 250,
51
- data: function (term) {
52
- var query = {m: "or"};
53
- fields.forEach(function(field) {
54
- query[field + "_contains"] = term;
55
- });
56
-
57
- return {
58
- order: order,
59
- q: query
60
- };
61
- },
62
- results: function (data, page) {
63
- return {
64
- results: jQuery.map(data, function(resource) {
65
- return {
66
- id: resource.id,
67
- text: resource[displayName]
68
- };
69
- })
70
- };
71
- },
72
- cache: true
73
- },
74
- minimumInputLength: minimumInputLength
75
- });
112
+ }
113
+ };
114
+
115
+ if (!!parent) {
116
+ var parentSelector = '#' + model + '_' + parent;
117
+
118
+ $(parentSelector).on('change', function(e) {
119
+ selectInstance.val(null).trigger('change');
120
+ parentId = e.val;
121
+
122
+ if(!parentId) {
123
+ parentId = INVALID_PARENT_ID;
124
+ }
125
+ });
126
+ }
127
+
128
+ if (collection) {
129
+ select2Config.query = collectionOptions;
130
+ } else {
131
+ select2Config.ajax = ajaxOptions;
132
+ }
133
+
134
+ selectInstance = $(el).select2(select2Config);
76
135
  });
77
136
  }
78
-
79
137
  });
@@ -11,3 +11,13 @@
11
11
  width: 12px;
12
12
  }
13
13
  }
14
+
15
+ .nested_select {
16
+ .nested-select-container {
17
+ margin-bottom: 20px;
18
+
19
+ &:last-of-type {
20
+ margin-bottom: 0px;
21
+ }
22
+ }
23
+ }
@@ -0,0 +1,144 @@
1
+ class NestedSelectInput < Formtastic::Inputs::StringInput
2
+ def to_html
3
+ html_elems = []
4
+
5
+ for_each_level do |level_data|
6
+ a = level_data[:attribute]
7
+ set_parent_value(level_data)
8
+ html_elems << builder.text_field(a, select_html_options(level_data))
9
+ html_elems << builder.label(a, translated_attribute(a))
10
+ end
11
+
12
+ input_wrapping do
13
+ html_elems.reverse.join("\n").html_safe
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def for_each_level
20
+ hierarchy = get_hierarchy
21
+ hierarchy_count = hierarchy.count
22
+
23
+ hierarchy.each_with_index do |level_data, idx|
24
+ next_idx = idx + 1
25
+ parent_level_data = hierarchy[next_idx] if hierarchy_count != next_idx
26
+ level_data[:parent_attribute] = parent_level_data[:attribute] if parent_level_data
27
+
28
+ yield(level_data)
29
+ end
30
+ end
31
+
32
+ def get_hierarchy
33
+ hierarchy = []
34
+ levels = @options.keys.select { |key| key.to_s.match(/level_[1-9]$/) }
35
+ reversed_levels = levels.reverse
36
+
37
+ reversed_levels.each_with_index do |level_key, idx|
38
+ previous_level_key = reversed_levels[idx + 1]
39
+ validate_level_data!(level_key, previous_level_key)
40
+ hierarchy << @options[level_key]
41
+ end
42
+
43
+ raise("Undefined levels on nested_select") if hierarchy.empty?
44
+
45
+ hierarchy
46
+ end
47
+
48
+ def validate_level_data!(level_key, previous_level_key)
49
+ current_level_number = get_level_number(level_key)
50
+ previous_level_number = get_level_number(previous_level_key)
51
+
52
+ if !(current_level_number == previous_level_number + 1)
53
+ raise("Missing :level_#{current_level_number - 1} key")
54
+ end
55
+
56
+ attribute = @options[level_key][:attribute]
57
+ raise("Missing mandatory attribute level_key on #{level_key}") unless attribute
58
+ end
59
+
60
+ def get_level_number(level_key)
61
+ level_key.to_s.split("_").last.to_i
62
+ end
63
+
64
+ def select_html_options(level)
65
+ attribute = level[:attribute]
66
+ instance = instance_from_attribute_name(attribute)
67
+
68
+ opts = {}
69
+ opts["class"] = select_classes(level)
70
+ opts["data-fields"] = get_option(level, :fields, ["name"]).to_json
71
+ opts["data-model"] = model_name
72
+ opts["data-display_name"] = get_option(level, :display_name, "name")
73
+ opts["data-minimum_input_length"] = get_option(level, :minimum_input_length, 1)
74
+ opts["data-collection"] = (level[:collection] || nil).to_json
75
+
76
+ opts["id"] = build_select_id(attribute)
77
+ opts["data-url"] = build_url(attribute)
78
+ opts["data-selected"] = instance.try(opts["data-display_name"])
79
+
80
+ opts.merge(select_html_parent_options(level[:parent_attribute]))
81
+ end
82
+
83
+ def select_html_parent_options(parent_attribute)
84
+ opts = {}
85
+ return opts unless parent_attribute
86
+ opts["data-parent"] = parent_attribute
87
+ opts["data-parent_id"] = @object.send(parent_attribute)
88
+ opts
89
+ end
90
+
91
+ def select_classes(level_data)
92
+ ['select2-ajax'].concat(get_option(level_data, :class, [])).join(' ')
93
+ end
94
+
95
+ def model_name
96
+ @object.class.to_s.downcase
97
+ end
98
+
99
+ def build_select_id(attribute)
100
+ [@object.class.to_s.downcase, attribute.to_s].join("_")
101
+ end
102
+
103
+ def get_option(level_data, option, default)
104
+ level_data[option] || @options[option] || default
105
+ end
106
+
107
+ def set_parent_value(level_data)
108
+ parent_attribute = level_data[:parent_attribute]
109
+ add_virtual_accessor(parent_attribute)
110
+ instance = instance_from_attribute_name(level_data[:attribute])
111
+ if instance && instance.respond_to?(parent_attribute)
112
+ @object.send("#{parent_attribute}=", instance.send(parent_attribute))
113
+ end
114
+ end
115
+
116
+ def instance_from_attribute_name(attribute)
117
+ return unless attribute
118
+ attribute_value = @object.send(attribute)
119
+ return unless attribute_value
120
+ klass = attribute.to_s.humanize.constantize
121
+ klass.find_by_id(attribute_value)
122
+ end
123
+
124
+ def add_virtual_accessor(attribute)
125
+ return unless attribute
126
+ @object.singleton_class.send(:attr_accessor, attribute) unless @object.respond_to?(attribute)
127
+ end
128
+
129
+ def translated_attribute(attribute)
130
+ @object.class.human_attribute_name(attribute)
131
+ end
132
+
133
+ def build_url(attribute)
134
+ url = ["/"]
135
+
136
+ if ActiveAdmin.application.default_namespace.present?
137
+ url << "#{ActiveAdmin.application.default_namespace}/"
138
+ end
139
+
140
+ url << attribute.to_s.humanize.tableize
141
+
142
+ url.join("")
143
+ end
144
+ end
@@ -2,7 +2,7 @@ class SearchSelectInput < Formtastic::Inputs::StringInput
2
2
  def input_html_options
3
3
  relation = @object.send(attributized_method_name)
4
4
  opts = {}
5
- opts[:class] = "select2-ajax"
5
+ opts[:class] = ['select2-ajax'].concat([@options[:class]] || []).join(' ')
6
6
  opts["data-fields"] = (@options[:fields] || []).to_json
7
7
  opts["data-url"] = @options[:url] || ""
8
8
  opts["data-display_name"] = @options[:display_name] || "name"
@@ -11,4 +11,3 @@ class SearchSelectInput < Formtastic::Inputs::StringInput
11
11
  super.merge opts
12
12
  end
13
13
  end
14
-
@@ -1,3 +1,3 @@
1
1
  module ActiveadminAddons
2
- VERSION = "0.2.8"
2
+ VERSION = "0.3.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activeadmin_addons
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.8
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Platanus
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-10-23 00:00:00.000000000 Z
11
+ date: 2016-01-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -348,7 +348,8 @@ files:
348
348
  - app/assets/images/fileicons/file_extension_zip.png
349
349
  - app/assets/javascripts/activeadmin_addons/all.js.coffee
350
350
  - app/assets/javascripts/activeadmin_addons/select2.js
351
- - app/assets/stylesheets/activeadmin_addons/all.css.scss
351
+ - app/assets/stylesheets/activeadmin_addons/all.scss
352
+ - app/inputs/nested_select_input.rb
352
353
  - app/inputs/range_select_input.rb
353
354
  - app/inputs/search_select_input.rb
354
355
  - app/inputs/tags_input.rb