glib-web 4.39.0 → 4.39.2

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.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/concerns/glib/auth/policy.rb +13 -0
  3. data/app/controllers/glib/api_docs_controller.rb +145 -0
  4. data/app/helpers/glib/json_ui/abstract_builder.rb +16 -0
  5. data/app/helpers/glib/json_ui/action_builder/dialogs.rb +4 -0
  6. data/app/helpers/glib/json_ui/list_builders.rb +2 -0
  7. data/app/helpers/glib/json_ui/view_builder/fields.rb +15 -0
  8. data/app/helpers/glib/json_ui/view_builder/panels.rb +450 -11
  9. data/app/helpers/glib/json_ui/view_builder.rb +1 -1
  10. data/app/views/glib/api_docs/component.json.jbuilder +215 -0
  11. data/app/views/glib/api_docs/index.json.jbuilder +103 -0
  12. data/app/views/glib/api_docs/show.json.jbuilder +111 -0
  13. data/app/views/json_ui/garage/actions/_dialogs.json.jbuilder +2 -2
  14. data/app/views/json_ui/garage/forms/dynamic_group.json.jbuilder +2 -2
  15. data/app/views/json_ui/garage/forms/file_upload_new.json.jbuilder +1 -1
  16. data/app/views/json_ui/garage/forms/partial_update.json.jbuilder +12 -12
  17. data/app/views/json_ui/garage/forms/selects.json.jbuilder +1 -1
  18. data/app/views/json_ui/garage/forms/show_hide.json.jbuilder +62 -7
  19. data/app/views/json_ui/garage/lists/edit_mode.json.jbuilder +4 -4
  20. data/app/views/json_ui/garage/lists/templating.json.jbuilder +68 -44
  21. data/app/views/json_ui/garage/pages/custom_style_class.json.jbuilder +1 -1
  22. data/app/views/json_ui/garage/pages/nav_buttons.json.jbuilder +31 -13
  23. data/app/views/json_ui/garage/panels/_styled.json.jbuilder +8 -8
  24. data/app/views/json_ui/garage/panels/hover.json.jbuilder +2 -2
  25. data/app/views/json_ui/garage/panels/timeline.json.jbuilder +5 -5
  26. data/app/views/json_ui/garage/panels/ul.json.jbuilder +1 -1
  27. data/app/views/json_ui/garage/tables/bulk_edit.json.jbuilder +1 -1
  28. data/app/views/json_ui/garage/test_page/file_upload_new.json.jbuilder +1 -1
  29. data/app/views/json_ui/garage/test_page/form.json.jbuilder +6 -6
  30. data/app/views/json_ui/garage/test_page/form_dynamic.json.jbuilder +2 -2
  31. data/app/views/json_ui/garage/test_page/logics_set.json.jbuilder +94 -0
  32. data/app/views/json_ui/garage/views/components_replace.json.jbuilder +13 -13
  33. data/app/views/json_ui/garage/views/components_set.json.jbuilder +6 -6
  34. data/app/views/json_ui/garage/views/fields_focus.json.jbuilder +22 -22
  35. data/app/views/json_ui/garage/views/markdowns.json.jbuilder +2 -0
  36. data/config/routes.rb +4 -0
  37. data/lib/glib/doc_generator.rb +386 -0
  38. data/lib/glib/json_crawler/router.rb +45 -24
  39. data/lib/glib/rubocop/cops/json_ui/base_nested_parameter.rb +145 -0
  40. data/lib/glib/rubocop/cops/json_ui/nested_action_parameter.rb +55 -0
  41. data/lib/glib/rubocop/cops/json_ui/nested_block_parameter.rb +51 -0
  42. data/lib/glib/rubocop/cops/multiline_method_call_style.rb +74 -5
  43. data/lib/glib/rubocop/cops/test_name_parentheses.rb +33 -0
  44. data/lib/glib/rubocop.rb +4 -0
  45. data/lib/glib/test/parallel_coverage.rb +38 -0
  46. data/lib/glib/test_helpers.rb +12 -0
  47. data/lib/glib-web.rb +1 -0
  48. data/lib/tasks/db.rake +1 -1
  49. data/lib/tasks/docs.rake +59 -0
  50. metadata +13 -1
@@ -0,0 +1,215 @@
1
+ json.title @component['class_name']
2
+
3
+ page = json_ui_page json
4
+
5
+ page.scroll padding: glib_json_padding_body, childViews: ->(scroll) do
6
+ # Back button
7
+ scroll.button \
8
+ text: "← Back to #{@category.titleize}",
9
+ styleClasses: ['btn-outline-secondary', 'btn-sm'],
10
+ onClick: ->(action) do
11
+ action.windows_open url: json_ui_api_url(category: @category)
12
+ end
13
+
14
+ scroll.spacer height: 16
15
+
16
+ # Title
17
+ scroll.panels_horizontal align: 'middle', childViews: ->(title_row) do
18
+ title_row.h1 text: @component['class_name']
19
+
20
+ if @component['extends']
21
+ title_row.spacer width: 12
22
+ title_row.h5 text: "extends #{@component['extends']}", styleClass: 'text-muted'
23
+ end
24
+ end
25
+
26
+ # Deprecated warning
27
+ if @component['deprecated']
28
+ scroll.spacer height: 16
29
+ scroll.panels_vertical \
30
+ padding: { all: 16 },
31
+ backgroundColor: '#fff3cd',
32
+ styleClasses: ['rounded'],
33
+ childViews: ->(warning) do
34
+ warning.h5 text: '⚠️ Deprecated', color: '#856404'
35
+ deprecation_text = @component['deprecated'] == true ? 'This component is deprecated and should not be used in new code.' : @component['deprecated']
36
+ warning.p text: deprecation_text, color: '#856404'
37
+ end
38
+ end
39
+
40
+ scroll.spacer height: 24
41
+
42
+ # Description
43
+ if @component['description']
44
+ scroll.h3 text: 'Description'
45
+ @component['description'].split("\n\n").each do |paragraph|
46
+ scroll.p text: paragraph.strip, styleClass: 'lead'
47
+ end
48
+ scroll.spacer height: 32
49
+ end
50
+
51
+ # Properties
52
+ if @component['properties'] && @component['properties'].any?
53
+ scroll.h2 text: 'Properties'
54
+ scroll.spacer height: 16
55
+
56
+ @component['properties'].each do |prop_name, prop|
57
+ scroll.panels_vertical \
58
+ padding: { all: 16 },
59
+ styleClasses: ['card', 'rounded'],
60
+ childViews: ->(prop_card) do
61
+ # Property name and badges
62
+ prop_card.panels_horizontal align: 'middle', childViews: ->(header) do
63
+ header.h5 text: prop_name, styleClass: 'font-monospace'
64
+ header.spacer width: 8
65
+
66
+ # Type badge
67
+ type_color = case prop['type']
68
+ when 'string', 'text' then '#0d6efd'
69
+ when 'int', 'float' then '#198754'
70
+ when 'bool' then '#0dcaf0'
71
+ when 'action' then '#ffc107'
72
+ when 'views', 'panels_builder' then '#6c757d'
73
+ when 'hash', 'array' then '#212529'
74
+ else '#f8f9fa'
75
+ end
76
+
77
+ header.label text: prop['type'], backgroundColor: type_color, styleClasses: ['badge'], color: '#ffffff'
78
+
79
+ if prop['required']
80
+ header.spacer width: 4
81
+ header.label text: 'required', backgroundColor: '#dc3545', styleClasses: ['badge'], color: '#ffffff'
82
+ end
83
+
84
+ if prop['deprecated']
85
+ header.spacer width: 4
86
+ header.label text: 'deprecated', backgroundColor: '#ffc107', styleClasses: ['badge']
87
+ end
88
+ end
89
+
90
+ # Description
91
+ if prop['description']
92
+ prop_card.spacer height: 8
93
+ prop['description'].split("\n").each do |line|
94
+ prop_card.p text: line.strip
95
+ end
96
+ end
97
+
98
+ # Hash options
99
+ if prop['options'] && prop['options']['optional']
100
+ prop_card.spacer height: 8
101
+ prop_card.label text: 'Optional hash keys:', styleClass: 'text-muted'
102
+ prop_card.label text: prop['options']['optional'].join(', '), styleClass: 'font-monospace'
103
+ end
104
+
105
+ # Examples
106
+ if prop['examples'] && prop['examples'].any?
107
+ prop_card.spacer height: 8
108
+ prop_card.label text: 'Example:', styleClasses: ['text-muted', 'font-weight-bold']
109
+ prop['examples'].each do |example|
110
+ prop_card.panels_vertical \
111
+ padding: { all: 12 },
112
+ backgroundColor: '#f6f8fa',
113
+ styleClasses: ['rounded'],
114
+ childViews: ->(code_block) do
115
+ code_block.label text: example, styleClass: 'font-monospace'
116
+ end
117
+ end
118
+ end
119
+
120
+ # Notes
121
+ if prop['notes'] && prop['notes'].any?
122
+ prop_card.spacer height: 8
123
+ prop_card.panels_vertical \
124
+ padding: { all: 12 },
125
+ backgroundColor: '#cfe2ff',
126
+ styleClasses: ['rounded'],
127
+ childViews: ->(note_block) do
128
+ note_block.label text: 'Note:', styleClasses: ['font-weight-bold'], color: '#084298'
129
+ prop['notes'].each do |note|
130
+ note_block.label text: note, color: '#084298'
131
+ end
132
+ end
133
+ end
134
+
135
+ # Deprecation
136
+ if prop['deprecated']
137
+ prop_card.spacer height: 8
138
+ prop_card.panels_vertical \
139
+ padding: { all: 12 },
140
+ backgroundColor: '#fff3cd',
141
+ styleClasses: ['rounded'],
142
+ childViews: ->(dep_block) do
143
+ dep_block.label text: 'Deprecated:', styleClasses: ['font-weight-bold'], color: '#856404'
144
+ dep_block.label text: prop['deprecated'], color: '#856404'
145
+ end
146
+ end
147
+ end
148
+
149
+ scroll.spacer height: 12
150
+ end
151
+
152
+ scroll.spacer height: 32
153
+ end
154
+
155
+ # Examples
156
+ if @component['examples'] && @component['examples'].any?
157
+ scroll.h2 text: 'Examples'
158
+ scroll.spacer height: 16
159
+
160
+ @component['examples'].each_with_index do |example, index|
161
+ scroll.panels_vertical \
162
+ styleClasses: ['card'],
163
+ childViews: ->(example_card) do
164
+ # Header
165
+ example_card.panels_vertical \
166
+ padding: { all: 12 },
167
+ backgroundColor: '#f8f9fa',
168
+ childViews: ->(header) do
169
+ header.h5 text: example['label'] || "Example #{index + 1}"
170
+ end
171
+
172
+ # Code
173
+ example_card.panels_vertical \
174
+ padding: { all: 16 },
175
+ backgroundColor: '#f6f8fa',
176
+ childViews: ->(code_block) do
177
+ example['code'].split("\n").each do |line|
178
+ code_block.label text: line, styleClass: 'font-monospace'
179
+ end
180
+ end
181
+ end
182
+
183
+ scroll.spacer height: 12
184
+ end
185
+
186
+ scroll.spacer height: 32
187
+ end
188
+
189
+ # References
190
+ if @component['references'] && @component['references'].any?
191
+ scroll.h2 text: 'References'
192
+ scroll.spacer height: 16
193
+
194
+ scroll.panels_vertical styleClasses: ['card'], childViews: ->(refs) do
195
+ @component['references'].each do |ref|
196
+ refs.panels_vertical padding: { all: 12 }, childViews: ->(ref_item) do
197
+ if ref['url']
198
+ ref_item.button \
199
+ text: ref['url'],
200
+ styleClasses: ['btn-link', 'text-start'],
201
+ onClick: ->(action) do
202
+ action.windows_open url: ref['url']
203
+ end
204
+
205
+ if ref['description']
206
+ ref_item.label text: ref['description'], styleClasses: ['text-muted', 'text-small']
207
+ end
208
+ else
209
+ ref_item.label text: ref['text'], styleClass: 'font-monospace'
210
+ end
211
+ end
212
+ end
213
+ end
214
+ end
215
+ end
@@ -0,0 +1,103 @@
1
+ json.title 'Glib Component API Documentation'
2
+
3
+ page = json_ui_page json
4
+
5
+ page.scroll padding: glib_json_padding_body, childViews: ->(scroll) do
6
+ # Header
7
+ scroll.panels_vertical \
8
+ padding: { top: 32, bottom: 32 },
9
+ backgroundColor: '#667eea',
10
+ align: 'center',
11
+ childViews: ->(header) do
12
+ header.h1 text: 'Glib Component API', color: '#ffffff'
13
+ header.p text: 'Interactive documentation for all Glib UI components', color: '#ffffff'
14
+ header.label text: 'Auto-generated from YARD comments in source code', color: '#e0e0e0', styleClass: 'text-small'
15
+ end
16
+
17
+ scroll.spacer height: 32
18
+
19
+ # Title
20
+ scroll.h2 text: 'Component Categories'
21
+ scroll.p text: 'Browse components by category', styleClass: 'text-muted'
22
+
23
+ scroll.spacer height: 16
24
+
25
+ if @categories.empty?
26
+ # Warning message
27
+ scroll.panels_vertical \
28
+ padding: { all: 16 },
29
+ backgroundColor: '#fff3cd',
30
+ styleClasses: ['rounded'],
31
+ childViews: ->(warning) do
32
+ warning.h4 text: 'No Documentation Found', color: '#856404'
33
+ warning.p text: 'Component documentation has not been generated yet.'
34
+ warning.p text: 'Run bin/generate_component_docs to generate documentation.', styleClass: 'code'
35
+ end
36
+ else
37
+ # Categories grid
38
+ scroll.panels_responsive width: 'matchParent', childViews: ->(responsive) do
39
+ @categories.each do |category|
40
+ responsive.panels_column \
41
+ lg: { cols: 4 },
42
+ md: { cols: 6 },
43
+ xs: { cols: 12 },
44
+ childViews: ->(col) do
45
+ col.panels_vertical \
46
+ padding: { all: 16 },
47
+ styleClasses: ['card', 'rounded'],
48
+ onClick: ->(action) do
49
+ action.windows_open url: json_ui_api_url(category: category['key'])
50
+ end,
51
+ childViews: ->(card) do
52
+ # Title with badge
53
+ card.panels_horizontal \
54
+ align: 'middle',
55
+ childViews: ->(title_row) do
56
+ title_row.h5 text: category['name']
57
+ title_row.spacer width: 8
58
+ title_row.label \
59
+ text: "#{category['component_count']} components",
60
+ styleClasses: ['badge', 'bg-primary']
61
+ end
62
+
63
+ card.spacer height: 8
64
+
65
+ # Source file
66
+ if category['source_file']
67
+ card.label \
68
+ text: File.basename(category['source_file']),
69
+ styleClasses: ['text-muted', 'text-small', 'font-monospace']
70
+ end
71
+
72
+ card.spacer height: 12
73
+
74
+ # Button
75
+ card.button \
76
+ text: 'View Components →',
77
+ styleClasses: ['btn-outline-primary', 'btn-sm']
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+
84
+ scroll.spacer height: 48
85
+
86
+ # About section
87
+ scroll.h3 text: 'About This Documentation'
88
+ scroll.panels_vertical styleClasses: ['card'], padding: { all: 16 }, childViews: ->(about) do
89
+ about.p text: 'This documentation is automatically generated from YARD comments in the Glib source code. Each component includes:'
90
+
91
+ about.panels_ul childViews: ->(ul) do
92
+ ul.label text: 'Description - What the component does and when to use it'
93
+ ul.label text: 'Properties - All available properties with types and descriptions'
94
+ ul.label text: 'Examples - Real code examples showing how to use the component'
95
+ ul.label text: 'References - Links to external documentation and garage examples'
96
+ end
97
+
98
+ about.spacer height: 8
99
+ about.label \
100
+ text: 'For more information, see doc/components/README.md and doc/common/component_documentation_guidelines.md',
101
+ styleClasses: ['text-muted', 'text-small']
102
+ end
103
+ end
@@ -0,0 +1,111 @@
1
+ json.title "#{@category.titleize} Components"
2
+
3
+ page = json_ui_page json
4
+
5
+ page.scroll padding: glib_json_padding_body, childViews: ->(scroll) do
6
+ # Back button
7
+ scroll.button \
8
+ text: '← Back to Categories',
9
+ styleClasses: ['btn-outline-secondary', 'btn-sm'],
10
+ onClick: ->(action) do
11
+ action.windows_open url: json_ui_api_url
12
+ end
13
+
14
+ scroll.spacer height: 16
15
+
16
+ # Title
17
+ scroll.h2 text: "#{@category.titleize} Components"
18
+
19
+ # Metadata
20
+ if @doc['meta']
21
+ scroll.panels_vertical \
22
+ padding: { all: 12 },
23
+ backgroundColor: '#f8f9fa',
24
+ styleClasses: ['rounded'],
25
+ childViews: ->(meta) do
26
+ meta.label \
27
+ text: "Source: #{@doc['meta']['source_file']}",
28
+ styleClasses: ['text-muted', 'text-small', 'font-monospace']
29
+
30
+ if @doc['meta']['generated_at']
31
+ generated_time = Time.parse(@doc['meta']['generated_at']).strftime('%Y-%m-%d %H:%M') rescue @doc['meta']['generated_at']
32
+ meta.label \
33
+ text: "Generated: #{generated_time}",
34
+ styleClasses: ['text-muted', 'text-small']
35
+ end
36
+ end
37
+ end
38
+
39
+ scroll.spacer height: 24
40
+
41
+ # Component cards
42
+ @components.sort.each do |key, component|
43
+ scroll.panels_vertical \
44
+ id: key,
45
+ padding: { all: 16 },
46
+ styleClasses: ['card', 'rounded'],
47
+ childViews: ->(card) do
48
+ # Title
49
+ card.panels_horizontal align: 'middle', childViews: ->(title_row) do
50
+ title_row.h4 text: component['class_name']
51
+
52
+ if component['extends']
53
+ title_row.spacer width: 8
54
+ title_row.label \
55
+ text: "extends #{component['extends']}",
56
+ styleClasses: ['text-muted']
57
+ end
58
+ end
59
+
60
+ # Deprecated warning
61
+ if component['deprecated']
62
+ card.spacer height: 8
63
+ card.panels_vertical \
64
+ padding: { all: 12 },
65
+ backgroundColor: '#fff3cd',
66
+ styleClasses: ['rounded'],
67
+ childViews: ->(warning) do
68
+ warning.label text: '⚠️ Deprecated', color: '#856404', styleClass: 'font-weight-bold'
69
+ deprecation_text = component['deprecated'] == true ? 'This component is deprecated' : component['deprecated']
70
+ warning.label text: deprecation_text, color: '#856404'
71
+ end
72
+ end
73
+
74
+ # Description
75
+ if component['description']
76
+ card.spacer height: 12
77
+ component['description'].split("\n\n").each do |paragraph|
78
+ card.p text: paragraph.strip
79
+ end
80
+ end
81
+
82
+ card.spacer height: 12
83
+
84
+ # Metadata and View Details button
85
+ card.panels_horizontal align: 'middle', childViews: ->(actions) do
86
+ actions.button \
87
+ text: 'View Details →',
88
+ styleClasses: ['btn-outline-primary', 'btn-sm'],
89
+ onClick: ->(action) do
90
+ action.windows_open url: json_ui_api_url(category: @category, component: key)
91
+ end
92
+
93
+ if component['properties']
94
+ actions.spacer width: 12
95
+ actions.label \
96
+ text: "#{component['properties'].size} #{'property'.pluralize(component['properties'].size)}",
97
+ styleClasses: ['text-muted']
98
+ end
99
+
100
+ if component['examples']
101
+ actions.spacer width: 12
102
+ actions.label \
103
+ text: "#{component['examples'].size} #{'example'.pluralize(component['examples'].size)}",
104
+ styleClasses: ['text-muted']
105
+ end
106
+ end
107
+ end
108
+
109
+ scroll.spacer height: 16
110
+ end
111
+ end
@@ -5,8 +5,8 @@ end
5
5
 
6
6
  section.rows builder: ->(template) do
7
7
  template.thumbnail title: 'dialogs/alert', onClick: ->(action) do
8
- action.dialogs_alert message: 'This is an alert dialog', onClose: ->(action) do
9
- action.snackbars_alert message: 'Closed'
8
+ action.dialogs_alert message: 'This is an alert dialog', onClose: ->(subaction) do
9
+ subaction.snackbars_alert message: 'Closed'
10
10
  end
11
11
  end
12
12
 
@@ -37,7 +37,7 @@ page.form url: json_ui_garage_url(path: 'forms/generic_post'), method: 'post', p
37
37
  template.fields_text width: 'matchParent', name: 'question', label: 'Question', placeholder: 'Question'
38
38
  template.fields_richText width: 'matchParent', name: 'description', label: 'Desc', placeholder: 'Desc'
39
39
 
40
- form.panels_responsive id: 'responsive_{{entryIndex}}', childViews: ->(column) do
40
+ template.panels_responsive id: 'responsive_{{entryIndex}}', childViews: ->(column) do
41
41
  column.panels_split width: 'matchParent', content: ->(split) do
42
42
  split.center childViews: ->(center) do
43
43
  center.fields_dynamicSelect \
@@ -51,7 +51,7 @@ page.form url: json_ui_garage_url(path: 'forms/generic_post'), method: 'post', p
51
51
  end
52
52
 
53
53
  options = [:rating, :yes_no, :choices, :unspecified]
54
- template.fields_select \
54
+ column.fields_select \
55
55
  width: 'matchParent',
56
56
  name: 'type',
57
57
  label: 'Answer Type',
@@ -58,7 +58,7 @@ page.form \
58
58
  form.h2 text: 'Field Upload', styleClass: 'pb-4'
59
59
  form.label text: 'placeholder image', styleClass: 'pb-1'
60
60
  form.panels_flow styleClass: 'align-center', xs: { gap: { all: 4 } }, childViews: ->(flow) do
61
- form.fields_upload properties.merge(
61
+ flow.fields_upload properties.merge(
62
62
  name: 'user[file_placeholderView]',
63
63
  id: 'pv1',
64
64
  placeholderView: { type: 'image', url: image&.url, width: 144, height: 144 }
@@ -5,13 +5,13 @@ render "#{@path_prefix}/nav_menu", json: json, page: page
5
5
 
6
6
  page.scroll childViews: ->(scroll) do
7
7
  scroll.panels_vertical padding: glib_json_padding_body, childViews: ->(vertical) do
8
- scroll.h2 text: 'Partial update'
9
- scroll.spacer height: 8
10
- scroll.label text: 'The content below will be updated. This is a more efficient alternative to windows_reload.'
11
- scroll.spacer height: 8
12
- scroll.label text: 'The updated content should be committed to the page history as the user navigates back and forward.'
13
- scroll.spacer height: 18
14
- scroll.panels_vertical id: 'greeting', childViews: ->(inner) do
8
+ vertical.h2 text: 'Partial update'
9
+ vertical.spacer height: 8
10
+ vertical.label text: 'The content below will be updated. This is a more efficient alternative to windows_reload.'
11
+ vertical.spacer height: 8
12
+ vertical.label text: 'The updated content should be committed to the page history as the user navigates back and forward.'
13
+ vertical.spacer height: 18
14
+ vertical.panels_vertical id: 'greeting', childViews: ->(inner) do
15
15
  inner.fields_hidden name: 'name', value: '<uninitialized>'
16
16
  inner.label text: 'Hello'
17
17
  end
@@ -21,11 +21,11 @@ page.scroll childViews: ->(scroll) do
21
21
  scroll.hr width: 'matchParent'
22
22
 
23
23
  scroll.panels_form url: json_ui_garage_url(path: 'forms/partial_update_response'), method: 'post', padding: glib_json_padding_body, childViews: ->(form) do
24
- scroll.h2 text: 'Update via POST request'
25
- scroll.spacer height: 8
26
- scroll.fields_text name: 'name', width: 'matchParent', label: 'Name', value: 'Jane'
27
- scroll.spacer height: 8
28
- scroll.fields_submit text: 'Submit'
24
+ form.h2 text: 'Update via POST request'
25
+ form.spacer height: 8
26
+ form.fields_text name: 'name', width: 'matchParent', label: 'Name', value: 'Jane'
27
+ form.spacer height: 8
28
+ form.fields_submit text: 'Submit'
29
29
  end
30
30
 
31
31
  scroll.spacer height: 18
@@ -20,7 +20,7 @@ page.form id: 'form', url: json_ui_garage_url(path: 'forms/generic_post'), metho
20
20
  options = languages.map do |k, v|
21
21
  { value: k, text: v }
22
22
  end
23
- form.fields_select \
23
+ column.fields_select \
24
24
  name: 'user[city]',
25
25
  width: 'matchParent',
26
26
  clearable: true,
@@ -153,6 +153,61 @@ page.form \
153
153
  form.label id: 'radiolabel1', text: 'Yes'
154
154
  form.label id: 'radiolabel2', text: 'No'
155
155
 
156
+ form.spacer height: 20
157
+
158
+ form.fields_radioGroup name: 'user[radio10]', value: 'no', childViews: ->(group) do
159
+ group.panels_horizontal childViews: ->(horizontal) do
160
+ horizontal.fields_radio label: 'Hourly rate', value: 'hourly_rate'
161
+ horizontal.spacer width: 20
162
+ horizontal.fields_radio label: 'Fixed amount', value: 'fixed_amount'
163
+ end
164
+ end, onChangeAndLoad: ->(action) do
165
+ action.runMultiple childActions: ->(multiple) do
166
+ multiple.logics_set \
167
+ targetId: 'pricing_hourly_rate_field',
168
+ conditionalData: {
169
+ displayed: {
170
+ "==": [
171
+ { "var": 'user[radio10]' },
172
+ 'hourly_rate'
173
+ ]
174
+ }
175
+ }
176
+
177
+ multiple.logics_set \
178
+ targetId: 'pricing_fixed_amount_field',
179
+ conditionalData: {
180
+ displayed: {
181
+ "==": [
182
+ { "var": 'user[radio10]' },
183
+ 'fixed_amount'
184
+ ]
185
+ }
186
+ }
187
+ end
188
+ end
189
+
190
+ form.fields_number \
191
+ id: 'pricing_hourly_rate_field',
192
+ name: 'user[pricing_hourly_rate]',
193
+ width: 160,
194
+ styleClass: 'outlined',
195
+ leftIcon: 'attach_money',
196
+ rightText: '.00'
197
+
198
+ form.panels_horizontal \
199
+ id: 'pricing_fixed_amount_field', \
200
+ width: 'matchParent', \
201
+ align: 'middle', \
202
+ childViews: ->(horizontal) do
203
+ horizontal.fields_number \
204
+ name: 'user[pricing_fixed_amount]',
205
+ width: 160,
206
+ styleClass: 'outlined',
207
+ leftIcon: 'attach_money',
208
+ rightText: '.00'
209
+ end
210
+
156
211
  form.spacer height: 20
157
212
  form.h1 text: 'Radio Group'
158
213
  form.fields_radioGroup \
@@ -372,19 +427,19 @@ page.form \
372
427
  id: 'panel1',
373
428
  width: 'matchParent',
374
429
  childViews: ->(res) do
375
- form.fields_text name: 'user[loadif_target2]', width: 'matchParent', value: 'Value 1'
376
- form.spacer height: 4
377
- form.fields_textarea name: 'user[loadif_target3]', width: 'matchParent', value: 'Value 2'
378
- form.spacer height: 4
430
+ res.fields_text name: 'user[loadif_target2]', width: 'matchParent', value: 'Value 1'
431
+ res.spacer height: 4
432
+ res.fields_textarea name: 'user[loadif_target3]', width: 'matchParent', value: 'Value 2'
433
+ res.spacer height: 4
379
434
  end
380
435
 
381
436
  form.panels_responsive \
382
437
  id: 'panel2',
383
438
  width: 'matchParent',
384
439
  childViews: ->(res) do
385
- form.fields_richText name: 'user[loadIf_target4]', width: 'matchParent', value: 'Value 3'
386
- form.spacer height: 4
387
- form.fields_radioGroup name: 'user[loadIf_target5]', width: 'matchParent', value: 'choice_1', childViews: ->(group) do
440
+ res.fields_richText name: 'user[loadIf_target4]', width: 'matchParent', value: 'Value 3'
441
+ res.spacer height: 4
442
+ res.fields_radioGroup name: 'user[loadIf_target5]', width: 'matchParent', value: 'choice_1', childViews: ->(group) do
388
443
  group.fields_radio label: 'Choice 1', value: 'choice_1'
389
444
  group.fields_radio label: 'Choice 2', value: 'choice_2'
390
445
  group.fields_radio label: 'Choice 3', value: 'choice_3'
@@ -33,18 +33,18 @@ page.form \
33
33
  header.panels_horizontal childViews: ->(horizontal) do
34
34
  horizontal.fields_check name: 'user[check_all]', label: 'All', checkValue: true
35
35
 
36
- header.spacer width: 20
36
+ horizontal.spacer width: 20
37
37
  # header.fields_text width: 'matchParent', styleClass: 'outlined', name: 'user[new_name]', label: 'Item name'
38
38
  statuses = [:pending, :active]
39
- header.fields_select \
39
+ horizontal.fields_select \
40
40
  styleClass: 'outlined',
41
41
  name: 'user[status]',
42
42
  width: 'matchParent',
43
43
  label: 'Status',
44
44
  options: statuses.map { |status| { value: status, text: status.to_s.humanize } }
45
45
 
46
- header.spacer width: 20
47
- header.fields_submit text: 'Update'
46
+ horizontal.spacer width: 20
47
+ horizontal.fields_submit text: 'Update'
48
48
  end
49
49
  end
50
50
  section.rows builder: ->(row) do