glib-web 3.24.3 → 3.25.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2aae0523d109fcf8f7e6b368ea3b64bc262f08fd3a7c1017a8ade64eba3185df
4
- data.tar.gz: 63d3d5b00d8b25e5450ed4eb5ebdd5658aaa4b4302f326e55bd7a5a5902d976e
3
+ metadata.gz: d2f5d2ae1abeb1b4204f3879a5561f0396f610ebc2805ff684ce1989b08041f5
4
+ data.tar.gz: 2ceb705bdc581a4e4fcf1b3f70b9ace090fb4af8576995310f2ec46813c7c1eb
5
5
  SHA512:
6
- metadata.gz: 103f9b75cab3048bd231a5cca4c94779031d57743bca95b631322dc82af1f956eb54e8220711230337594e28dda40d786fb58fd3491255e18f656a0ec07cdbff
7
- data.tar.gz: bd77f29f8ab4952f46840f9e18060140673f3de43d1f05de76e8a9cb4ba03ef58b05ca0f6a11919719bbab53cee8111cee12ba120c01e94d2391e16d515c7931
6
+ metadata.gz: 1f97d523b8eedd779e93c2cd54a27d5af356e4fc16287d141c0b3ec647596e7d0661713a2849c27b255684b2d7c8185a77f5a43bdcd625f15a621f86cacfa6dd
7
+ data.tar.gz: a87a2e17a6763771cb606910f3ce9c3011bde9b8e6d935c7a44616a66713ccc4aabade5d0b849b2b1c6ac078308c24ebc32ddecf7bbeb99ef6984f991be5cdda
@@ -35,7 +35,7 @@ module Glib
35
35
  eos
36
36
 
37
37
  # We can't use prepend_view_path because it affects the app, not the gem
38
- path = "#{@path_prefix}/#{params[:path] || 'home/index'}"
38
+ path = "#{@path_prefix}/#{params[:override_path] || params[:path] || 'home/index'}"
39
39
  render path
40
40
  end
41
41
 
@@ -16,6 +16,12 @@ class Glib::JsonUi::ActionBuilder
16
16
  end
17
17
 
18
18
  # Experimental
19
+ class ReplaceChildren < Action
20
+ string :targetId
21
+ views :childViews
22
+ end
23
+
24
+ # Experimental. Can this be merged with `components_set` ?
19
25
  class Replace < Action
20
26
  string :targetId
21
27
  action :onReplace
@@ -109,6 +109,30 @@ module Glib
109
109
  end
110
110
  end
111
111
 
112
+ module Logics
113
+ # Future: Replace showIf and loadIf
114
+ # Example:
115
+ # `submitWhenNotDisplayed` is false by default
116
+ # fields_text id: 'my_text', displayed: false, submitWhenNotDisplayed: true
117
+ #
118
+ # logics_if condition: { '==', BLAH1, BLAH2 }, true: ->(action) do
119
+ # action.components_set targetId: 'my_text', displayed: true
120
+ # end
121
+ #
122
+ # class If < Action
123
+ # hash :condition
124
+ # action :true
125
+ # action :false
126
+ # end
127
+
128
+ class Set < Action
129
+ string :targetId
130
+ hash :conditionalData
131
+ hash :variables
132
+ action :onSet
133
+ end
134
+ end
135
+
112
136
  module Timeouts
113
137
  class Set < Action
114
138
  string :timerId
@@ -141,7 +165,24 @@ module Glib
141
165
  end
142
166
  end
143
167
 
168
+ module Cookies
169
+ class Save < Action
170
+ string :key
171
+ string :value
172
+ action :onSave
173
+ end
174
+
175
+ # FUTURE
176
+ # class Remove < Action
177
+ # end
178
+
179
+ # FUTURE
180
+ # class Clear < Action
181
+ # end
182
+ end
183
+
144
184
  # FUTURE
185
+
145
186
  module Data
146
187
  class Save < Action
147
188
  string :key
@@ -183,6 +183,12 @@ module Glib
183
183
  end
184
184
  end
185
185
 
186
+ def bodyFooter(options = {})
187
+ json.bodyFooter do
188
+ vertical_content(options)
189
+ end
190
+ end
191
+
186
192
  def header(options = {})
187
193
  json.header do
188
194
  vertical_content(options)
@@ -50,6 +50,17 @@ module Glib
50
50
 
51
51
  ###
52
52
 
53
+ ### Chart
54
+
55
+ def glib_chart_tooltip_template(options)
56
+ %{
57
+ <div style="border: 1px solid gray; border-radius: 6px;">
58
+ <div style="border-radius: 6px 6px 0 0; background-color: gray; padding: 4px; color: white;">#{options[:title]}</div>
59
+ <div style="border-radius: 0 0 6px 6px; background-color: white; padding: 4px" color: black;>#{options[:content]}</div>
60
+ </div>
61
+ }
62
+ end
63
+
53
64
  end
54
65
  end
55
66
  end
@@ -10,6 +10,7 @@ class Glib::JsonUi::ViewBuilder
10
10
  bool :disableDirtyCheck
11
11
  action :onChange
12
12
  string :paramNameForFormData
13
+ string :paramNameForFieldName
13
14
 
14
15
  def default_url_options
15
16
  { only_path: true }
@@ -172,6 +173,11 @@ class Glib::JsonUi::ViewBuilder
172
173
  string :cacheKey
173
174
  end
174
175
 
176
+ # Deprecated
177
+ # Just use fields_select with options provided by the backend. This allows greater flexibility,
178
+ # which is important because different systems might want to use different values for
179
+ # countries as well as for regions, e.g. alpha2 vs alpha3
180
+ # See app/views/json_ui/garage/forms/pickers.json.jbuilder for an example
175
181
  class Country < AbstractField
176
182
  hash :region
177
183
  end
@@ -0,0 +1,18 @@
1
+
2
+ section.header padding: glib_json_padding_list, childViews: ->(header) do
3
+ header.h3 text: 'Components'
4
+ end
5
+
6
+ section.rows builder: ->(template) do
7
+ template.thumbnail title: 'components/update (Deprecated)', onClick: ->(action) do
8
+ action.windows_open url: json_ui_garage_url(path: 'views/components_update')
9
+ end
10
+
11
+ # template.thumbnail title: 'components/replace', onClick: ->(action) do
12
+ # action.windows_open url: json_ui_garage_url(path: 'views/components')
13
+ # end
14
+
15
+ template.thumbnail title: 'components/set', onClick: ->(action) do
16
+ action.windows_open url: json_ui_garage_url(path: 'views/components_set')
17
+ end
18
+ end
@@ -0,0 +1,12 @@
1
+
2
+ section.header padding: glib_json_padding_list, childViews: ->(header) do
3
+ header.h3 id: 'cookie', text: 'Cookies'
4
+ end
5
+
6
+ section.rows builder: ->(template) do
7
+ template.thumbnail title: 'cookies/save', onClick: ->(action) do
8
+ action.cookies_save key: 'glib_cookie', value: "test_cookie_#{DateTime.current.to_i}", onSave: ->(subaction) do
9
+ subaction.snackbars_alert message: 'Saved'
10
+ end
11
+ end
12
+ end
@@ -84,10 +84,18 @@ section.rows builder: ->(template) do
84
84
  action.dialogs_open url: json_ui_garage_url(path: 'forms/dialogs_update2')
85
85
  end
86
86
 
87
+ template.thumbnail title: 'dialogs/open (update form inside dialog)', onClick: ->(action) do
88
+ action.dialogs_open url: json_ui_garage_url(path: 'forms/dialogs_form')
89
+ end
90
+
87
91
  template.thumbnail title: 'dialogs/open (with filePaster)', onClick: ->(action) do
88
92
  action.dialogs_open url: json_ui_garage_url(path: 'forms/dialogs_update3')
89
93
  end
90
94
 
95
+ template.thumbnail title: 'dialogs/open (update form inside dialog)', onClick: ->(action) do
96
+ action.dialogs_open url: json_ui_garage_url(path: 'forms/dialogs_form')
97
+ end
98
+
91
99
  template.thumbnail title: 'dialogs/oauth', onClick: ->(action) do
92
100
  if respond_to?(:user_facebook_omniauth_authorize_url)
93
101
  provider = {
@@ -0,0 +1,10 @@
1
+
2
+ section.header padding: glib_json_padding_list, childViews: ->(header) do
3
+ header.h3 text: 'Fields'
4
+ end
5
+
6
+ section.rows builder: ->(template) do
7
+ template.thumbnail title: 'fields/focus, fields/blur, fields/reset', onClick: ->(action) do
8
+ action.windows_open url: json_ui_garage_url(path: 'views/fields_focus')
9
+ end
10
+ end
@@ -19,5 +19,11 @@ panel.panels_list id: 'action_list', sections: [
19
19
  render "#{@path_prefix}/actions/commands", section: section
20
20
  end, ->(section) do
21
21
  render "#{@path_prefix}/actions/tours", section: section
22
+ end, ->(section) do
23
+ render "#{@path_prefix}/actions/components", section: section
24
+ end, ->(section) do
25
+ render "#{@path_prefix}/actions/fields", section: section
26
+ end, ->(section) do
27
+ render "#{@path_prefix}/actions/cookies", section: section
22
28
  end
23
29
  ]
@@ -0,0 +1,40 @@
1
+ json.title 'Forms'
2
+
3
+ page = json_ui_page json
4
+ render "#{@path_prefix}/nav_menu", json: json, page: page
5
+
6
+ data = params[:user] || { cities: [] }
7
+
8
+ page.scroll childViews: ->(scroll) do
9
+ cities = {
10
+ 'Brisbane' => 'Brisbane',
11
+ 'Canberra' => 'Canberra',
12
+ 'Melbourne' => 'Melbourne',
13
+ 'Sydney' => 'Sydney',
14
+ }
15
+ scroll.panels_form \
16
+ url: json_ui_garage_url(path: 'forms/generic_post'),
17
+ method: 'post',
18
+ width: 'matchParent',
19
+ id: 'dialogs_form',
20
+ padding: glib_json_padding_body,
21
+ childViews: ->(form) do
22
+ form.fields_select \
23
+ name: 'user[cities][]',
24
+ width: 'matchParent',
25
+ label: 'Cities',
26
+ options: cities.map { |k, v| { value: k, text: v } },
27
+ value: data[:cities] + [params[:new_city]],
28
+ multiple: true,
29
+ accessory: ->(accessory) do
30
+ accessory.footer padding: { all: 20 }, childViews: ->(footer) do
31
+ footer.label text: 'Can\'t find a city? Enter a new one', onClick: ->(action) do
32
+ action.dialogs_open url: json_ui_garage_url(path: 'forms/dialogs_subform')
33
+ end
34
+ end
35
+ end
36
+
37
+ form.spacer height: 20
38
+ form.button text: 'Submit', onClick: ->(action) { action.forms_submit }
39
+ end
40
+ end
@@ -0,0 +1,21 @@
1
+ json.title 'Forms'
2
+
3
+ page = json_ui_page json
4
+ render "#{@path_prefix}/nav_menu", json: json, page: page
5
+
6
+ page.scroll childViews: ->(scroll) do
7
+ scroll.panels_form \
8
+ url: json_ui_garage_url(path: 'forms/dialogs_subform_post'),
9
+ method: 'post',
10
+ width: 'matchParent',
11
+ padding: glib_json_padding_body,
12
+ childViews: ->(form) do
13
+ form.fields_text \
14
+ name: 'user[city]',
15
+ width: 'matchParent',
16
+ label: 'City'
17
+
18
+ form.spacer height: 20
19
+ form.button text: 'Submit', onClick: ->(action) { action.forms_submit }
20
+ end
21
+ end
@@ -0,0 +1,13 @@
1
+ data = params[:user] || {}
2
+
3
+ json_ui_response json do |action|
4
+ action.dialogs_close onClose: ->(subaction) do
5
+ subaction.components_find targetId: 'dialogs_form', onFind: ->(subsubaction) do
6
+ # Use `override_path` to override the form's original form, which gets submitted in form data,
7
+ # so it needs to be explicitly overriden using a different param name.
8
+ subsubaction.forms_submit \
9
+ overrideUrl: json_ui_garage_url(override_path: 'forms/dialogs_form', new_city: data[:city]),
10
+ overrideMethod: :get
11
+ end
12
+ end
13
+ end
@@ -81,9 +81,82 @@ page.form \
81
81
  form.spacer height: 20
82
82
  form.h2 text: 'Country'
83
83
  form.spacer height: 6
84
- region_field = { name: 'user[city]', label: 'City' }
85
- form.fields_country name: 'user[country]', width: 'matchParent', label: 'Country', region: nil
86
- form.fields_country name: 'user[country_with_region]', width: 'matchParent', label: 'Country with region', region: region_field
84
+ # region_field = { name: 'user[city]', label: 'City' }
85
+ # form.fields_country name: 'user[country]', width: 'matchParent', label: 'Country', region: nil
86
+ # form.fields_country name: 'user[country_with_region]', width: 'matchParent', label: 'Country with region', region: region_field
87
+
88
+ countries = [
89
+ {
90
+ code: 'AU',
91
+ name: 'Australia',
92
+ regions: ['ACT', 'New South Wales', 'Victoria', 'Western Australia']
93
+ },
94
+ {
95
+ code: 'ID',
96
+ name: 'Indonesia',
97
+ regions: ['Jawa Barat', 'Java Tengah', 'Jawa Timur', 'Sumatra Utara', 'Sumatra Barat', 'Sumatra Selatan']
98
+ }
99
+ ]
100
+ region_registry = countries.map do |c|
101
+ [c[:code], c[:regions].map { |r| { value: r, text: r } } ]
102
+ end.to_h
103
+ form.fields_select \
104
+ name: 'user[country1]',
105
+ width: 'matchParent',
106
+ label: 'Country',
107
+ options: countries.map { |c| { value: c[:code], text: c[:name] } },
108
+ paramNameForFormData: 'variables',
109
+ onChange: ->(action) do
110
+ action.logics_set targetId: 'region_code1', conditionalData: {
111
+ options: {
112
+ '[]' => [{ 'var': 'static[region_registry]' }, { 'var': 'user[country1]' }]
113
+ }
114
+ }, variables: {
115
+ 'static[region_registry]' => region_registry
116
+ }
117
+ end
118
+
119
+ form.fields_select \
120
+ name: 'user[region1]',
121
+ width: 'matchParent',
122
+ label: 'Region',
123
+ id: 'region_code1',
124
+ options: []
125
+
126
+ form.spacer height: 20
127
+
128
+ selected_country = 'AU'
129
+ form.fields_select \
130
+ name: 'user[country2]',
131
+ width: 'matchParent',
132
+ label: 'Country',
133
+ options: countries.map { |c| { value: c[:code], text: c[:name] } },
134
+ paramNameForFormData: 'variables',
135
+ value: selected_country,
136
+ onChange: ->(action) do
137
+ action.logics_set targetId: 'region_code2', conditionalData: {
138
+ options: {
139
+ '??' => [
140
+ {
141
+ '[]' => [{ 'var': 'static[region_registry]' }, { 'var': 'user[country2]' }]
142
+ },
143
+ []
144
+ ]
145
+ },
146
+ value: nil
147
+ }, variables: {
148
+ 'static[region_registry]' => region_registry
149
+ }
150
+ end
151
+
152
+ form.fields_select \
153
+ name: 'user[region2]',
154
+ width: 'matchParent',
155
+ label: 'Region',
156
+ id: 'region_code2',
157
+ value: 'Victoria',
158
+ options: region_registry[selected_country]
159
+ form.label text: 'This select options should not be blank'
87
160
 
88
161
  form.spacer height: 20
89
162
  form.h2 text: 'Map'
@@ -70,8 +70,12 @@ page.form url: json_ui_garage_url(path: 'forms/generic_post'), method: 'post', p
70
70
  accessory.header padding: { x: 16, y: 10 }, childViews: ->(header) do
71
71
  header.label text: 'Header'
72
72
  end
73
- accessory.footer padding: { x: 16, y: 10 }, childViews: ->(footer) do
74
- footer.label text: 'Footer'
73
+ accessory.footer styleClass: 'select-footer', padding: { x: 16, y: 10 }, childViews: ->(footer) do
74
+ footer.h3 text: 'Footer'
75
+ # footer.spacer height: 4
76
+ footer.p styleClass: 'select-footer-paragraph', text: %(
77
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Tortor consequat id porta nibh venenatis cras sed. Amet consectetur adipiscing elit duis tristique sollicitudin nibh. Proin sagittis nisl rhoncus mattis rhoncus urna neque viverra justo. Velit egestas dui id ornare arcu odio. Pretium nibh ipsum consequat nisl vel pretium. Bibendum at varius vel pharetra. Leo duis ut diam quam nulla porttitor massa id. Consectetur libero id faucibus nisl tincidunt eget nullam non. Eu facilisis sed odio morbi quis. Eu volutpat odio facilisis mauris sit amet massa vitae tortor. Sed odio morbi quis commodo odio aenean sed. Sit amet justo donec enim diam. Ullamcorper a lacus vestibulum sed arcu non odio euismod.
78
+ )
75
79
  footer.spacer height: 14
76
80
  footer.label text: 'Click me', onClick: ->(action) do
77
81
  action.components_findClosest view: 'fields/select', onFind: ->(subaction) do
@@ -61,6 +61,32 @@ else
61
61
  # scroll.h1 text: 'Line chart using remote data'
62
62
  # render "#{@path_prefix}/views/chart_data", json: json, builder: scroll
63
63
 
64
+ scroll.h2 text: 'Line chart with custom tooltip'
65
+ scroll.charts_line \
66
+ plugins: { customTooltip: true },
67
+ colors: ['#79AC78', '#3085C3'], legend: { display: false },
68
+ dataSeries: [
69
+ -> do
70
+ json.title 'Line'
71
+
72
+ points = {
73
+ 'Jan' => 100,
74
+ 'Feb' => 78,
75
+ 'Mar' => 70,
76
+ 'Apr' => 62,
77
+ }
78
+ prev = points['Jan']
79
+
80
+
81
+ json.points points.map { |k, v|
82
+ delta = prev - v
83
+ tooltip = v < prev ? "<div>Delta</div><div>▼ #{delta}</div>" : "<div>Delta</div><div>▲ #{delta}</div>"
84
+ prev = v
85
+ { x: k, y: v, tooltip: glib_chart_tooltip_template(title: "Summary #{k}", content: tooltip) }
86
+ }
87
+ end
88
+ ]
89
+
64
90
  scroll.h2 text: 'Column chart (Clustered)'
65
91
  scroll.charts_column dataGroups: [
66
92
  -> do
@@ -0,0 +1,37 @@
1
+ json.title 'Component set'
2
+
3
+ page = json_ui_page json
4
+
5
+ render "#{@path_prefix}/nav_menu", json: json, page: page, top_nav: true
6
+
7
+ page.body padding: glib_json_padding_body, childViews: ->(body) do
8
+ body.panels_responsive width: 'matchParent', childViews: ->(res) do
9
+ res.label id: 'label', text: 'Hello world!'
10
+ res.spacer height: 8
11
+ res.button text: 'set', onClick: ->(action) do
12
+ action.components_set targetId: 'label', data: { text: 'Hello too!' }, onSet: ->(saction) do
13
+ saction.snackbars_alert styleClasses: ['success'], message: 'Changed!'
14
+ end
15
+ end
16
+ res.spacer height: 16
17
+
18
+ res.panels_form \
19
+ url: json_ui_garage_url(path: 'forms/generic_post'),
20
+ method: 'post',
21
+ childViews: ->(form) do
22
+ res.fields_text id: 'ftext', name: 'user[full_name]', value: 'John Doe', label: 'Full name', placeholder: 'Full name', width: 300
23
+ res.spacer height: 8
24
+ res.panels_horizontal childViews: ->(hori) do
25
+ res.button text: 'set', onClick: ->(action) do
26
+ action.components_set targetId: 'ftext', data: { name: 'user[city]', value: 'Taipei', label: 'City', placeholder: 'City' }
27
+ end
28
+ res.spacer width: 4
29
+ res.fields_submit text: 'submit'
30
+ end
31
+ end
32
+
33
+
34
+ res.spacer height: 16
35
+
36
+ end
37
+ end
@@ -0,0 +1,148 @@
1
+ json.title 'Component update'
2
+
3
+ page = json_ui_page json
4
+
5
+ render "#{@path_prefix}/nav_menu", json: json, page: page, top_nav: true
6
+
7
+ panels_ids = {
8
+ 'pres' => 'panels_responsive',
9
+ 'pcol' => 'panels_column',
10
+ 'phor' => 'panels_horizontal',
11
+ 'pver' => 'panels_vertical',
12
+ 'pflow' => 'panels_flow',
13
+ 'psplit' => 'panels_split',
14
+ }
15
+ other_ids = {
16
+ 'paragraph' => 'p',
17
+ 'label' => 'label'
18
+ }
19
+ comp_ids = panels_ids.merge(other_ids)
20
+ cities = [{ text: 'Bali', value: 'bali' }, { text: 'Jakarta', value: 'jakarta' }]
21
+
22
+ small_image_url = 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSGQpSWjtELISLBlmugOZ6wzl1JamYXQvbFeYywpfg3E8b8DrO0Kg&s'
23
+
24
+ page.body padding: glib_json_padding_body, childViews: ->(body) do
25
+ body.panels_responsive width: 'matchParent', childViews: ->(res) do
26
+ res.panels_column lg: { cols: 3 }, childViews: ->(col) do
27
+ res.h3 text: 'Props changes'
28
+ res.spacer height: 8
29
+ res.panels_flow innerPadding: { top: 4, right: 4, bottom: 4, left: 4 }, childViews: ->(hori) do
30
+ hori.button text: 'change bgcolor', onClick: ->(action) do
31
+ action.runMultiple childActions: ->(saction) do
32
+ comp_ids.each do |id, method|
33
+ saction.components_update targetId: id, views: ->(view) do
34
+ if id == 'pflow'
35
+ view.public_send(method, { backgroundColor: '#00FFFF', innerPadding: { bottom: 0 } })
36
+ else
37
+ view.public_send(method, { backgroundColor: '#00FFFF' })
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ hori.button text: 'change text (p & label)', onClick: ->(action) do
45
+ action.runMultiple childActions: ->(saction) do
46
+ saction.components_update targetId: 'paragraph', views: ->(view) do
47
+ view.p text: 'changed!'
48
+ end
49
+ saction.components_update targetId: 'label', views: ->(view) do
50
+ view.label text: 'changed!'
51
+ end
52
+ end
53
+ end
54
+
55
+ hori.button text: 'Change fields text', onClick: ->(action) do
56
+ action.components_update targetId: 'inp-text', views: ->(view) do
57
+ view.fields_text name: 'user[city]', value: 'Jakarta', placeholder: 'City', label: 'City'
58
+ end
59
+ end
60
+
61
+ hori.button text: 'Change fields select', onClick: ->(action) do
62
+ action.components_update targetId: 'inp-select', views: ->(view) do
63
+ view.fields_select options: cities + [{ text: 'Taipei', value: 'taipei' }]
64
+ end
65
+ end
66
+ end
67
+ res.spacer height: 16
68
+ res.h3 text: 'Childviews changes'
69
+ res.spacer height: 8
70
+ res.panels_flow innerPadding: { top: 4, right: 4, bottom: 4, left: 4 }, childViews: ->(hori) do
71
+ hori.button text: 'Add child to panel', onClick: ->(action) do
72
+ action.runMultiple childActions: ->(saction) do
73
+ panels_ids.each do |id, method|
74
+ saction.components_update targetId: id, views: ->(view) do
75
+ props = {
76
+ childViews: ->(sview) do
77
+ sview.label text: method
78
+ sview.image url: small_image_url, width: 'matchParent', height: 'matchParent'
79
+ end
80
+ }
81
+ props.merge!({ innerPadding: { bottom: 0 } }) if id == 'pflow'
82
+ if id == 'psplit'
83
+ props.delete(:childViews)
84
+ props.merge({
85
+ content: ->(split) do
86
+ split.left childViews: ->(sview) do
87
+ sview.label text: method
88
+ end
89
+ split.right childViews: ->(sview) do
90
+ sview.image url: small_image_url, width: 'matchParent', height: 'matchParent'
91
+ end
92
+ end
93
+ })
94
+ end
95
+ view.public_send(method, props)
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
101
+ res.spacer height: 16
102
+ end
103
+
104
+ res.panels_column lg: { cols: 9 }, childViews: ->(col) do
105
+ col.panels_responsive id: 'pres', width: 200, childViews: ->(cview) do
106
+ cview.label text: 'Panels responsive'
107
+ end
108
+ col.spacer height: 4
109
+ col.panels_column id: 'pcol', lg: { cols: 6 }, childViews: ->(cview) do
110
+ cview.label text: 'Panels column'
111
+ end
112
+ col.spacer height: 4
113
+ col.panels_horizontal id: 'phor', width: 200, childViews: ->(cview) do
114
+ cview.label text: 'Panels horizontal'
115
+ end
116
+ col.spacer height: 4
117
+ col.panels_vertical id: 'pver', width: 200, childViews: ->(cview) do
118
+ cview.label text: 'Panels vertical'
119
+ end
120
+ col.spacer height: 4
121
+ col.panels_flow innerPadding: { bottom: 0 }, id: 'pflow', width: 200, childViews: ->(cview) do
122
+ cview.label text: 'Panels flow'
123
+ end
124
+ col.spacer height: 4
125
+ col.panels_split id: 'psplit', width: 200, content: ->(cview) do
126
+ cview.left childViews: ->(ccview) do
127
+ ccview.label text: 'Panels split (not supported)'
128
+ end
129
+ end
130
+ col.spacer height: 4
131
+ col.p id: 'paragraph', width: 500, text: 'In publishing and graphic design, Lorem ipsum is a placeholder text commonly used to demonstrate the visual form of a document or a typeface without relying on meaningful content.'
132
+ col.spacer height: 4
133
+ col.label id: 'label', text: 'birds flying'
134
+ col.spacer height: 8
135
+ col.panels_form \
136
+ url: json_ui_garage_url(path: 'forms/generic_post'),
137
+ method: 'post',
138
+ childViews: ->(form) do
139
+ col.fields_text id: 'inp-text', name: 'user[full_name]', width: 300, label: 'Full name', placeholder: 'Full name'
140
+ col.spacer height: 4
141
+
142
+ col.fields_select id: 'inp-select', options: cities, width: 300, name: 'user[city]'
143
+ col.spacer height: 4
144
+ col.fields_submit text: 'Submit'
145
+ end
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,47 @@
1
+ json.title 'Field focus'
2
+
3
+ page = json_ui_page json
4
+
5
+ render "#{@path_prefix}/nav_menu", json: json, page: page, top_nav: true
6
+
7
+ page.body padding: glib_json_padding_body, childViews: ->(body) do
8
+ body.panels_responsive width: 'matchParent', childViews: ->(res) do
9
+ res.panels_form \
10
+ url: json_ui_garage_url(path: 'forms/generic_post'),
11
+ method: 'post',
12
+ width: 300,
13
+ childViews: ->(form) do
14
+ res.fields_text id: 'first', name: 'user[full_name]', label: 'Full name', placeholder: 'Full name', width: 'matchParent'
15
+ res.spacer height: 8
16
+ res.fields_number id: 'second', name: 'user[age]', label: 'Age', placeholder: 'Age', width: 'matchParent'
17
+ res.spacer height: 4
18
+ res.panels_horizontal childViews: ->(hori) do
19
+ res.button text: 'focus1', onClick: ->(action) do
20
+ action.fields_focus targetId: 'first'
21
+ end
22
+ res.spacer width: 4
23
+ res.button text: 'focus2', onClick: ->(action) do
24
+ action.fields_focus targetId: 'second'
25
+ end
26
+ res.spacer width: 4
27
+ res.button text: 'blur', onClick: ->(action) do
28
+ action.fields_focus targetId: 'first', onFocus: ->(saction) do
29
+ saction.timeouts_set interval: 1000, onTimeout: ->(ssaction) { ssaction.fields_blur }
30
+ end
31
+ end
32
+ res.spacer width: 4
33
+ res.button text: 'reset', onClick: ->(action) do
34
+ action.fields_reset targetId: 'first', onReset: ->(saction) do
35
+ saction.snackbars_alert styleClasses: ['success'], message: 'Reset full name!'
36
+ end
37
+ end
38
+ res.spacer width: 4
39
+ res.fields_submit text: 'submit'
40
+ end
41
+ end
42
+
43
+
44
+ res.spacer height: 16
45
+
46
+ end
47
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: glib-web
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.24.3
4
+ version: 3.25.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ''
@@ -139,8 +139,11 @@ files:
139
139
  - app/validators/url_validator.rb
140
140
  - app/views/json_ui/garage/_nav_menu.json.jbuilder
141
141
  - app/views/json_ui/garage/actions/_commands.json.jbuilder
142
+ - app/views/json_ui/garage/actions/_components.json.jbuilder
143
+ - app/views/json_ui/garage/actions/_cookies.json.jbuilder
142
144
  - app/views/json_ui/garage/actions/_dialogs.json.jbuilder
143
145
  - app/views/json_ui/garage/actions/_dialogs_show.json.jbuilder
146
+ - app/views/json_ui/garage/actions/_fields.json.jbuilder
144
147
  - app/views/json_ui/garage/actions/_http.json.jbuilder
145
148
  - app/views/json_ui/garage/actions/_list.json.jbuilder
146
149
  - app/views/json_ui/garage/actions/_panels.json.jbuilder
@@ -164,6 +167,9 @@ files:
164
167
  - app/views/json_ui/garage/forms/chip_group.json.jbuilder
165
168
  - app/views/json_ui/garage/forms/conditional_value.json.jbuilder
166
169
  - app/views/json_ui/garage/forms/dialogs_close.json.jbuilder
170
+ - app/views/json_ui/garage/forms/dialogs_form.json.jbuilder
171
+ - app/views/json_ui/garage/forms/dialogs_subform.json.jbuilder
172
+ - app/views/json_ui/garage/forms/dialogs_subform_post.json.jbuilder
167
173
  - app/views/json_ui/garage/forms/dialogs_update.json.jbuilder
168
174
  - app/views/json_ui/garage/forms/dialogs_update2.json.jbuilder
169
175
  - app/views/json_ui/garage/forms/dialogs_update3.json.jbuilder
@@ -264,7 +270,10 @@ files:
264
270
  - app/views/json_ui/garage/views/banners.json.jbuilder
265
271
  - app/views/json_ui/garage/views/calendar_data.json.jbuilder
266
272
  - app/views/json_ui/garage/views/charts.json.jbuilder
273
+ - app/views/json_ui/garage/views/components_set.json.jbuilder
274
+ - app/views/json_ui/garage/views/components_update.json.jbuilder
267
275
  - app/views/json_ui/garage/views/controls.json.jbuilder
276
+ - app/views/json_ui/garage/views/fields_focus.json.jbuilder
268
277
  - app/views/json_ui/garage/views/iap.json.jbuilder
269
278
  - app/views/json_ui/garage/views/icon_names.json.jbuilder
270
279
  - app/views/json_ui/garage/views/icons.json.jbuilder