activeadmin_dynamic_fields 0.2.0 → 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
- SHA1:
3
- metadata.gz: d599f816a20b2b7068d3b7d72e7ada1002c848bf
4
- data.tar.gz: 296760d26145ceddb5e535296c1fa8a234e9781d
2
+ SHA256:
3
+ metadata.gz: 1af148e7cd9d7704c902e17fdb022acbb1c0c2012bf423f9be6e4ae92cdb6f5f
4
+ data.tar.gz: ad108b3ae42ba846251dcab61487e68809e4cfaf21e453039a7ad3cb0cb22bd8
5
5
  SHA512:
6
- metadata.gz: 28779caf4f980c64bffc0cc88e006f0d3ec9b6b1666e53f306a57e9e035c386f7c4f30d55994ee38e610bd337b6922a2470662f5c341b3ca2f77acfbf322b021
7
- data.tar.gz: e078d3ab6b1ddc26c1af8c899c4aa2a903803b59e3f2f56a331e071437fb98265efd8386653fe16f140015e2ce8070f2a7d1b65b6313167ec855d73da3b3b722
6
+ metadata.gz: 0c76b4cb42b90bf7c88c4cafbbab1bb40f8fa61efbaa8acef0cb3230c6dd2f3eea3b0bf88413431c2a275538ef7c1f37aa0463a2445f0e2a61eae17b189955b5
7
+ data.tar.gz: d09b1cfe869567e5634236a31385608800375be5cef690b5ee1c420d2cba8a5018f642c5bec0d2996078338a8bdfa0499c02d839e264b9704fb5581e5659d44d
data/README.md CHANGED
@@ -1,36 +1,37 @@
1
- # ActiveAdmin Dynamic Fields [![Gem Version](https://badge.fury.io/rb/activeadmin_dynamic_fields.svg)](https://badge.fury.io/rb/activeadmin_dynamic_fields)
1
+ # ActiveAdmin Dynamic Fields [![Gem Version](https://badge.fury.io/rb/activeadmin_dynamic_fields.svg)](https://badge.fury.io/rb/activeadmin_dynamic_fields) [![CircleCI](https://circleci.com/gh/blocknotes/activeadmin_dynamic_fields.svg?style=svg)](https://circleci.com/gh/blocknotes/activeadmin_dynamic_fields)
2
2
 
3
- An Active Admin plugin to add dynamic behaviors to fields.
3
+ An Active Admin plugin to add dynamic behaviors to some fields.
4
4
 
5
5
  Features:
6
-
7
6
  - set conditional checks on fields
8
- - trigger some actions on other fields
7
+ - trigger actions on target elements
9
8
  - inline field editing
10
9
  - create links to load some content in a dialog
11
10
 
12
- The easiest way to show how this plugin works is looking the examples [below](#examples-of-dynamic-fields).
11
+ The easiest way to show how this plugin works is looking the examples [below](#examples).
13
12
 
14
13
  ## Install
15
-
16
14
  - Add to your Gemfile: `gem 'activeadmin_dynamic_fields'`
17
15
  - Execute bundle
18
16
  - Add at the end of your ActiveAdmin javascripts (_app/assets/javascripts/active_admin.js_):
19
- `//= require activeadmin/dynamic_fields`
20
17
 
21
- ## Options
18
+ ```js
19
+ //= require activeadmin/dynamic_fields
20
+ ```
22
21
 
22
+ ## Options
23
23
  Options are passed to fields using *input_html* parameter as *data* attributes:
24
-
25
24
  - **data-if**: check a condition, values:
26
25
  + **checked**: check if a checkbox is checked
27
26
  + **not_checked**: check if a checkbox is not checked
28
27
  + **blank**: check if a field is blank
29
28
  + **not_blank**: check if a field is not blank
29
+ + **changed**: check if the value of an input is changed (dirty)
30
30
  - **data-eq**: check if a field has a specific value
31
31
  - **data-not**: check if a field hasn't a specific value
32
- - **data-target**: target css selector
33
- - **data-action**: the action to trigger, values:
32
+ - **data-target**: target css selector (from parent fieldset, look for the closest match)
33
+ - **data-gtarget**: target css selector globally
34
+ - **data-then**: the action to trigger (alias **data-action**), values:
34
35
  + **hide**: hides elements
35
36
  + **slide**: hides elements (using sliding)
36
37
  + **fade**: hides elements (using fading)
@@ -40,50 +41,51 @@ Options are passed to fields using *input_html* parameter as *data* attributes:
40
41
  - **data-function**: check the return value of a custom function
41
42
  - **data-arg**: argument passed to the custom set function (as array of strings)
42
43
 
44
+ A check condition or a custom check function are required. A trigger action is required too, unless you are using a custom function (in that case it is optional).
45
+
43
46
  ## Examples
44
47
 
45
48
  ### Dynamic fields examples
46
-
47
- - A checkbox that hides other fields if false (ex. model *Article*):
49
+ - A checkbox that hides other fields if is checked (ex. model *Article*):
48
50
 
49
51
  ```rb
50
52
  form do |f|
51
53
  f.inputs 'Article' do
52
- f.input :published, input_html: { data: { if: 'not_checked', action: 'hide', target: '.grp1' } }
54
+ f.input :published, input_html: { data: { if: 'checked', then: 'hide', target: '.grp1' } }
53
55
  f.input :online_date, wrapper_html: { class: 'grp1' }
54
- f.input :position, wrapper_html: { class: 'grp1' }
56
+ f.input :draft_notes, wrapper_html: { class: 'grp1' }
55
57
  end
56
58
  f.actions
57
59
  end
58
60
  ```
59
61
 
60
- - Add 3 classes (*first*, *second*, *third*) if a checkbox is true:
62
+ - Add 3 classes (*first*, *second*, *third*) if a checkbox is not checked:
61
63
 
62
- `f.input :published, input_html: { data: { if: 'checked', action: 'addClass first second third', target: '.grp1' } }`
64
+ `f.input :published, input_html: { data: { if: 'not_checked', then: 'addClass first second third', target: '.grp1' } }`
63
65
 
64
66
  - Set another field value if a string field is blank:
65
67
 
66
- `f.input :title, input_html: { data: { if: 'blank', action: 'setValue 10', target: '#article_position' } }`
68
+ `f.input :title, input_html: { data: { if: 'blank', then: 'setValue 10', target: '#article_position' } }`
67
69
 
68
70
  - Use a custom function for conditional check (*title_not_empty()* must be available on global scope) (with alternative syntax for data attributes):
69
71
 
70
- `f.input :title, input_html: { 'data-function': 'title_empty', 'data-action': 'slide', 'data-target': '#article_description_input' }`
72
+ `f.input :title, input_html: { 'data-function': 'title_empty', 'data-then': 'slide', 'data-target': '#article_description_input' }`
71
73
 
72
74
  ```js
73
- function title_empty( el ) {
74
- return ( $('#article_title').val().trim() === '' );
75
+ function title_empty(el) {
76
+ return ($('#article_title').val().trim() === '');
75
77
  }
76
78
  ```
77
79
 
78
80
  - Call a callback function as action:
79
81
 
80
- `f.input :published, input_html: { data: { if: 'checked', action: 'callback set_title', args: '["Unpublished !"]' } }`
82
+ `f.input :published, input_html: { data: { if: 'checked', then: 'callback set_title', args: '["Unpublished !"]' } }`
81
83
 
82
84
  ```js
83
- function set_title( args ) {
84
- if( $('#article_title').val().trim() === '' ) {
85
- $('#article_title').val( args[0] );
86
- $('#article_title').trigger( 'change' );
85
+ function set_title(args) {
86
+ if($('#article_title').val().trim() === '') {
87
+ $('#article_title').val(args[0]);
88
+ $('#article_title').trigger('change');
87
89
  }
88
90
  }
89
91
  ```
@@ -93,22 +95,21 @@ function set_title( args ) {
93
95
  `f2.input :category, as: :select, collection: [ [ 'Cat 1', 'cat1' ], [ 'Cat 2', 'cat2' ], [ 'Cat 3', 'cat3' ] ], input_html: { 'data-function': 'on_change_category' }`
94
96
 
95
97
  ```js
96
- function on_change_category( el ) {
97
- var target = el.closest( 'fieldset' ).find( '.pub' );
98
- target.prop( 'checked', ( el.val() == 'cat2' ) );
99
- target.trigger( 'change' );
98
+ function on_change_category(el) {
99
+ var target = el.closest('fieldset').find('.pub');
100
+ target.prop('checked', (el.val() == 'cat2');
101
+ target.trigger('change');
100
102
  }
101
103
  ```
102
104
 
103
- ### Inline editing example
104
-
105
+ ### Inline editing examples
105
106
  - Prepare a custom member action to save data, an *update* helper function is available (third parameter is optional, allow to filter using strong parameters):
106
107
 
107
108
  ```rb
108
109
  member_action :save, method: [:post] do
109
- render ActiveAdmin::DynamicFields::update( resource, params )
110
- # render ActiveAdmin::DynamicFields::update( resource, params, [:published] )
111
- # render ActiveAdmin::DynamicFields::update( resource, params, Article::permit_params )
110
+ render ActiveAdmin::DynamicFields.update(resource, params)
111
+ # render ActiveAdmin::DynamicFields.update(resource, params, [:published])
112
+ # render ActiveAdmin::DynamicFields.update(resource, params, Article::permit_params)
112
113
  end
113
114
  ```
114
115
 
@@ -117,29 +118,28 @@ end
117
118
  ```rb
118
119
  # Edit a string:
119
120
  column :title do |row|
120
- div row.title, ActiveAdmin::DynamicFields::edit_string( :title, save_admin_article_path( row.id ) )
121
+ div row.title, ActiveAdmin::DynamicFields.edit_string(:title, save_admin_article_path(row.id))
121
122
  end
122
123
  # Edit a boolean:
123
124
  column :published do |row|
124
- status_tag row.published, ActiveAdmin::DynamicFields::edit_boolean( :published, save_admin_article_path( row.id ), row.published )
125
+ status_tag row.published, ActiveAdmin::DynamicFields.edit_boolean(:published, save_admin_article_path(row.id), row.published)
125
126
  end
126
127
  # Edit a select ([''] allow to have a blank value):
127
128
  column :author do |row|
128
- select ActiveAdmin::DynamicFields::edit_select( :author_id, save_admin_article_path( row.id ) ) do
129
- options_for_select( [''] + Author.pluck( :name, :id ), row.author_id )
129
+ select ActiveAdmin::DynamicFields.edit_select(:author_id, save_admin_article_path(row.id)) do
130
+ options_for_select([''] + Author.pluck(:name, :id), row.author_id)
130
131
  end
131
132
  end
132
133
  ```
133
134
 
134
- - In *show* config (less useful):
135
+ - In *show* config (inside `attributes_table` block):
135
136
  ```rb
136
137
  row :title do |row|
137
- div row.title, ActiveAdmin::DynamicFields::edit_string( :title, save_admin_article_path( row.id ) )
138
+ div row.title, ActiveAdmin::DynamicFields.edit_string(:title, save_admin_article_path(row.id))
138
139
  end
139
140
  ```
140
141
 
141
142
  ### Dialog example
142
-
143
143
  Example with 2 models: *Author* and *Article*
144
144
 
145
145
  Prepare the content dialog - in Active Admin Author config:
@@ -148,12 +148,16 @@ Prepare the content dialog - in Active Admin Author config:
148
148
  ActiveAdmin.register Author do
149
149
  # ...
150
150
  member_action :dialog do
151
- content = '<dl style="margin: 12px">'
152
- [:name, :age, :created_at].each do |field|
153
- content += "<dt>#{Author.human_attribute_name(field)}:</dt><dd>#{resource[field]}</dd>"
151
+ record = resource
152
+ context = Arbre::Context.new do
153
+ dl do
154
+ %i[name age created_at].each do |field|
155
+ dt "#{Author.human_attribute_name(field)}:"
156
+ dd record[field]
157
+ end
158
+ end
154
159
  end
155
- content += '</dl>'
156
- render plain: content
160
+ render plain: context
157
161
  end
158
162
  # ...
159
163
  end
@@ -168,7 +172,7 @@ ActiveAdmin.register Article do
168
172
  attributes_table do
169
173
  # ...
170
174
  row :author do
171
- link_to object.author.name, dialog_admin_author_path( object.author ), title: object.author.name, 'data-df-dialog': true, 'data-df-icon': true
175
+ link_to object.author.name, dialog_admin_author_path(object.author), title: object.author.name, 'data-df-dialog': true, 'data-df-icon': true
172
176
  end
173
177
  end
174
178
  end
@@ -179,13 +183,13 @@ end
179
183
  The link url is loaded via AJAX before opening the dialog.
180
184
 
181
185
  ## Do you like it? Star it!
182
-
183
186
  If you use this component just star it. A developer is more motivated to improve a project when there is some interest.
184
187
 
185
- ## Contributors
188
+ Take a look at [other ActiveAdmin components](https://github.com/blocknotes?utf8=✓&tab=repositories&q=activeadmin&type=source) that I made if you are curious.
186
189
 
187
- - [Mattia Roccoberton](http://blocknot.es) - creator, maintainer
190
+ ## Contributors
191
+ - [Mattia Roccoberton](http://blocknot.es): author
192
+ - The good guys that opened issues and pull requests from time to time
188
193
 
189
194
  ## License
190
-
191
- [MIT](LICENSE.txt)
195
+ The gem is available as open-source under the terms of the [MIT](LICENSE.txt).
data/Rakefile CHANGED
@@ -1,3 +1,3 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
- require "bundler/gem_tasks"
3
+ require 'bundler/gem_tasks'
@@ -1,208 +1,199 @@
1
- // Evaluate a condition
2
- function dfEvalCondition( el, args ) {
3
- if( args.fn ) {
4
- if( args.fn && window[args.fn] ) return !window[args.fn]( el );
5
- else console.log( 'Warning - activeadmin_dynamic_fields: ' + args.fn + '() not available [1]' );
6
- }
7
- else if( args.if == 'checked' ) {
8
- return !el.is(':checked');
9
- }
10
- else if( args.if == 'not_checked' ) {
11
- return el.is(':checked');
12
- }
13
- else if( args.if == 'blank' ) {
14
- return el.val().length === 0 || !el.val().trim();
15
- }
16
- else if( args.if == 'not_blank' ) {
17
- return el.val().length !== 0 && el.val().trim();
18
- }
19
- else if( args.eq ) {
20
- return el.val() == args.eq;
21
- }
22
- else if( args.not ) {
23
- return el.val() != args.not;
24
- }
25
- return undefined;
26
- }
27
-
28
- // Prepare a field
29
- function dfSetupField( el ) {
30
- var action = el.data( 'action' );
31
- var target, args = {};
32
- args.if = el.data( 'if' );
33
- args.eq = el.data( 'eq' );
34
- args.not = el.data( 'not' );
35
- args.fn = el.data( 'function' );
36
- if( el.data( 'target' ) ) target = el.closest( 'fieldset' ).find( el.data( 'target' ) )
37
- if( action == 'hide' ) {
38
- if( dfEvalCondition( el, args ) ) target.show();
39
- else target.hide();
40
- el.on( 'change', function( event ) {
41
- if( dfEvalCondition( $(this), args ) ) target.show();
42
- else target.hide();
43
- });
44
- }
45
- else if( action == 'slide' ) {
46
- if( dfEvalCondition( el, args ) ) target.slideDown();
47
- else target.slideUp();
48
- el.on( 'change', function( event ) {
49
- if( dfEvalCondition( $(this), args ) ) target.slideDown();
50
- else target.slideUp();
51
- });
1
+ (function () {
2
+ 'use strict'
3
+
4
+ const ACTIONS = {
5
+ addClass: (el, name) => el.addClass(name),
6
+ callback: (el, name) => {
7
+ if (window[name]) window[name](el.data('args'))
8
+ else {
9
+ el.attr('data-df-errors', 'callback function not found')
10
+ console.warn(`activeadmin_dynamic_fields callback function not found: ${name}`)
11
+ }
12
+ },
13
+ fade: el => el.fadeOut(),
14
+ hide: el => el.hide(),
15
+ setValue: (el, value) => dfSetValue(el, value),
16
+ slide: el => el.slideUp()
52
17
  }
53
- else if( action == 'fade' ) {
54
- if( dfEvalCondition( el, args ) ) target.fadeIn();
55
- else target.fadeOut();
56
- el.on( 'change', function( event ) {
57
- if( dfEvalCondition( $(this), args ) ) target.fadeIn();
58
- else target.fadeOut();
59
- });
18
+
19
+ const CONDITIONS = {
20
+ blank: el => el.val().length === 0 || !el.val().trim(),
21
+ changed: _el => true,
22
+ checked: el => el.is(':checked'),
23
+ eq: (el, value) => el.val() == value,
24
+ not: (el, value) => el.val() != value,
25
+ not_blank: el => el.val().trim(),
26
+ not_checked: el => !el.is(':checked')
60
27
  }
61
- else if( action.substr( 0, 8 ) == 'setValue' ) {
62
- var val = action.substr( 8 ).trim();
63
- if( dfEvalCondition( el, args ) ) dfSetValue( target, val );
64
- el.on( 'change', function( event ) {
65
- if( dfEvalCondition( $(this), args ) ) dfSetValue( target, val );
66
- });
28
+
29
+ const REVERSE_ACTIONS = {
30
+ addClass: (el, name) => el.removeClass(name),
31
+ fade: el => el.fadeIn(),
32
+ hide: el => el.show(),
33
+ slide: el => el.slideDown()
67
34
  }
68
- else if( action.substr( 0, 8 ) == 'callback' ) {
69
- var cb = action.substr( 8 ).trim();
70
- if( cb && window[cb] ) {
71
- if( dfEvalCondition( el, args ) ) window[cb]( el.data( 'args' ) );
72
- el.on( 'change', function( event ) {
73
- if( dfEvalCondition( $(this), args ) ) window[cb]( el.data( 'args' ) );
74
- });
35
+
36
+ function dfEvalCondition(el) {
37
+ let condition = CONDITIONS[el.data('if')]
38
+ let condition_arg
39
+
40
+ if(!condition && el.data('eq')) {
41
+ condition = CONDITIONS['eq']
42
+ condition_arg = el.data('eq')
43
+ }
44
+ if(!condition && el.data('not')) {
45
+ condition = CONDITIONS['not']
46
+ condition_arg = el.data('not')
75
47
  }
76
- else console.log( 'Warning - activeadmin_dynamic_fields: ' + cb + '() not available [2]' );
48
+ if(!condition && el.data('function')) {
49
+ condition = window[el.data('function')]
50
+ if(!condition) {
51
+ el.attr('data-df-errors', 'custom function not found')
52
+ console.warn(`activeadmin_dynamic_fields custom function not found: ${el.data('function')}`)
53
+ }
54
+ }
55
+
56
+ return [condition, condition_arg]
77
57
  }
78
- else if( action.substr( 0, 8 ) == 'addClass' ) {
79
- var classes = action.substr( 8 ).trim();
80
- if( dfEvalCondition( el, args ) ) target.removeClass( classes );
81
- else target.addClass( classes );
82
- el.on( 'change', function( event ) {
83
- if( dfEvalCondition( $(this), args ) ) target.removeClass( classes );
84
- else target.addClass( classes );
85
- });
58
+
59
+ function dfInitField(el) {
60
+ const [condition, condition_arg] = dfEvalCondition(el)
61
+ const action_name = (el.data('then') || el.data('action') || '').substr(0, 8)
62
+ const action = ACTIONS[action_name]
63
+ const arg = (el.data('then') || el.data('action') || '').substr(9)
64
+ const reverse_action = REVERSE_ACTIONS[action_name]
65
+ if (typeof condition === 'undefined') return
66
+ if (typeof action === 'undefined' && !el.data('function')) return
67
+
68
+ // closest find for has many associations
69
+ let target
70
+ if (el.data('target')) target = el.closest('fieldset').find(el.data('target'))
71
+ else if (el.data('gtarget')) target = $(el.data('gtarget'))
72
+ if (action_name == 'callback') target = el
73
+
74
+ if (condition(el, condition_arg) && el.data('if') != 'changed') action(target, arg)
75
+ else if (reverse_action) reverse_action(target, arg)
76
+
77
+ el.on('change', () => {
78
+ if (condition(el, condition_arg)) action(target, arg)
79
+ else if (reverse_action) reverse_action(target, arg)
80
+ })
86
81
  }
87
- else if( args.fn ) { // function without action
88
- dfEvalCondition( el, args );
89
- el.on( 'change', function( event ) {
90
- dfEvalCondition( el, args );
91
- });
82
+
83
+ // Set the value of an element
84
+ function dfSetValue(el, val) {
85
+ if (el.attr('type') == 'checkbox') el.prop('checked', val == '1')
86
+ else el.val(val)
87
+ el.trigger('change')
92
88
  }
93
- }
94
-
95
- // Set the value of an element
96
- function dfSetValue( el, val ) {
97
- if( el.attr('type') != 'checkbox' ) el.val( val );
98
- else el.prop('checked', val == '1');
99
- el.trigger( 'change' );
100
- }
101
-
102
- // Inline update - must be called binded on the editing element
103
- function dfUpdateField() {
104
- if( $(this).data( 'loading' ) != '1' ) {
105
- $(this).data( 'loading', '1' );
106
- var _this = $(this);
107
- var type = $(this).data( 'field-type' );
108
- var new_value;
109
- if( type == 'boolean' ) new_value = !$(this).data( 'field-value' );
110
- else if( type == 'select' ) new_value = $(this).val();
111
- else new_value = $(this).text();
112
- var data = {};
113
- data[$(this).data('field')] = new_value;
114
- $.ajax({
115
- context: _this,
116
- data: { data: data },
117
- method: 'POST',
118
- url: $(this).data( 'save-url' ),
119
- complete: function( req, status ) {
120
- $(this).data( 'loading', '0' );
121
- },
122
- success: function( data, status, req ) {
123
- if( data.status == 'error' ) {
124
- if( $(this).data( 'show-errors' ) ) {
125
- var result = '';
126
- var message = data.message;
127
- for( var key in message ) {
128
- if( typeof( message[key] ) === 'object' ) {
129
- if( result ) result += ' - ';
130
- result += key + ': ' + message[key].join( '; ' );
89
+
90
+ // Inline update - must be called binded on the editing element
91
+ function dfUpdateField() {
92
+ if ($(this).data('loading') != '1') {
93
+ $(this).data('loading', '1');
94
+ let _this = $(this);
95
+ let type = $(this).data('field-type');
96
+ let new_value;
97
+ if (type == 'boolean') new_value = !$(this).data('field-value');
98
+ else if (type == 'select') new_value = $(this).val();
99
+ else new_value = $(this).text();
100
+ let data = {};
101
+ data[$(this).data('field')] = new_value;
102
+ $.ajax({
103
+ context: _this,
104
+ data: { data: data },
105
+ method: 'POST',
106
+ url: $(this).data('save-url'),
107
+ complete: function (req, status) {
108
+ $(this).data('loading', '0');
109
+ },
110
+ success: function (data, status, req) {
111
+ if (data.status == 'error') {
112
+ if ($(this).data('show-errors')) {
113
+ let result = '';
114
+ let message = data.message;
115
+ for (let key in message) {
116
+ if (typeof (message[key]) === 'object') {
117
+ if (result) result += ' - ';
118
+ result += key + ': ' + message[key].join('; ');
119
+ }
131
120
  }
121
+ if (result) alert(result);
132
122
  }
133
- if( result ) alert( result );
134
123
  }
135
- }
136
- else {
137
- $(this).data( 'field-value', new_value );
138
- if( $(this).data('content') ) {
139
- var old_text = $(this).text();
140
- var old_class = $(this).attr( 'class' );
141
- var content = $($(this).data('content'));
142
- $(this).text( content.text() );
143
- $(this).attr( 'class', content.attr( 'class' ) );
144
- content.text( old_text );
145
- content.attr( 'class', old_class );
146
- $(this).data( 'content', content );
124
+ else {
125
+ $(this).data('field-value', new_value);
126
+ if ($(this).data('content')) {
127
+ let old_text = $(this).text();
128
+ let old_class = $(this).attr('class');
129
+ let content = $($(this).data('content'));
130
+ $(this).text(content.text());
131
+ $(this).attr('class', content.attr('class'));
132
+ content.text(old_text);
133
+ content.attr('class', old_class);
134
+ $(this).data('content', content);
135
+ }
147
136
  }
148
137
  }
149
- },
150
- // error: function( req, status, error ) {
151
- // // if( $(this).data( 'show-errors' ) && req.responseJSON.message ) { }
152
- // },
153
- });
154
- }
155
- }
156
-
157
- // Init
158
- $(document).ready( function() {
159
- // Setup dynamic fields
160
- $('.active_admin .input [data-if], .active_admin .input [data-function], .active_admin .input [data-eq], .active_admin .input [data-not]').each( function() {
161
- dfSetupField( $(this) );
162
- });
163
- // Setup dynamic fields for has many associations
164
- $('.active_admin .has_many_container').on( 'has_many_add:after', function( e, fieldset, container ) {
165
- $('.active_admin .input [data-if], .active_admin .input [data-function], .active_admin .input [data-eq], .active_admin .input [data-not]').each( function() {
166
- dfSetupField( $(this) );
167
- });
168
- });
169
- // Set dialog icon link
170
- $('.active_admin [data-df-icon]').each( function() {
171
- $(this).append( ' &raquo;' ); // ' &bullet;'
172
- });
173
- // Open content in dialog
174
- $('.active_admin [data-df-dialog]').on( 'click', function( event ) {
175
- event.preventDefault();
176
- $(this).blur();
177
- if( $('#df-dialog').data( 'loading' ) != '1' ) {
178
- $('#df-dialog').data( 'loading', '1' );
179
- if( $('#df-dialog').length == 0 ) $('body').append( '<div id="df-dialog"></div>' );
180
- var title = $(this).attr( 'title' );
181
- $.ajax({
182
- url: $(this).attr( 'href' ),
183
- complete: function( req, status ) {
184
- $('#df-dialog').data( 'loading', '0' );
185
- },
186
- success: function( data, status, req ) {
187
- if( title ) $('#df-dialog').attr( 'title', title );
188
- $('#df-dialog').html( data );
189
- $('#df-dialog').dialog({ modal: true });
190
- },
191
138
  });
192
139
  }
193
- });
194
- // Inline editing
195
- $('[data-field][data-field-type="boolean"][data-save-url]').each( function() {
196
- $(this).on( 'click', $.proxy( dfUpdateField, $(this) ) );
197
- });
198
- $('[data-field][data-field-type="string"][data-save-url]' ).each( function() {
199
- $(this).data( 'field-value', $(this).text() );
200
- var fnUpdate = $.proxy( dfUpdateField, $(this) );
201
- $(this).on( 'blur', function() {
202
- if( $(this).data( 'field-value' ) != $(this).text() ) fnUpdate();
203
- });
204
- });
205
- $('[data-field][data-field-type="select"][data-save-url]').each( function() {
206
- $(this).on( 'change', $.proxy( dfUpdateField, $(this) ) );
207
- });
208
- });
140
+ }
141
+
142
+ // Init
143
+ $(document).ready(function () {
144
+ // Setup dynamic fields
145
+ const selectors = '.active_admin .input [data-if], .active_admin .input [data-eq], .active_admin .input [data-not], .active_admin .input [data-function]'
146
+ $(selectors).each(function () {
147
+ dfInitField($(this))
148
+ })
149
+
150
+ // Setup dynamic fields for associations
151
+ $('.active_admin .has_many_container').on('has_many_add:after', () => {
152
+ $(selectors).each(function () {
153
+ dfInitField($(this))
154
+ })
155
+ })
156
+
157
+ // Set dialog icon link
158
+ $('.active_admin [data-df-icon]').each(function () {
159
+ $(this).append(' &raquo;')
160
+ })
161
+
162
+ // Open content in dialog
163
+ $('.active_admin [data-df-dialog]').on('click', function (event) {
164
+ event.preventDefault()
165
+ $(this).blur()
166
+ if ($('#df-dialog').data('loading') != '1') {
167
+ $('#df-dialog').data('loading', '1')
168
+ if ($('#df-dialog').length == 0) $('body').append('<div id="df-dialog"></div>')
169
+ let title = $(this).attr('title')
170
+ $.ajax({
171
+ url: $(this).attr('href'),
172
+ complete: function (req, status) {
173
+ $('#df-dialog').data('loading', '0')
174
+ },
175
+ success: function (data, status, req) {
176
+ if (title) $('#df-dialog').attr('title', title)
177
+ $('#df-dialog').html(data)
178
+ $('#df-dialog').dialog({ modal: true })
179
+ },
180
+ })
181
+ }
182
+ })
183
+
184
+ // Inline editing
185
+ $('[data-field][data-field-type="boolean"][data-save-url]').each(function () {
186
+ $(this).on('click', $.proxy(dfUpdateField, $(this)))
187
+ })
188
+ $('[data-field][data-field-type="string"][data-save-url]').each(function () {
189
+ $(this).data('field-value', $(this).text())
190
+ let fnUpdate = $.proxy(dfUpdateField, $(this))
191
+ $(this).on('blur', function () {
192
+ if ($(this).data('field-value') != $(this).text()) fnUpdate()
193
+ })
194
+ })
195
+ $('[data-field][data-field-type="select"][data-save-url]').each(function () {
196
+ $(this).on('change', $.proxy(dfUpdateField, $(this)))
197
+ })
198
+ })
199
+ })()
@@ -1 +1,3 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'activeadmin/dynamic_fields/engine'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'active_admin'
2
4
 
3
5
  module ActiveAdmin
@@ -6,24 +8,39 @@ module ActiveAdmin
6
8
  engine_name 'activeadmin_dynamic_fields'
7
9
  end
8
10
 
9
- def self.edit_boolean( field, url, value )
10
- { 'data-field': field, 'data-field-type': 'boolean', 'data-field-value': value, 'data-content': "<span class=\"status_tag changed\">#{value ? 'no' : 'yes'}</span>", 'data-save-url': url, 'data-show-errors': '1' }
11
+ def self.edit_boolean(field, url, value)
12
+ {
13
+ 'data-field': field,
14
+ 'data-field-type': 'boolean',
15
+ 'data-field-value': value,
16
+ 'data-content': "<span class=\"status_tag changed\">#{value ? 'no' : 'yes'}</span>",
17
+ 'data-save-url': url,
18
+ 'data-show-errors': '1'
19
+ }
11
20
  end
12
21
 
13
- def self.edit_select( field, url )
14
- { 'data-field': field, 'data-field-type': 'select', 'data-save-url': url, 'data-show-errors': '1' }
15
- # 'data-field': 'author_id', 'data-field-type': 'select', 'data-save-url': save_admin_article_path( row.id ), 'data-show-errors': '1' do
16
- # ( [''] + Author.pluck( :name, :id ) ).map{ |opt| option opt[0], value: opt[1], selected: row.author_id == opt[1] }.join
17
- # end
22
+ def self.edit_select(field, url)
23
+ {
24
+ 'data-field': field,
25
+ 'data-field-type': 'select',
26
+ 'data-save-url': url,
27
+ 'data-show-errors': '1'
28
+ }
18
29
  end
19
30
 
20
- def self.edit_string( field, url )
21
- { contenteditable: true, 'data-field': field, 'data-field-type': 'string', 'data-save-url': url, 'data-show-errors': '1' }
31
+ def self.edit_string(field, url)
32
+ {
33
+ contenteditable: true,
34
+ 'data-field': field,
35
+ 'data-field-type': 'string',
36
+ 'data-save-url': url,
37
+ 'data-show-errors': '1'
38
+ }
22
39
  end
23
40
 
24
- def self.update( resource, params, permit_params = nil )
41
+ def self.update(resource, params, permit_params = nil)
25
42
  if params[:data]
26
- if resource.update( permit_params ? params[:data].permit( permit_params ) : params[:data].permit! )
43
+ if resource.update(permit_params ? params[:data].permit(permit_params) : params[:data].permit!)
27
44
  { json: { status: 'ok' } }
28
45
  else
29
46
  { json: { status: 'error', message: resource.errors } }
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveAdmin
2
4
  module DynamicFields
3
- VERSION = '0.2.0'
5
+ VERSION = '0.3.0'
4
6
  end
5
7
  end
@@ -1 +1,3 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'activeadmin/dynamic_fields'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activeadmin_dynamic_fields
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mattia Roccoberton
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-09-24 00:00:00.000000000 Z
11
+ date: 2020-09-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activeadmin
@@ -16,26 +16,149 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.0'
19
+ version: '2.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.0'
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activestorage
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 6.0.3.2
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 6.0.3.2
41
+ - !ruby/object:Gem::Dependency
42
+ name: capybara
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 3.33.0
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 3.33.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.13.1
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.13.1
69
+ - !ruby/object:Gem::Dependency
70
+ name: puma
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 4.3.5
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 4.3.5
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec_junit_formatter
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 0.4.1
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 0.4.1
97
+ - !ruby/object:Gem::Dependency
98
+ name: rspec-rails
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: 4.0.1
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 4.0.1
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubocop
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: 0.90.0
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: 0.90.0
125
+ - !ruby/object:Gem::Dependency
126
+ name: selenium-webdriver
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: 3.142.7
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: 3.142.7
139
+ - !ruby/object:Gem::Dependency
140
+ name: sqlite3
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: 1.4.2
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: 1.4.2
27
153
  description: An Active Admin plugin to add dynamic behaviors to fields
28
154
  email: mat@blocknot.es
29
155
  executables: []
30
156
  extensions: []
31
157
  extra_rdoc_files: []
32
158
  files:
33
- - ".gitignore"
34
- - Gemfile
35
159
  - LICENSE.txt
36
160
  - README.md
37
161
  - Rakefile
38
- - activeadmin_dynamic_fields.gemspec
39
162
  - app/assets/javascripts/activeadmin/dynamic_fields.js
40
163
  - lib/activeadmin/dynamic_fields.rb
41
164
  - lib/activeadmin/dynamic_fields/engine.rb
@@ -45,7 +168,7 @@ homepage: https://github.com/blocknotes/activeadmin_dynamic_fields
45
168
  licenses:
46
169
  - MIT
47
170
  metadata: {}
48
- post_install_message:
171
+ post_install_message:
49
172
  rdoc_options: []
50
173
  require_paths:
51
174
  - lib
@@ -60,9 +183,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
60
183
  - !ruby/object:Gem::Version
61
184
  version: '0'
62
185
  requirements: []
63
- rubyforge_project:
64
- rubygems_version: 2.6.13
65
- signing_key:
186
+ rubygems_version: 3.0.3
187
+ signing_key:
66
188
  specification_version: 4
67
189
  summary: Dynamic fields for ActiveAdmin
68
190
  test_files: []
data/.gitignore DELETED
@@ -1,3 +0,0 @@
1
- _misc/
2
-
3
- *.orig
data/Gemfile DELETED
@@ -1,4 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- gemspec
4
-
@@ -1,19 +0,0 @@
1
- lib = File.expand_path('../lib', __FILE__)
2
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
- require 'activeadmin/dynamic_fields/version'
4
-
5
- Gem::Specification.new do |spec|
6
- spec.name = 'activeadmin_dynamic_fields'
7
- spec.version = ActiveAdmin::DynamicFields::VERSION
8
- spec.summary = 'Dynamic fields for ActiveAdmin'
9
- spec.description = 'An Active Admin plugin to add dynamic behaviors to fields'
10
- spec.license = 'MIT'
11
- spec.authors = ['Mattia Roccoberton']
12
- spec.email = 'mat@blocknot.es'
13
- spec.homepage = 'https://github.com/blocknotes/activeadmin_dynamic_fields'
14
-
15
- spec.files = `git ls-files -z`.split("\x0")
16
- spec.require_paths = ['lib']
17
-
18
- spec.add_runtime_dependency 'activeadmin', '~> 1.0'
19
- end