activeadmin_dynamic_fields 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml 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