activeadmin_dynamic_fields 0.4.0 → 0.6.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
  SHA256:
3
- metadata.gz: bf72bdd2f498f04dd656b044b1b711cd1e4962ad98d9190807ac9b4bfa423ba0
4
- data.tar.gz: 036c3c43e6b00ed99b900f21216b824b00dccbf3a3d871cdfa331080f30eceb3
3
+ metadata.gz: 04dad08d3de4d4cfd25de86ec9a07e3010e081afc8481b513e85103026863869
4
+ data.tar.gz: 193871cc16015051ae231a3894c6dbf3fa71f043156fcfac7162bc830380e92c
5
5
  SHA512:
6
- metadata.gz: 94007fc44295a8e251f011ef78884c31a03904e53d264bc9b5aa716645c268a0c3a7343f75b0831f790a36b14f1dcdb03ea6a87fb8e819accb36b871c5617f14
7
- data.tar.gz: bc6beec26ce12eb2f40c70cc8b9fd12f3cdd416ecf735380fd77343d395e7e7b3f2665cfc2fed8a8339651dcbc12db1eaaae3ce7c6019b5cf6bdf133c4390e31
6
+ metadata.gz: ed3de892e2f3e225bfc875c37906dfca703c1769413c631f20caf8a1fcded149c9560cf523c50f3e56ff60cca02622061c5fe8185a09d8bd081963d3674ee9ed
7
+ data.tar.gz: 70e75c688f0b2c8448e23f747752202288c89abf9ab7b4c5b11a1c4de1d92c3c18ff1e029e2e7728f5333bf76c2cc4ad54c0ca5b76402b33e698a83e448b410a
data/README.md CHANGED
@@ -1,8 +1,9 @@
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)
1
+ # ActiveAdmin Dynamic Fields [![Gem Version](https://badge.fury.io/rb/activeadmin_dynamic_fields.svg)](https://badge.fury.io/rb/activeadmin_dynamic_fields) [![Gem downloads](https://badgen.net/rubygems/dt/activeadmin_dynamic_fields)](https://rubygems.org/gems/activeadmin_dynamic_fields) [![Specs](https://github.com/blocknotes/activeadmin_dynamic_fields/actions/workflows/specs.yml/badge.svg)](https://github.com/blocknotes/activeadmin_dynamic_fields/actions/workflows/specs.yml)
2
2
 
3
3
  An Active Admin plugin to add dynamic behaviors to some fields.
4
4
 
5
5
  Features:
6
+
6
7
  - set conditional checks on fields
7
8
  - trigger actions on target elements
8
9
  - inline field editing
@@ -10,41 +11,67 @@ Features:
10
11
 
11
12
  The easiest way to show how this plugin works is looking the examples [below](#examples).
12
13
 
14
+ Please :star: if you like it.
15
+
13
16
  ## Install
14
- - Add to your Gemfile: `gem 'activeadmin_dynamic_fields'`
15
- - Execute bundle
16
- - Add at the end of your ActiveAdmin javascripts (_app/assets/javascripts/active_admin.js_):
17
+
18
+ First, add the gem to your ActiveAdmin project: `gem 'activeadmin_dynamic_fields'` (and execute `bundle`)
19
+
20
+ If you installed Active Admin **without Webpacker** support:
21
+ - add at the end of your ActiveAdmin javascripts (_app/assets/javascripts/active_admin.js_):
17
22
 
18
23
  ```js
19
24
  //= require activeadmin/dynamic_fields
20
25
  ```
21
26
 
27
+ Otherwise **with Webpacker**:
28
+
29
+ - Execute in your project root:
30
+
31
+ ```sh
32
+ yarn add blocknotes/activeadmin_dynamic_fields
33
+ ```
34
+
35
+ - Add to your *app/javascript/packs/active_admin.js*:
36
+
37
+ ```js
38
+ require('activeadmin_dynamic_fields')
39
+ ```
40
+
22
41
  ## Options
42
+
23
43
  Options are passed to fields using *input_html* parameter as *data* attributes.
24
44
 
25
45
  Conditions:
46
+
26
47
  - **data-if**: check a condition, values:
27
- + **checked**: check if a checkbox is checked
48
+ + **checked**: check if a checkbox is checked (ex. `"data-if": "checked"`)
28
49
  + **not_checked**: check if a checkbox is not checked
29
50
  + **blank**: check if a field is blank
30
51
  + **not_blank**: check if a field is not blank
31
52
  + **changed**: check if the value of an input is changed (dirty)
32
- - **data-eq**: check if a field has a specific value
33
- - **data-not**: check if a field hasn't a specific value
34
- - **data-function**: check the return value of a custom function
53
+ - **data-eq**: check if a field has a specific value (ex. `"data-eq": "42"`)
54
+ - **data-not**: check if a field has not a specific value
55
+ - **data-match**: check if a field match a regexp
56
+ - **data-mismatch**: check if a field doesn't match a regexp (ex. `"data-mismatch": "^\d+$"`)
57
+ - **data-function**: check the return value of a custom function (ex. `"data-function": "my_check"`)
35
58
 
36
59
  Actions:
60
+
37
61
  - **data-then**: action to trigger (alias **data-action**), values:
38
- + **hide**: hides elements
62
+ + **hide**: hides elements (ex. `"data-then": "hide", "data-target": ".errors"`)
39
63
  + **slide**: hides elements (using sliding)
40
64
  + **fade**: hides elements (using fading)
41
- + **addClass**: adds classes
42
- + **setValue**: set a value
43
- + **callback**: call a function (with arguments: **data-args**)
65
+ + **addClass**: adds classes (ex. `"data-then": "addClass red"`)
66
+ + **addStyle**: adds some styles (ex. `"data-then": "addStyle color: #fb1; font-size: 12px"`)
67
+ + **setText**: set the text of an element (ex. `"data-then": "setText A sample text"`)
68
+ + **setValue**: set the value of an input element (ex. `"data-then": "setValue A sample value"`)
69
+ + **callback**: call a function (with arguments: **data-args**) (ex. `"data-then": "callback a_fun"`)
44
70
  - **data-else**: action to trigger when the condition check is not true
45
71
  - **data-args**: arguments passed to the callback function
46
72
 
47
73
  Targets:
74
+
48
75
  - **data-target**: target css selector (from parent fieldset, look for the closest match)
49
76
  - **data-gtarget**: target css selector globally
50
77
 
@@ -53,6 +80,7 @@ A check condition or a custom check function are required. A trigger action is r
53
80
  ## Examples
54
81
 
55
82
  ### Dynamic fields examples
83
+
56
84
  - A checkbox that hides other fields if is checked (ex. model *Article*):
57
85
 
58
86
  ```rb
@@ -124,6 +152,7 @@ function on_change_category(el) {
124
152
  ```
125
153
 
126
154
  ### Inline editing examples
155
+
127
156
  - Prepare a custom member action to save data, an *update* helper function is available (third parameter is optional, allow to filter using strong parameters):
128
157
 
129
158
  ```rb
@@ -161,6 +190,7 @@ end
161
190
  ```
162
191
 
163
192
  ### Dialog example
193
+
164
194
  Example with 2 models: *Author* and *Article*
165
195
 
166
196
  Prepare the content dialog - in Active Admin Author config:
@@ -204,13 +234,16 @@ end
204
234
  The link url is loaded via AJAX before opening the dialog.
205
235
 
206
236
  ## Do you like it? Star it!
207
- If you use this component just star it. A developer is more motivated to improve a project when there is some interest.
208
237
 
209
- 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.
238
+ If you use this component just star it. A developer is more motivated to improve a project when there is some interest. My other [Active Admin components](https://github.com/blocknotes?utf8=✓&tab=repositories&q=activeadmin&type=source).
239
+
240
+ Or consider offering me a coffee, it's a small thing but it is greatly appreciated: [about me](https://www.blocknot.es/about-me).
210
241
 
211
242
  ## Contributors
243
+
212
244
  - [Mattia Roccoberton](http://blocknot.es): author
213
245
  - The good guys that opened issues and pull requests from time to time
214
246
 
215
247
  ## License
248
+
216
249
  The gem is available as open-source under the terms of the [MIT](LICENSE.txt).
data/Rakefile CHANGED
@@ -1,3 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "bundler/gem_tasks"
3
+ require 'bundler/gem_tasks'
4
+
5
+ begin
6
+ require 'rspec/core/rake_task'
7
+
8
+ RSpec::Core::RakeTask.new(:spec) do |t|
9
+ # t.ruby_opts = %w[-w]
10
+ t.rspec_opts = ['--color', '--format documentation']
11
+ end
12
+
13
+ task default: :spec
14
+ rescue LoadError
15
+ puts '! LoadError: no RSpec available'
16
+ end
@@ -1,10 +1,19 @@
1
1
  (function () {
2
2
  'use strict'
3
3
 
4
+ // noinspection JSUnusedGlobalSymbols
4
5
  const ACTIONS = {
5
6
  addClass: (el, name) => el.addClass(name),
7
+ addStyle: (el, extra_style) => {
8
+ let style = (el.attr('style') || '').trim()
9
+ if (!style.includes(extra_style)) {
10
+ if (style) style = style.replace(/;$/, '') + '; ' // ensure style ends with ;
11
+ el.attr('style', `${style}${extra_style}`)
12
+ }
13
+ },
6
14
  callback: (el, name) => {
7
- if (window[name]) window[name](el.data('args'))
15
+ const cb_function = window.hasOwnProperty(name) ? window[name] : null
16
+ if (typeof cb_function === 'function') cb_function(el.data('args'))
8
17
  else {
9
18
  el.attr('data-df-errors', 'callback function not found')
10
19
  console.warn(`activeadmin_dynamic_fields callback function not found: ${name}`)
@@ -12,19 +21,23 @@
12
21
  },
13
22
  fade: el => el.fadeOut(),
14
23
  hide: el => el.hide(),
24
+ setText: (el, text) => el.text(text),
15
25
  setValue: (el, value) => {
16
- if (el.attr('type') == 'checkbox') el.prop('checked', value == '1')
26
+ if (el.attr('type') === 'checkbox') el.prop('checked', value === '1')
17
27
  else el.val(value)
18
28
  el.trigger('change')
19
29
  },
20
30
  slide: el => el.slideUp()
21
31
  }
22
32
 
33
+ // noinspection EqualityComparisonWithCoercionJS, JSUnusedGlobalSymbols
23
34
  const CONDITIONS = {
24
35
  blank: el => el.val().length === 0 || !el.val().trim(),
25
36
  changed: _el => true,
26
37
  checked: el => el.is(':checked'),
27
38
  eq: (el, value) => el.val() == value,
39
+ match: (el, regexp) => regexp.test(el.val()),
40
+ mismatch: (el, regexp) => !regexp.test(el.val()),
28
41
  not: (el, value) => el.val() != value,
29
42
  not_blank: el => el.val().trim(),
30
43
  not_checked: el => !el.is(':checked')
@@ -32,6 +45,9 @@
32
45
 
33
46
  const REVERSE_ACTIONS = {
34
47
  addClass: (el, name) => el.removeClass(name),
48
+ addStyle: (el, extra_style) => {
49
+ if(el.attr('style')) el.attr('style', el.attr('style').replace(extra_style, ''))
50
+ },
35
51
  fade: el => el.fadeIn(),
36
52
  hide: el => el.show(),
37
53
  slide: el => el.slideDown()
@@ -39,74 +55,98 @@
39
55
 
40
56
  class Field {
41
57
  constructor(el) {
42
- const action = el.data('then') || el.data('action') || ''
58
+ this.el = el
59
+ const action_name = this.evaluateAction()
60
+ const result = this.evaluateCondition()
61
+ this.condition = result.condition
62
+ this.condition_arg = result.condition_arg
63
+ this.evaluateTarget(action_name)
64
+ }
65
+
66
+ apply() {
67
+ if (this.condition(this.el, this.condition_arg)) {
68
+ if (this.else_reverse_action) this.else_reverse_action(this.target, this.else_action_arg)
69
+ this.action(this.target, this.action_arg)
70
+ }
71
+ else {
72
+ if (this.reverse_action) this.reverse_action(this.target, this.action_arg)
73
+ if (this.else_action) this.else_action(this.target, this.else_action_arg)
74
+ }
75
+ }
76
+
77
+ evaluateAction() {
78
+ const action = this.el.data('then') || this.el.data('action') || ''
43
79
  const action_name = action.split(' ', 1)[0]
44
- const else_action = el.data('else') || ''
80
+ const else_action = this.el.data('else') || ''
45
81
  const else_action_name = else_action.split(' ', 1)[0]
46
82
 
47
- this.el = el
48
83
  this.action = ACTIONS[action_name]
49
84
  this.action_arg = action.substring(action.indexOf(' ') + 1)
50
85
  this.reverse_action = REVERSE_ACTIONS[action_name]
51
86
  this.else_action = ACTIONS[else_action_name]
52
87
  this.else_action_arg = else_action.substring(else_action.indexOf(' ') + 1)
53
88
  this.else_reverse_action = REVERSE_ACTIONS[else_action_name]
54
- this.condition = CONDITIONS[el.data('if')]
55
- if (!this.condition && el.data('eq')) {
56
- [this.condition, this.condition_arg] = [CONDITIONS['eq'], el.data('eq')]
57
- }
58
- if (!this.condition && el.data('not')) {
59
- [this.condition, this.condition_arg] = [CONDITIONS['not'], el.data('not')]
60
- }
61
- this.custom_function = el.data('function')
62
- if (!this.condition && this.custom_function) {
63
- this.condition = window[this.custom_function]
64
- if (!this.condition) {
65
- el.attr('data-df-errors', 'custom function not found')
89
+
90
+ return action_name
91
+ }
92
+
93
+ evaluateCondition() {
94
+ let value = CONDITIONS[this.el.data('if')?.trim()]
95
+ if (value) return { condition: value }
96
+
97
+ value = this.el.data('eq')
98
+ if (value) return { condition: CONDITIONS['eq'], condition_arg: value }
99
+
100
+ value = this.el.data('not')
101
+ if (value) return { condition: CONDITIONS['not'], condition_arg: value }
102
+
103
+ value = this.el.data('match')
104
+ if (value) return { condition: CONDITIONS['match'], condition_arg: new RegExp(value) }
105
+
106
+ value = this.el.data('mismatch')
107
+ if (value) return { condition: CONDITIONS['mismatch'], condition_arg: new RegExp(value) }
108
+
109
+ this.custom_function = this.el.data('function')
110
+ if (this.custom_function) {
111
+ value = window[this.custom_function]
112
+ if (value) return { condition: value }
113
+ else {
114
+ this.el.attr('data-df-errors', 'custom function not found')
66
115
  console.warn(`activeadmin_dynamic_fields custom function not found: ${this.custom_function}`)
67
116
  }
68
117
  }
69
118
 
70
- // closest find for has many associations
71
- if (el.data('target')) this.target = el.closest('fieldset').find(el.data('target'))
72
- else if (el.data('gtarget')) this.target = $(el.data('gtarget'))
73
- if (action_name == 'callback') this.target = el
119
+ return {}
74
120
  }
75
121
 
76
- apply(el) {
77
- if (this.condition(el, this.condition_arg)) {
78
- if (this.else_reverse_action) this.else_reverse_action(this.target, this.else_action_arg)
79
- this.action(this.target, this.action_arg)
80
- }
81
- else {
82
- if (this.reverse_action) this.reverse_action(this.target, this.action_arg)
83
- if (this.else_action) this.else_action(this.target, this.else_action_arg)
84
- }
122
+ evaluateTarget(action_name) {
123
+ // closest find for has many associations
124
+ if (this.el.data('target')) this.target = this.el.closest('fieldset').find(this.el.data('target'))
125
+ else if (this.el.data('gtarget')) this.target = $(this.el.data('gtarget'))
126
+ if (action_name === 'callback') this.target = this.el
85
127
  }
86
128
 
87
- is_valid() {
129
+ isValid() {
88
130
  if (!this.condition) return false
89
- if (!this.action && !this.custom_function) return false
90
-
91
- return true
131
+ return (this.action || this.custom_function)
92
132
  }
93
133
 
94
134
  setup() {
95
- if (!this.is_valid()) return
96
- if (this.el.data('if') != 'changed') this.apply(this.el)
97
- this.el.on('change', () => this.apply(this.el))
135
+ if (!this.isValid()) return
136
+ if (this.el.data('if') !== 'changed') this.apply()
137
+ this.el.on('change', () => this.apply())
98
138
  }
99
139
  }
100
140
 
101
- // Inline update - must be called binded on the editing element
141
+ // Inline update - must be called bound on the editing element
102
142
  function dfUpdateField() {
103
- if ($(this).data('loading') != '1') {
143
+ if ($(this).data('loading') !== '1') {
104
144
  $(this).data('loading', '1');
105
145
  let _this = $(this);
106
146
  let type = $(this).data('field-type');
107
147
  let new_value;
108
- if (type == 'boolean') new_value = !$(this).data('field-value');
109
- else if (type == 'select') new_value = $(this).val();
148
+ if (type === 'boolean') new_value = !$(this).data('field-value');
149
+ else if (type === 'select') new_value = $(this).val();
110
150
  else new_value = $(this).text();
111
151
  let data = {};
112
152
  data[$(this).data('field')] = new_value;
@@ -115,16 +155,16 @@
115
155
  data: { data: data },
116
156
  method: 'POST',
117
157
  url: $(this).data('save-url'),
118
- complete: function (req, status) {
158
+ complete: function (_req, _status) {
119
159
  $(this).data('loading', '0');
120
160
  },
121
- success: function (data, status, req) {
122
- if (data.status == 'error') {
161
+ success: function (data, _status, _req) {
162
+ if (data.status === 'error') {
123
163
  if ($(this).data('show-errors')) {
124
164
  let result = '';
125
165
  let message = data.message;
126
166
  for (let key in message) {
127
- if (typeof (message[key]) === 'object') {
167
+ if (message.hasOwnProperty(key) && typeof (message[key]) === 'object') {
128
168
  if (result) result += ' - ';
129
169
  result += key + ': ' + message[key].join('; ');
130
170
  }
@@ -150,10 +190,9 @@
150
190
  }
151
191
  }
152
192
 
153
- // Init
154
- $(document).ready(function () {
193
+ function dfInit() {
155
194
  // Setup dynamic fields
156
- const selectors = '.active_admin .input [data-if], .active_admin .input [data-eq], .active_admin .input [data-not], .active_admin .input [data-function]'
195
+ const selectors = '.active_admin .input [data-if], .active_admin .input [data-eq], .active_admin .input [data-not], .active_admin .input [data-match], .active_admin .input [data-mismatch], .active_admin .input [data-function]'
157
196
  $(selectors).each(function () {
158
197
  new Field($(this)).setup()
159
198
  })
@@ -174,20 +213,23 @@
174
213
  $('.active_admin [data-df-dialog]').on('click', function (event) {
175
214
  event.preventDefault()
176
215
  $(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>')
216
+ const df_dialog = $('#df-dialog')
217
+
218
+ if (df_dialog.data('loading') !== '1') {
219
+ df_dialog.data('loading', '1')
220
+ if (df_dialog.length === 0) $('body').append('<div id="df-dialog"></div>')
180
221
  let title = $(this).attr('title')
181
222
  $.ajax({
182
223
  url: $(this).attr('href'),
183
- complete: function (req, status) {
224
+ complete: function (_req, _status) {
184
225
  $('#df-dialog').data('loading', '0')
185
226
  },
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
- },
227
+ success: function (data, _status, _req) {
228
+ const dialog = $('#df-dialog')
229
+ if (title) dialog.attr('title', title)
230
+ dialog.html(data)
231
+ dialog.dialog({ modal: true })
232
+ }
191
233
  })
192
234
  }
193
235
  })
@@ -200,11 +242,14 @@
200
242
  $(this).data('field-value', $(this).text())
201
243
  let fnUpdate = $.proxy(dfUpdateField, $(this))
202
244
  $(this).on('blur', function () {
203
- if ($(this).data('field-value') != $(this).text()) fnUpdate()
245
+ if ($(this).data('field-value') !== $(this).text()) fnUpdate()
204
246
  })
205
247
  })
206
248
  $('[data-field][data-field-type="select"][data-save-url]').each(function () {
207
249
  $(this).on('change', $.proxy(dfUpdateField, $(this)))
208
250
  })
209
- })
251
+ }
252
+
253
+ $(document).ready(dfInit)
254
+ $(document).on('turbolinks:load', dfInit)
210
255
  })()
@@ -2,6 +2,6 @@
2
2
 
3
3
  module ActiveAdmin
4
4
  module DynamicFields
5
- VERSION = '0.4.0'
5
+ VERSION = '0.6.0'
6
6
  end
7
7
  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.4.0
4
+ version: 0.6.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: 2020-09-22 00:00:00.000000000 Z
11
+ date: 2021-05-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activeadmin
@@ -24,132 +24,6 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
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
153
27
  description: An Active Admin plugin to add dynamic behaviors to fields
154
28
  email: mat@blocknot.es
155
29
  executables: []
@@ -183,7 +57,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
183
57
  - !ruby/object:Gem::Version
184
58
  version: '0'
185
59
  requirements: []
186
- rubygems_version: 3.0.3
60
+ rubygems_version: 3.1.4
187
61
  signing_key:
188
62
  specification_version: 4
189
63
  summary: Dynamic fields for ActiveAdmin