activeadmin_dynamic_fields 0.8.0 → 0.9.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 +4 -4
- data/README.md +58 -13
- data/app/assets/javascripts/activeadmin/dynamic_fields.js +50 -26
- data/lib/activeadmin/dynamic_fields/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 97b522ebfcb88c5347507a8db90342028627a4fbadce5878e5c69cc24ca12653
|
4
|
+
data.tar.gz: 5b0e53d191c5a020c4750593a2659d123f7b9a1ecf8ab2393e52086f02e5b0f0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 36529da7a2362d72decbb4aae98fae8b19b3a97ef68336a73dc3443eb68c46b7f2176c6573b8b775d464a7c9f7152ce1755ef40d95492b8d4300c1ae15aeb7fa
|
7
|
+
data.tar.gz: 80f0bcd3f053a4701bb04b7d9353e68179caa27285ba9e8b1b606027adea8ca5bf9b10d8c74580c405c9fbee4d056f72be58f6288ea92daf24d787f488725aa0
|
data/README.md
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# ActiveAdmin Dynamic Fields
|
2
|
-
[](https://badge.fury.io/rb/activeadmin_dynamic_fields) [](https://rubygems.org/gems/activeadmin_dynamic_fields) [](https://github.com/blocknotes/activeadmin_dynamic_fields/actions/workflows/linters.yml) [](https://badge.fury.io/rb/activeadmin_dynamic_fields) [](https://rubygems.org/gems/activeadmin_dynamic_fields) [](https://github.com/blocknotes/activeadmin_dynamic_fields/actions/workflows/linters.yml) [](https://github.com/blocknotes/activeadmin_dynamic_fields/actions/workflows/specs_rails70.yml)
|
3
3
|
|
4
4
|
An Active Admin plugin to add dynamic behaviors to some fields.
|
5
5
|
|
@@ -63,13 +63,14 @@ Actions:
|
|
63
63
|
+ **hide**: hides elements (ex. `"data-then": "hide", "data-target": ".errors"`)
|
64
64
|
+ **slide**: hides elements (using sliding)
|
65
65
|
+ **fade**: hides elements (using fading)
|
66
|
-
+ **addClass**: adds classes (ex. `"data-then": "addClass red"`)
|
67
|
-
+ **addStyle**: adds some styles (ex. `"data-then": "addStyle color: #fb1; font-size: 12px"`)
|
68
|
-
+ **setText**: set the text of an element (ex. `"data-then": "setText A sample text"`)
|
69
|
-
+ **setValue**: set the value of an input element (ex. `"data-then": "setValue A sample value"`)
|
66
|
+
+ **addClass**: adds classes (ex. `"data-then": "addClass", "data-args": "red"`)
|
67
|
+
+ **addStyle**: adds some styles (ex. `"data-then": "addStyle", "data-args": "color: #fb1; font-size: 12px"`)
|
68
|
+
+ **setText**: set the text of an element (ex. `"data-then": "setText", "data-args": "A sample text"`)
|
69
|
+
+ **setValue**: set the value of an input element (ex. `"data-then": "setValue", "data-args": "A sample value"`)
|
70
70
|
+ **callback**: call a function (with arguments: **data-args**) (ex. `"data-then": "callback a_fun"`)
|
71
|
+
- **data-args**: arguments passed to the triggered action (or to the callback function)
|
71
72
|
- **data-else**: action to trigger when the condition check is not true
|
72
|
-
- **data-args**: arguments passed to the
|
73
|
+
- **data-else-args**: arguments passed to the triggered else action
|
73
74
|
|
74
75
|
Targets:
|
75
76
|
|
@@ -98,14 +99,14 @@ end
|
|
98
99
|
- Add 3 classes (*first*, *second*, *third*) if a checkbox is not checked, else add "forth" class:
|
99
100
|
|
100
101
|
```rb
|
101
|
-
data = { if: 'not_checked', then: 'addClass first second third', target: '.grp1', else: 'addClass forth' }
|
102
|
+
data = { if: 'not_checked', then: 'addClass', args: 'first second third', target: '.grp1', else: 'addClass', 'else-args': 'forth' }
|
102
103
|
f.input :published, input_html: { data: data }
|
103
104
|
```
|
104
105
|
|
105
106
|
- Set another field value if a string field is blank:
|
106
107
|
|
107
108
|
```rb
|
108
|
-
f.input :title, input_html: { data: { if: 'blank', then: 'setValue 10', target: '#article_position' } }
|
109
|
+
f.input :title, input_html: { data: { if: 'blank', then: 'setValue', args: '10', target: '#article_position' } }
|
109
110
|
```
|
110
111
|
|
111
112
|
- Use a custom function for conditional check (*title_not_empty()* must be available on global scope) (with alternative syntax for data attributes):
|
@@ -234,17 +235,61 @@ end
|
|
234
235
|
|
235
236
|
The link url is loaded via AJAX before opening the dialog.
|
236
237
|
|
238
|
+
## Development
|
239
|
+
|
240
|
+
Project created by [Mattia Roccoberton](http://blocknot.es), thanks also to the good guys that opened issues and pull requests from time to time.
|
241
|
+
|
242
|
+
There 3 ways to interact with this project:
|
243
|
+
|
244
|
+
1) Using Docker:
|
245
|
+
|
246
|
+
```sh
|
247
|
+
# Run rails server on the dummy app (=> http://localhost:3000 to access to ActiveAdmin):
|
248
|
+
make up
|
249
|
+
# Enter in a Rails console (with the dummy app started):
|
250
|
+
make console
|
251
|
+
# Enter in a shell (with the dummy app started):
|
252
|
+
make shell
|
253
|
+
# Run the linter on the project (with the dummy app started):
|
254
|
+
make lint
|
255
|
+
# Run the test suite (with the dummy app started):
|
256
|
+
make specs
|
257
|
+
# Remove container and image:
|
258
|
+
make cleanup
|
259
|
+
# To try different versions of Ruby/Rails/ActiveAdmin edit docker-compose.yml
|
260
|
+
# For more commands please check the Makefile
|
261
|
+
```
|
262
|
+
|
263
|
+
2) Using Appraisal:
|
264
|
+
|
265
|
+
```sh
|
266
|
+
export RAILS_ENV=development
|
267
|
+
# Install dependencies:
|
268
|
+
bin/appraisal
|
269
|
+
# Run server (or any command):
|
270
|
+
bin/appraisal rails s
|
271
|
+
# Or with a specific configuration:
|
272
|
+
bin/appraisal rails80-activeadmin rails s
|
273
|
+
```
|
274
|
+
|
275
|
+
3) With a local setup:
|
276
|
+
|
277
|
+
```sh
|
278
|
+
# Dev setup (set the required envs):
|
279
|
+
source extra/dev_setup.sh
|
280
|
+
# Install dependencies:
|
281
|
+
bundle update
|
282
|
+
# Run server (or any command):
|
283
|
+
bin/rails s
|
284
|
+
# To try different versions of Rails/ActiveAdmin edit extra/dev_setup.sh
|
285
|
+
```
|
286
|
+
|
237
287
|
## Do you like it? Star it!
|
238
288
|
|
239
289
|
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).
|
240
290
|
|
241
291
|
Or consider offering me a coffee, it's a small thing but it is greatly appreciated: [about me](https://www.blocknot.es/about-me).
|
242
292
|
|
243
|
-
## Contributors
|
244
|
-
|
245
|
-
- [Mattia Roccoberton](http://blocknot.es): author
|
246
|
-
- The good guys that opened issues and pull requests from time to time
|
247
|
-
|
248
293
|
## License
|
249
294
|
|
250
295
|
The gem is available as open-source under the terms of the [MIT](LICENSE.txt).
|
@@ -1,3 +1,4 @@
|
|
1
|
+
/* global $ */
|
1
2
|
(function () {
|
2
3
|
'use strict'
|
3
4
|
|
@@ -12,8 +13,9 @@
|
|
12
13
|
}
|
13
14
|
},
|
14
15
|
callback: (el, name) => {
|
15
|
-
const
|
16
|
-
|
16
|
+
const callbackDefined = Object.prototype.hasOwnProperty.call(window, name)
|
17
|
+
const callbackFunction = callbackDefined ? window[name] : null
|
18
|
+
if (typeof callbackFunction === 'function') callbackFunction(el.data('args'))
|
17
19
|
else {
|
18
20
|
el.attr('data-df-errors', 'callback function not found')
|
19
21
|
console.warn(`activeadmin_dynamic_fields callback function not found: ${name}`)
|
@@ -33,7 +35,7 @@
|
|
33
35
|
// noinspection EqualityComparisonWithCoercionJS, JSUnusedGlobalSymbols
|
34
36
|
const CONDITIONS = {
|
35
37
|
blank: el => el.val().length === 0 || !el.val().trim(),
|
36
|
-
changed:
|
38
|
+
changed: () => true,
|
37
39
|
checked: el => el.is(':checked'),
|
38
40
|
eq: (el, value) => el.val() == value,
|
39
41
|
match: (el, regexp) => regexp.test(el.val()),
|
@@ -77,50 +79,71 @@
|
|
77
79
|
}
|
78
80
|
|
79
81
|
evaluateAction() {
|
80
|
-
const
|
81
|
-
const
|
82
|
-
const
|
83
|
-
const
|
82
|
+
const dataAction = this.el.data('then') || this.el.data('action') || ''
|
83
|
+
const actionName = dataAction.split(' ', 1)[0]
|
84
|
+
const dataElse = this.el.data('else') || ''
|
85
|
+
const elseActionName = dataElse.split(' ', 1)[0]
|
84
86
|
|
85
|
-
this.action = ACTIONS[
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
87
|
+
this.action = ACTIONS[actionName]
|
88
|
+
if (actionName == 'callback') {
|
89
|
+
this.action_arg = dataAction.substring(dataAction.indexOf(' ') + 1)
|
90
|
+
} else {
|
91
|
+
this.action_arg = this.el.data('args') || dataAction.substring(dataAction.indexOf(' ') + 1)
|
92
|
+
}
|
93
|
+
this.reverse_action = REVERSE_ACTIONS[actionName]
|
94
|
+
this.else_action = ACTIONS[elseActionName]
|
95
|
+
if (elseActionName == 'callback') {
|
96
|
+
this.else_action_arg = dataElse.substring(dataElse.indexOf(' ') + 1)
|
97
|
+
} else {
|
98
|
+
this.else_action_arg = this.el.data('else-args') || dataElse.substring(dataElse.indexOf(' ') + 1)
|
99
|
+
}
|
100
|
+
this.else_reverse_action = REVERSE_ACTIONS[elseActionName]
|
91
101
|
|
92
|
-
return
|
102
|
+
return actionName
|
93
103
|
}
|
94
104
|
|
95
105
|
evaluateCondition() {
|
96
|
-
let value
|
97
|
-
if (value
|
106
|
+
let value = this.el.data('if')
|
107
|
+
if (value) {
|
98
108
|
if (REGEXP_NOT.test(value)) value = 'not_' + value.replace(REGEXP_NOT, '')
|
109
|
+
|
99
110
|
return { condition: CONDITIONS[value] }
|
100
111
|
}
|
101
|
-
|
112
|
+
|
113
|
+
value = this.el.data('eq')
|
114
|
+
if (value) {
|
102
115
|
if (REGEXP_NOT.test(value)) {
|
103
116
|
return { condition: CONDITIONS['not'], condition_arg: value.replace(REGEXP_NOT, '') }
|
104
117
|
}
|
118
|
+
|
105
119
|
return { condition: CONDITIONS['eq'], condition_arg: value }
|
106
120
|
}
|
107
|
-
|
121
|
+
|
122
|
+
value = this.el.data('not')
|
123
|
+
if (value) {
|
108
124
|
if (REGEXP_NOT.test(value)) {
|
109
125
|
return { condition: CONDITIONS['eq'], condition_arg: value.replace(REGEXP_NOT, '') }
|
110
126
|
}
|
127
|
+
|
111
128
|
return { condition: CONDITIONS['not'], condition_arg: value }
|
112
129
|
}
|
113
|
-
|
130
|
+
|
131
|
+
value = this.el.data('match')
|
132
|
+
if (value) {
|
114
133
|
return { condition: CONDITIONS['match'], condition_arg: new RegExp(value) }
|
115
134
|
}
|
116
|
-
|
135
|
+
|
136
|
+
value = this.el.data('mismatch')
|
137
|
+
if (value) {
|
117
138
|
return { condition: CONDITIONS['mismatch'], condition_arg: new RegExp(value) }
|
118
139
|
}
|
119
140
|
|
120
141
|
this.custom_function = this.el.data('function')
|
121
142
|
if (this.custom_function) {
|
122
143
|
value = window[this.custom_function]
|
123
|
-
if (value)
|
144
|
+
if (value) {
|
145
|
+
return { condition: value }
|
146
|
+
}
|
124
147
|
else {
|
125
148
|
this.el.attr('data-df-errors', 'custom function not found')
|
126
149
|
console.warn(`activeadmin_dynamic_fields custom function not found: ${this.custom_function}`)
|
@@ -166,16 +189,17 @@
|
|
166
189
|
data: { data: data },
|
167
190
|
method: 'POST',
|
168
191
|
url: $(this).data('save-url'),
|
169
|
-
complete: function (
|
192
|
+
complete: function () {
|
170
193
|
$(this).data('loading', '0');
|
171
194
|
},
|
172
|
-
success: function (data
|
195
|
+
success: function (data) {
|
173
196
|
if (data.status === 'error') {
|
174
197
|
if ($(this).data('show-errors')) {
|
175
198
|
let result = '';
|
176
199
|
let message = data.message;
|
177
200
|
for (let key in message) {
|
178
|
-
|
201
|
+
const keyAvailable = Object.prototype.hasOwnProperty.call(message, key)
|
202
|
+
if (keyAvailable && typeof (message[key]) === 'object') {
|
179
203
|
if (result) result += ' - ';
|
180
204
|
result += key + ': ' + message[key].join('; ');
|
181
205
|
}
|
@@ -232,10 +256,10 @@
|
|
232
256
|
let title = $(this).attr('title')
|
233
257
|
$.ajax({
|
234
258
|
url: $(this).attr('href'),
|
235
|
-
complete: function (
|
259
|
+
complete: function () {
|
236
260
|
$('#df-dialog').data('loading', '0')
|
237
261
|
},
|
238
|
-
success: function (data
|
262
|
+
success: function (data) {
|
239
263
|
const dialog = $('#df-dialog')
|
240
264
|
if (title) dialog.attr('title', title)
|
241
265
|
dialog.html(data)
|
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
|
+
version: 0.9.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:
|
11
|
+
date: 2025-03-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activeadmin
|
@@ -80,7 +80,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
80
80
|
- !ruby/object:Gem::Version
|
81
81
|
version: '0'
|
82
82
|
requirements: []
|
83
|
-
rubygems_version: 3.
|
83
|
+
rubygems_version: 3.5.22
|
84
84
|
signing_key:
|
85
85
|
specification_version: 4
|
86
86
|
summary: Dynamic fields for ActiveAdmin
|