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.
- checksums.yaml +4 -4
- data/app/controllers/concerns/glib/auth/policy.rb +13 -0
- data/app/controllers/glib/api_docs_controller.rb +145 -0
- data/app/helpers/glib/json_ui/abstract_builder.rb +16 -0
- data/app/helpers/glib/json_ui/action_builder/dialogs.rb +4 -0
- data/app/helpers/glib/json_ui/list_builders.rb +2 -0
- data/app/helpers/glib/json_ui/view_builder/fields.rb +15 -0
- data/app/helpers/glib/json_ui/view_builder/panels.rb +450 -11
- data/app/helpers/glib/json_ui/view_builder.rb +1 -1
- data/app/views/glib/api_docs/component.json.jbuilder +215 -0
- data/app/views/glib/api_docs/index.json.jbuilder +103 -0
- data/app/views/glib/api_docs/show.json.jbuilder +111 -0
- data/app/views/json_ui/garage/actions/_dialogs.json.jbuilder +2 -2
- data/app/views/json_ui/garage/forms/dynamic_group.json.jbuilder +2 -2
- data/app/views/json_ui/garage/forms/file_upload_new.json.jbuilder +1 -1
- data/app/views/json_ui/garage/forms/partial_update.json.jbuilder +12 -12
- data/app/views/json_ui/garage/forms/selects.json.jbuilder +1 -1
- data/app/views/json_ui/garage/forms/show_hide.json.jbuilder +62 -7
- data/app/views/json_ui/garage/lists/edit_mode.json.jbuilder +4 -4
- data/app/views/json_ui/garage/lists/templating.json.jbuilder +68 -44
- data/app/views/json_ui/garage/pages/custom_style_class.json.jbuilder +1 -1
- data/app/views/json_ui/garage/pages/nav_buttons.json.jbuilder +31 -13
- data/app/views/json_ui/garage/panels/_styled.json.jbuilder +8 -8
- data/app/views/json_ui/garage/panels/hover.json.jbuilder +2 -2
- data/app/views/json_ui/garage/panels/timeline.json.jbuilder +5 -5
- data/app/views/json_ui/garage/panels/ul.json.jbuilder +1 -1
- data/app/views/json_ui/garage/tables/bulk_edit.json.jbuilder +1 -1
- data/app/views/json_ui/garage/test_page/file_upload_new.json.jbuilder +1 -1
- data/app/views/json_ui/garage/test_page/form.json.jbuilder +6 -6
- data/app/views/json_ui/garage/test_page/form_dynamic.json.jbuilder +2 -2
- data/app/views/json_ui/garage/test_page/logics_set.json.jbuilder +94 -0
- data/app/views/json_ui/garage/views/components_replace.json.jbuilder +13 -13
- data/app/views/json_ui/garage/views/components_set.json.jbuilder +6 -6
- data/app/views/json_ui/garage/views/fields_focus.json.jbuilder +22 -22
- data/app/views/json_ui/garage/views/markdowns.json.jbuilder +2 -0
- data/config/routes.rb +4 -0
- data/lib/glib/doc_generator.rb +386 -0
- data/lib/glib/json_crawler/router.rb +45 -24
- data/lib/glib/rubocop/cops/json_ui/base_nested_parameter.rb +145 -0
- data/lib/glib/rubocop/cops/json_ui/nested_action_parameter.rb +55 -0
- data/lib/glib/rubocop/cops/json_ui/nested_block_parameter.rb +51 -0
- data/lib/glib/rubocop/cops/multiline_method_call_style.rb +74 -5
- data/lib/glib/rubocop/cops/test_name_parentheses.rb +33 -0
- data/lib/glib/rubocop.rb +4 -0
- data/lib/glib/test/parallel_coverage.rb +38 -0
- data/lib/glib/test_helpers.rb +12 -0
- data/lib/glib-web.rb +1 -0
- data/lib/tasks/db.rake +1 -1
- data/lib/tasks/docs.rake +59 -0
- 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: ->(
|
|
9
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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
|
-
|
|
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
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
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
|
-
|
|
386
|
-
|
|
387
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
47
|
-
|
|
46
|
+
horizontal.spacer width: 20
|
|
47
|
+
horizontal.fields_submit text: 'Update'
|
|
48
48
|
end
|
|
49
49
|
end
|
|
50
50
|
section.rows builder: ->(row) do
|