activeadmin_dynamic_fields 0.1.5 → 0.2.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
2
  SHA1:
3
- metadata.gz: 42ac2b763d8f98e2e55cf81e3ec76aecf16cec7e
4
- data.tar.gz: 9a7c58695fbb59281f948ce192bfeb0aefe79e2e
3
+ metadata.gz: d599f816a20b2b7068d3b7d72e7ada1002c848bf
4
+ data.tar.gz: 296760d26145ceddb5e535296c1fa8a234e9781d
5
5
  SHA512:
6
- metadata.gz: 613eeec1ba5f472a7309a0b1463bd06ced96044def8845005f6fc3fad7c44cc40efbbece500af140251ab03ad6001b21f1d40b3205b4bb70167ca819156dfbc0
7
- data.tar.gz: f60670bc64107e1c7d57f19f9792c5dd2485d5d910f22ec970c5f572d7d2703e18c626457bbefc1ab03ff530d1c4549d42e3d2230ee89df92ef520a09c106671
6
+ metadata.gz: 28779caf4f980c64bffc0cc88e006f0d3ec9b6b1666e53f306a57e9e035c386f7c4f30d55994ee38e610bd337b6922a2470662f5c341b3ca2f77acfbf322b021
7
+ data.tar.gz: e078d3ab6b1ddc26c1af8c899c4aa2a903803b59e3f2f56a331e071437fb98265efd8386653fe16f140015e2ce8070f2a7d1b65b6313167ec855d73da3b3b722
data/README.md CHANGED
@@ -6,6 +6,7 @@ Features:
6
6
 
7
7
  - set conditional checks on fields
8
8
  - trigger some actions on other fields
9
+ - inline field editing
9
10
  - create links to load some content in a dialog
10
11
 
11
12
  The easiest way to show how this plugin works is looking the examples [below](#examples-of-dynamic-fields).
@@ -39,7 +40,9 @@ Options are passed to fields using *input_html* parameter as *data* attributes:
39
40
  - **data-function**: check the return value of a custom function
40
41
  - **data-arg**: argument passed to the custom set function (as array of strings)
41
42
 
42
- ## Examples of dynamic fields
43
+ ## Examples
44
+
45
+ ### Dynamic fields examples
43
46
 
44
47
  - A checkbox that hides other fields if false (ex. model *Article*):
45
48
 
@@ -97,7 +100,45 @@ function on_change_category( el ) {
97
100
  }
98
101
  ```
99
102
 
100
- ## Example to open a dialog
103
+ ### Inline editing example
104
+
105
+ - 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
+ ```rb
108
+ 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 )
112
+ end
113
+ ```
114
+
115
+ - In *index* config:
116
+
117
+ ```rb
118
+ # Edit a string:
119
+ column :title do |row|
120
+ div row.title, ActiveAdmin::DynamicFields::edit_string( :title, save_admin_article_path( row.id ) )
121
+ end
122
+ # Edit a boolean:
123
+ column :published do |row|
124
+ status_tag row.published, ActiveAdmin::DynamicFields::edit_boolean( :published, save_admin_article_path( row.id ), row.published )
125
+ end
126
+ # Edit a select ([''] allow to have a blank value):
127
+ 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 )
130
+ end
131
+ end
132
+ ```
133
+
134
+ - In *show* config (less useful):
135
+ ```rb
136
+ row :title do |row|
137
+ div row.title, ActiveAdmin::DynamicFields::edit_string( :title, save_admin_article_path( row.id ) )
138
+ end
139
+ ```
140
+
141
+ ### Dialog example
101
142
 
102
143
  Example with 2 models: *Author* and *Article*
103
144
 
@@ -99,6 +99,61 @@ function dfSetValue( el, val ) {
99
99
  el.trigger( 'change' );
100
100
  }
101
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( '; ' );
131
+ }
132
+ }
133
+ if( result ) alert( result );
134
+ }
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 );
147
+ }
148
+ }
149
+ },
150
+ // error: function( req, status, error ) {
151
+ // // if( $(this).data( 'show-errors' ) && req.responseJSON.message ) { }
152
+ // },
153
+ });
154
+ }
155
+ }
156
+
102
157
  // Init
103
158
  $(document).ready( function() {
104
159
  // Setup dynamic fields
@@ -111,20 +166,43 @@ $(document).ready( function() {
111
166
  dfSetupField( $(this) );
112
167
  });
113
168
  });
169
+ // Set dialog icon link
170
+ $('.active_admin [data-df-icon]').each( function() {
171
+ $(this).append( ' »' ); // ' •'
172
+ });
114
173
  // Open content in dialog
115
174
  $('.active_admin [data-df-dialog]').on( 'click', function( event ) {
116
175
  event.preventDefault();
117
- if( $('#df-dialog').length == 0 ) $('body').append( '<div id="df-dialog"></div>' );
118
- var title = $(this).attr( 'title' );
119
- $.ajax({
120
- url: $(this).attr( 'href' )
121
- }).done( function( result ) {
122
- if( title ) $('#df-dialog').attr( 'title', title );
123
- $('#df-dialog').html( result );
124
- $('#df-dialog').dialog({ modal: true });
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
+ });
192
+ }
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();
125
203
  });
126
204
  });
127
- $('.active_admin [data-df-icon]').each( function() {
128
- $(this).append( ' &raquo;' ); // ' &bullet;'
205
+ $('[data-field][data-field-type="select"][data-save-url]').each( function() {
206
+ $(this).on( 'change', $.proxy( dfUpdateField, $(this) ) );
129
207
  });
130
208
  });
@@ -5,5 +5,32 @@ module ActiveAdmin
5
5
  class Engine < ::Rails::Engine
6
6
  engine_name 'activeadmin_dynamic_fields'
7
7
  end
8
+
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
+ end
12
+
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
18
+ end
19
+
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' }
22
+ end
23
+
24
+ def self.update( resource, params, permit_params = nil )
25
+ if params[:data]
26
+ if resource.update( permit_params ? params[:data].permit( permit_params ) : params[:data].permit! )
27
+ { json: { status: 'ok' } }
28
+ else
29
+ { json: { status: 'error', message: resource.errors } }
30
+ end
31
+ else
32
+ { json: { status: 'error', message: 'No data' }, status: 400 }
33
+ end
34
+ end
8
35
  end
9
36
  end
@@ -1,5 +1,5 @@
1
1
  module ActiveAdmin
2
2
  module DynamicFields
3
- VERSION = '0.1.5'
3
+ VERSION = '0.2.0'
4
4
  end
5
5
  end
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.1.5
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mattia Roccoberton
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-09-23 00:00:00.000000000 Z
11
+ date: 2017-09-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activeadmin