ProMotion-XLForm 0.0.7 → 0.0.8
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 +46 -1
- data/lib/ProMotion-XLForm.rb +4 -0
- data/lib/ProMotion/XLForm/cells/xl_form_cell.rb +12 -0
- data/lib/ProMotion/XLForm/cells/xl_form_color_selector_cell.rb +17 -17
- data/lib/ProMotion/XLForm/cells/xl_form_image_selector_cell.rb +80 -78
- data/lib/ProMotion/XLForm/validators/regex_validator.rb +1 -1
- data/lib/ProMotion/XLForm/xl_form.rb +54 -311
- data/lib/ProMotion/XLForm/xl_form_cell_builder.rb +182 -0
- data/lib/ProMotion/XLForm/xl_form_helper.rb +65 -0
- data/lib/ProMotion/XLForm/xl_form_patch.rb +78 -10
- data/lib/ProMotion/XLForm/xl_form_screen.rb +88 -40
- data/lib/ProMotion/XLForm/xl_form_section_builder.rb +48 -0
- data/lib/ProMotion/XLForm/xl_form_view_controller.rb +1 -1
- data/lib/ProMotion/XLForm/xl_sub_form_screen.rb +21 -21
- metadata +20 -2
@@ -0,0 +1,65 @@
|
|
1
|
+
module ProMotion
|
2
|
+
module XLFormHelper
|
3
|
+
|
4
|
+
def configure_hidden(cell_or_section, predicate)
|
5
|
+
tag = operand = value = nil
|
6
|
+
if predicate.is_a?(Hash)
|
7
|
+
tag = predicate[:name]
|
8
|
+
operand = case predicate[:is]
|
9
|
+
when :equal
|
10
|
+
'=='
|
11
|
+
when :not_equal
|
12
|
+
'!='
|
13
|
+
when :contains
|
14
|
+
'contains'
|
15
|
+
when :not_contains
|
16
|
+
'not contains'
|
17
|
+
else
|
18
|
+
predicate[:is]
|
19
|
+
end
|
20
|
+
value = predicate[:value]
|
21
|
+
else
|
22
|
+
match = /(:?[a-zA-Z_]+)\s+(==|!=|contains|not contains)\s+(.*)/.match(predicate)
|
23
|
+
if match && match.length == 4
|
24
|
+
# todo better than ignore ?
|
25
|
+
tag = match[1]
|
26
|
+
operand = match[2]
|
27
|
+
value = match[3]
|
28
|
+
if value =~ /"(.*)"/
|
29
|
+
value = value[1, value.length - 2]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
if tag && operand
|
35
|
+
if tag.is_a?(Symbol)
|
36
|
+
tag = tag.to_s
|
37
|
+
elsif tag.start_with?(':')
|
38
|
+
tag[0] = ''
|
39
|
+
end
|
40
|
+
value = case value
|
41
|
+
when nil
|
42
|
+
'nil'
|
43
|
+
when 'true', :true, true
|
44
|
+
0
|
45
|
+
when 'false', :false, false
|
46
|
+
1
|
47
|
+
when String
|
48
|
+
"\"#{value}\""
|
49
|
+
else
|
50
|
+
value
|
51
|
+
end
|
52
|
+
|
53
|
+
if operand == 'contains'
|
54
|
+
cell_or_section.hidden = "$#{tag} contains[c] #{value}"
|
55
|
+
elsif operand == 'not contains'
|
56
|
+
cell_or_section.hidden = "not($#{tag} contains[c] #{value})"
|
57
|
+
else
|
58
|
+
cell_or_section.hidden = "$#{tag} #{operand} #{value}"
|
59
|
+
end
|
60
|
+
else
|
61
|
+
mp predicate: predicate.inspect, message: "predicate can not be parsed", force_color: :red
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -9,7 +9,7 @@ class XLFormAction
|
|
9
9
|
def copyWithZone(zone)
|
10
10
|
action_copy = old_copyWithZone(zone)
|
11
11
|
|
12
|
-
action_copy.cells
|
12
|
+
action_copy.cells = self.cells.copy
|
13
13
|
action_copy.required = self.required
|
14
14
|
action_copy
|
15
15
|
end
|
@@ -17,20 +17,88 @@ end
|
|
17
17
|
|
18
18
|
class XLFormRowDescriptor
|
19
19
|
|
20
|
+
attr_accessor :cell_data
|
21
|
+
|
22
|
+
alias :old_copyWithZone :copyWithZone
|
23
|
+
|
24
|
+
def copyWithZone(zone)
|
25
|
+
row_copy = old_copyWithZone(zone)
|
26
|
+
row_copy.cell_data = cell_data
|
27
|
+
row_copy
|
28
|
+
end
|
29
|
+
|
20
30
|
def options=(options)
|
21
31
|
self.selectorOptions = parse_options(options)
|
22
32
|
end
|
23
33
|
|
24
34
|
def parse_options(options)
|
25
|
-
|
35
|
+
return nil if options.nil? || options.empty?
|
36
|
+
|
37
|
+
options.map do |key, text|
|
38
|
+
val = key
|
39
|
+
if val.is_a? Symbol
|
40
|
+
val = val.to_s
|
41
|
+
end
|
42
|
+
XLFormOptionsObject.formOptionsObjectWithValue(val, displayText: text)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class XLFormSectionDescriptor
|
48
|
+
attr_accessor :section_data, :options
|
49
|
+
|
50
|
+
def self.section(section_data)
|
51
|
+
title = section_data[:title]
|
52
|
+
|
53
|
+
options = section_data.fetch(:options, :none)
|
54
|
+
options = parse_section_options(options)
|
55
|
+
insert_mode = section_insert_mode(section_data[:insert_mode])
|
56
|
+
|
57
|
+
section = XLFormSectionDescriptor.formSectionWithTitle(title, sectionOptions: options, sectionInsertMode: insert_mode)
|
58
|
+
section.section_data = section_data
|
59
|
+
section.options = options
|
60
|
+
section
|
61
|
+
end
|
62
|
+
|
63
|
+
def options=(value)
|
64
|
+
@options = self.class.parse_section_options(value)
|
65
|
+
end
|
66
|
+
|
67
|
+
def options
|
68
|
+
@options
|
69
|
+
end
|
70
|
+
|
71
|
+
def sectionOptions
|
72
|
+
options
|
73
|
+
end
|
26
74
|
|
27
|
-
|
28
|
-
|
29
|
-
if val.is_a? Symbol
|
30
|
-
val = val.to_s
|
31
|
-
end
|
32
|
-
XLFormOptionsObject.formOptionsObjectWithValue(val, displayText: text)
|
33
|
-
end
|
34
|
-
end
|
75
|
+
def self.parse_section_options(options)
|
76
|
+
return section_options(:none) if options.nil?
|
35
77
|
|
78
|
+
opts = section_options(:none)
|
79
|
+
unless options.is_a?(Array)
|
80
|
+
options = [options]
|
81
|
+
end
|
82
|
+
options.each do |opt|
|
83
|
+
opts |= section_options(opt)
|
84
|
+
end
|
85
|
+
|
86
|
+
opts
|
87
|
+
end
|
88
|
+
|
89
|
+
def self.section_insert_mode(symbol)
|
90
|
+
{
|
91
|
+
last_row: XLFormSectionInsertModeLastRow,
|
92
|
+
button: XLFormSectionInsertModeButton
|
93
|
+
}[symbol] || symbol || XLFormSectionInsertModeLastRow
|
94
|
+
end
|
95
|
+
|
96
|
+
def self.section_options(symbol)
|
97
|
+
{
|
98
|
+
none: XLFormSectionOptionNone,
|
99
|
+
insert: XLFormSectionOptionCanInsert,
|
100
|
+
delete: XLFormSectionOptionCanDelete,
|
101
|
+
reorder: XLFormSectionOptionCanReorder
|
102
|
+
}[symbol] || symbol || XLFormSectionOptionNone
|
103
|
+
end
|
36
104
|
end
|
@@ -13,33 +13,33 @@ module ProMotion
|
|
13
13
|
|
14
14
|
if form_options[:on_cancel]
|
15
15
|
on_cancel = form_options[:on_cancel]
|
16
|
-
title
|
17
|
-
item
|
16
|
+
title = NSLocalizedString('Cancel', nil)
|
17
|
+
item = :cancel
|
18
18
|
if on_cancel.is_a? Hash
|
19
19
|
title = on_cancel[:title] if on_cancel[:title]
|
20
|
-
item
|
20
|
+
item = on_cancel[:item] if on_cancel[:item]
|
21
21
|
end
|
22
22
|
|
23
23
|
set_nav_bar_button :left, {
|
24
|
-
|
25
|
-
|
26
|
-
|
24
|
+
system_item: item,
|
25
|
+
title: title,
|
26
|
+
action: 'on_cancel:'
|
27
27
|
}
|
28
28
|
end
|
29
29
|
|
30
30
|
if form_options[:on_save]
|
31
31
|
on_cancel = form_options[:on_save]
|
32
|
-
title
|
33
|
-
item
|
32
|
+
title = NSLocalizedString('Save', nil)
|
33
|
+
item = :save
|
34
34
|
if on_cancel.is_a? Hash
|
35
35
|
title = on_cancel[:title] if on_cancel[:title]
|
36
|
-
item
|
36
|
+
item = on_cancel[:item] if on_cancel[:item]
|
37
37
|
end
|
38
38
|
|
39
39
|
set_nav_bar_button :right, {
|
40
|
-
|
41
|
-
|
42
|
-
|
40
|
+
system_item: item,
|
41
|
+
title: title,
|
42
|
+
action: 'on_save:'
|
43
43
|
}
|
44
44
|
end
|
45
45
|
|
@@ -53,30 +53,34 @@ module ProMotion
|
|
53
53
|
|
54
54
|
def update_form_data
|
55
55
|
form_options = self.class.get_form_options
|
56
|
-
title
|
57
|
-
required
|
56
|
+
title = self.class.title
|
57
|
+
required = form_options[:required]
|
58
58
|
|
59
59
|
@form_builder = PM::XLForm.new(self.form_data,
|
60
60
|
{
|
61
|
-
|
62
|
-
|
61
|
+
title: title,
|
62
|
+
required: required
|
63
63
|
})
|
64
|
-
@form_object
|
65
|
-
self.form
|
64
|
+
@form_object = @form_builder.build
|
65
|
+
self.form = @form_object
|
66
66
|
end
|
67
67
|
|
68
68
|
def values
|
69
69
|
values = {}
|
70
70
|
formValues.each do |key, value|
|
71
|
-
|
72
|
-
value = value.formValue
|
73
|
-
end
|
74
|
-
values[key] = value
|
71
|
+
values[key] = clean_value(value)
|
75
72
|
end
|
76
73
|
|
77
74
|
values
|
78
75
|
end
|
79
76
|
|
77
|
+
def value_for_cell(tag)
|
78
|
+
if tag.respond_to?(:to_s)
|
79
|
+
tag = tag.to_s
|
80
|
+
end
|
81
|
+
values.has_key?(tag) ? values[tag] : nil
|
82
|
+
end
|
83
|
+
|
80
84
|
def valid?
|
81
85
|
validation_errors.empty?
|
82
86
|
end
|
@@ -91,23 +95,31 @@ module ProMotion
|
|
91
95
|
end
|
92
96
|
|
93
97
|
if NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1
|
94
|
-
alert
|
95
|
-
|
96
|
-
|
98
|
+
alert = UIAlertController.alertControllerWithTitle(NSLocalizedString('Error', nil),
|
99
|
+
message: errors.join(', '),
|
100
|
+
preferredStyle: UIAlertControllerStyleAlert)
|
97
101
|
action = UIAlertAction.actionWithTitle(NSLocalizedString('OK', nil),
|
98
|
-
style:
|
102
|
+
style: UIAlertActionStyleDefault,
|
99
103
|
handler: nil)
|
100
104
|
alert.addAction(action)
|
101
105
|
presentViewController(alert, animated: true, completion: nil)
|
102
106
|
else
|
103
|
-
alert
|
104
|
-
alert.title
|
107
|
+
alert = UIAlertView.new
|
108
|
+
alert.title = NSLocalizedString('Error', nil)
|
105
109
|
alert.message = errors.join(', ')
|
106
110
|
alert.addButtonWithTitle(NSLocalizedString('OK', nil))
|
107
111
|
alert.show
|
108
112
|
end
|
109
113
|
end
|
110
114
|
|
115
|
+
def section_with_tag(tag)
|
116
|
+
if tag.respond_to? :to_s
|
117
|
+
tag = tag.to_s
|
118
|
+
end
|
119
|
+
self.form.formSections.select { |section| section.multivaluedTag && section.multivaluedTag == tag }
|
120
|
+
.first
|
121
|
+
end
|
122
|
+
|
111
123
|
def cell_with_tag(tag)
|
112
124
|
if tag.respond_to? :to_s
|
113
125
|
tag = tag.to_s
|
@@ -202,28 +214,32 @@ module ProMotion
|
|
202
214
|
end
|
203
215
|
|
204
216
|
## XLFormDescriptorDelegate
|
205
|
-
def formSectionHasBeenAdded(section, atIndex:
|
217
|
+
def formSectionHasBeenAdded(section, atIndex: index)
|
206
218
|
super
|
207
|
-
|
208
|
-
|
219
|
+
action = @form_builder.get_callback(section, :on_add)
|
220
|
+
return if action.nil?
|
221
|
+
trigger_action(action, row, index_path)
|
209
222
|
end
|
210
223
|
|
211
|
-
def formSectionHasBeenRemoved(section, atIndex:
|
224
|
+
def formSectionHasBeenRemoved(section, atIndex: index)
|
212
225
|
super
|
213
|
-
|
214
|
-
|
226
|
+
action = @form_builder.get_callback(section, :on_remove)
|
227
|
+
return if action.nil?
|
228
|
+
trigger_action(action, section, index)
|
215
229
|
end
|
216
230
|
|
217
|
-
def formRowHasBeenAdded(row, atIndexPath:
|
231
|
+
def formRowHasBeenAdded(row, atIndexPath: index_path)
|
218
232
|
super
|
219
|
-
|
220
|
-
|
233
|
+
action = @form_builder.get_callback(row, :on_add)
|
234
|
+
return if action.nil?
|
235
|
+
trigger_action(action, row, index_path)
|
221
236
|
end
|
222
237
|
|
223
|
-
def formRowHasBeenRemoved(row, atIndexPath:
|
238
|
+
def formRowHasBeenRemoved(row, atIndexPath: index_path)
|
224
239
|
super
|
225
|
-
|
226
|
-
|
240
|
+
action = @form_builder.get_callback(row, :on_remove)
|
241
|
+
return if action.nil?
|
242
|
+
trigger_action(action, row, index_path)
|
227
243
|
end
|
228
244
|
|
229
245
|
def formRowDescriptorValueHasChanged(row, oldValue: old_value, newValue: new_value)
|
@@ -241,5 +257,37 @@ module ProMotion
|
|
241
257
|
end
|
242
258
|
end
|
243
259
|
|
260
|
+
def formRowFormMultivaluedFormSection(section)
|
261
|
+
if section.multivaluedRowTemplate
|
262
|
+
cell_data = section.multivaluedRowTemplate.cell_data
|
263
|
+
else
|
264
|
+
cell_data = section.section_data[:cells].first
|
265
|
+
end
|
266
|
+
|
267
|
+
@form_builder.create_cell(cell_data)
|
268
|
+
end
|
269
|
+
|
270
|
+
private
|
271
|
+
def trigger_action(action, section_or_row, index_path)
|
272
|
+
case arity = action.arity
|
273
|
+
when 0 then
|
274
|
+
action.call # Just call the proc or the method
|
275
|
+
when 2 then
|
276
|
+
action.call(section_or_row, index_path) # Send arguments and index path
|
277
|
+
else
|
278
|
+
mp("Action should not have optional parameters: #{action.to_s}", force_color: :yellow) if arity < 0
|
279
|
+
action.call(section_or_row)
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
def clean_value(value)
|
284
|
+
if value.is_a? XLFormOptionsObject
|
285
|
+
value = value.formValue
|
286
|
+
elsif value.is_a? Array
|
287
|
+
value = value.map { |v| clean_value(v) }
|
288
|
+
end
|
289
|
+
|
290
|
+
value
|
291
|
+
end
|
244
292
|
end
|
245
293
|
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module ProMotion
|
2
|
+
module XLFormSectionBuilder
|
3
|
+
|
4
|
+
def create_section(section_data)
|
5
|
+
section = XLFormSectionDescriptor.section(section_data)
|
6
|
+
|
7
|
+
tag = section_data[:name]
|
8
|
+
if tag.respond_to? :to_s
|
9
|
+
tag = tag.to_s
|
10
|
+
end
|
11
|
+
unless section.options.nil?
|
12
|
+
mp("MutliValued section with no :name option", force_color: :red) unless tag
|
13
|
+
end
|
14
|
+
|
15
|
+
# force a tag for procs
|
16
|
+
if tag.nil?
|
17
|
+
@section_index ||= 0
|
18
|
+
tag = "section_#{@section_index}"
|
19
|
+
end
|
20
|
+
section.multivaluedTag = tag
|
21
|
+
|
22
|
+
section.footerTitle = section_data[:footer] if section_data[:footer]
|
23
|
+
|
24
|
+
add_proc tag, :on_add, section_data[:on_add] if section_data[:on_add]
|
25
|
+
add_proc tag, :on_remove, section_data[:on_remove] if section_data[:on_remove]
|
26
|
+
|
27
|
+
# section visible
|
28
|
+
if section_data[:hidden]
|
29
|
+
configure_hidden(section, section_data[:hidden])
|
30
|
+
end
|
31
|
+
|
32
|
+
section_data[:cells].each do |cell_data|
|
33
|
+
cell = create_cell(cell_data)
|
34
|
+
|
35
|
+
section.addFormRow(cell)
|
36
|
+
|
37
|
+
# multi sections
|
38
|
+
if section.multivaluedTag
|
39
|
+
cell.action.required = @required
|
40
|
+
section.multivaluedRowTemplate = cell.copy
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
section
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
@@ -4,34 +4,34 @@ module ProMotion
|
|
4
4
|
|
5
5
|
def form_data
|
6
6
|
[
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
7
|
+
{
|
8
|
+
title: rowDescriptor.title,
|
9
|
+
cells: rowDescriptor.action.cells.map do |cell|
|
10
|
+
tag = cell[:name]
|
11
|
+
if tag.respond_to? :to_s
|
12
|
+
tag = tag.to_s
|
13
|
+
end
|
14
|
+
if rowDescriptor && rowDescriptor.value && rowDescriptor.value[tag]
|
15
|
+
cell.merge({ value: rowDescriptor.value[tag] })
|
16
|
+
else
|
17
|
+
cell
|
18
|
+
end
|
19
|
+
end
|
20
|
+
}
|
21
21
|
]
|
22
22
|
end
|
23
23
|
|
24
24
|
def update_form_data
|
25
|
-
title
|
26
|
-
required
|
25
|
+
title = rowDescriptor.title
|
26
|
+
required = rowDescriptor.action.required
|
27
27
|
|
28
28
|
@form_builder = PM::XLForm.new(self.form_data,
|
29
29
|
{
|
30
|
-
|
31
|
-
|
30
|
+
title: title,
|
31
|
+
required: required
|
32
32
|
})
|
33
|
-
@form_object
|
34
|
-
self.form
|
33
|
+
@form_object = @form_builder.build
|
34
|
+
self.form = @form_object
|
35
35
|
end
|
36
36
|
|
37
37
|
## XLFormDescriptorDelegate
|
@@ -40,4 +40,4 @@ module ProMotion
|
|
40
40
|
rowDescriptor.value = values
|
41
41
|
end
|
42
42
|
end
|
43
|
-
end
|
43
|
+
end
|