gloo 4.2.1 → 4.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1776f8bb92860bc0338c79c0ce77a2a9eb06e22a68bf2007812c173280b109f6
4
- data.tar.gz: 1beb107590b4f91bf964953c3808179ac3e0b1e2e35012ff02d7b5e0cb96a4d6
3
+ metadata.gz: 8433bf6ce21086f0a4ade5d45ef2c4bca77aa0d43edf087304a84b08d91ca49a
4
+ data.tar.gz: 0a9bb39b56d34eb411b617cd8260aaf42afc8574aa7535dc61eedef21d6fc593
5
5
  SHA512:
6
- metadata.gz: 69d271ac18569be4d22bacabcdb6b5233c47c3be8db86057ed0833d0a09b028e45eca167b7e2b74a8a427ff07b1e2cb156926e3374228a05324668bd9a9c6b51
7
- data.tar.gz: 113a69b5a18f303a67c363c2ddce2b22d325802e78db5e7490e5d3bf2a9f025caeba1c68cda163f0f195ae4e90fd145902256718fa1d5678704b725bf80e613e
6
+ metadata.gz: 80bf8f11fe5329c2475fe95839f995f6d6726f7c9798701a98d0ba80fe1bcfc3f0004c5c9fd34f931d65c8587542abdbdaba3e1bc5f0e554a91b44788690ef0f
7
+ data.tar.gz: 5fdecb6bfcfdf629db8f48cd7a8a8b41727d7461984d2131c697ba39e7e68113c87e5034b4ca165d67a7cb1a1ce1e693563eed0f4c2ff60c82b78c1ac05c511d
data/gloo.gemspec CHANGED
@@ -46,7 +46,7 @@ Gem::Specification.new do |spec|
46
46
  spec.add_dependency 'mysql2', '~> 0.5', '>= 0.5.3'
47
47
  spec.add_dependency 'sqlite3', '~> 1.4', '>= 1.4.2'
48
48
  spec.add_dependency 'os', '~> 1.1', '>= 1.1.4'
49
- spec.add_dependency 'pg', '~> 1.5.4'
49
+ # spec.add_dependency 'pg', '~> 1.5.4'
50
50
  spec.add_dependency 'thin', '~> 1.8.2'
51
51
  spec.add_dependency 'redcarpet', '~> 3.6.0'
52
52
  spec.add_dependency 'bcrypt', '~> 3.1.20'
data/lib/VERSION CHANGED
@@ -1 +1 @@
1
- 4.2.1
1
+ 4.4.0
data/lib/VERSION_NOTES CHANGED
@@ -1,3 +1,12 @@
1
+ 4.4.0 - 2025.07.30
2
+ - Adds form and fields
3
+ - Adds option to include image_tag and other asset tags in helper rendering.
4
+
5
+
6
+ 4.3.0 - 2025.07.02
7
+ - Removes postgres dependency (for now)
8
+
9
+
1
10
  4.2.1 - 2025.05.15
2
11
  - Fixes bug with begin and end month date messages
3
12
 
@@ -71,6 +71,22 @@ module Gloo
71
71
  return return_any ? return_any.value : nil
72
72
  end
73
73
 
74
+ #
75
+ # Get the params hash from the child object.
76
+ # Returns nil if there is none.
77
+ #
78
+ def params_hash
79
+ params_can = find_child PARAMS
80
+ return nil unless params_can
81
+
82
+ h = {}
83
+ params_can.children.each do |o|
84
+ h[ o.name ] = o.value
85
+ end
86
+
87
+ return h
88
+ end
89
+
74
90
 
75
91
  # ---------------------------------------------------------------------
76
92
  # Children
@@ -156,7 +172,12 @@ module Gloo
156
172
 
157
173
  set_params args if args
158
174
  run_on_invoke
159
- return_value = result
175
+
176
+ if @engine.running_app&.obj&.embedded_renderer
177
+ return_value = @engine.running_app.obj.embedded_renderer.render result, params_hash
178
+ else
179
+ return_value = result
180
+ end
160
181
  @engine.heap.it.set_to return_value
161
182
  run_after_invoke
162
183
 
@@ -1,216 +1,216 @@
1
- # Author:: Eric Crane (mailto:eric.crane@mac.com)
2
- # Copyright:: Copyright (c) 2023 Eric Crane. All rights reserved.
3
- #
4
- # A Postgres database connection.
5
- #
6
- # https://rubygems.org/gems/pg/versions/0.18.4
7
- # https://github.com/ged/ruby-pg
8
- #
9
- require 'pg'
10
-
11
- module Gloo
12
- module Objs
13
- class Pg < Gloo::Core::Obj
14
-
15
- KEYWORD = 'postgres'.freeze
16
- KEYWORD_SHORT = 'pg'.freeze
17
-
18
- HOST = 'host'.freeze
19
- DB = 'database'.freeze
20
- USER = 'username'.freeze
21
- PASSWD = 'password'.freeze
22
-
23
- #
24
- # The name of the object type.
25
- #
26
- def self.typename
27
- return KEYWORD
28
- end
29
-
30
- #
31
- # The short name of the object type.
32
- #
33
- def self.short_typename
34
- return KEYWORD_SHORT
35
- end
36
-
37
- # ---------------------------------------------------------------------
38
- # Children
39
- # ---------------------------------------------------------------------
40
-
41
- #
42
- # Does this object have children to add when an object
43
- # is created in interactive mode?
44
- # This does not apply during obj load, etc.
45
- #
46
- def add_children_on_create?
47
- return true
48
- end
49
-
50
- #
51
- # Add children to this object.
52
- # This is used by containers to add children needed
53
- # for default configurations.
54
- #
55
- def add_default_children
56
- fac = @engine.factory
57
- fac.create_string HOST, nil, self
58
- fac.create_string DB, nil, self
59
- fac.create_string USER, nil, self
60
- fac.create_string PASSWD, nil, self
61
- end
62
-
63
- # ---------------------------------------------------------------------
64
- # Messages
65
- # ---------------------------------------------------------------------
66
-
67
- #
68
- # Get a list of message names that this object receives.
69
- #
70
- def self.messages
71
- return super + [ 'verify' ]
72
- end
73
-
74
- #
75
- # SSH to the host and execute the command, then update result.
76
- #
77
- def msg_verify
78
- return unless connects?
79
-
80
- @engine.heap.it.set_to true
81
- end
82
-
83
- # ---------------------------------------------------------------------
84
- # DB functions (all database connections)
85
- # ---------------------------------------------------------------------
86
-
87
- #
88
- # Open a connection and execute the SQL statement.
89
- # Return the resulting data.
90
- #
91
- def query( sql, params = nil )
92
- heads = []
93
- data = []
94
- client = pg_conn
95
-
96
- if params
97
- param_arr = []
98
- params.each do |p|
99
- param_arr << { :value => p, :type => 0, :format => 0 }
100
- end
101
- rs = client.exec_params( sql, params )
102
- else
103
- rs = client.exec( sql )
104
- end
105
-
106
- if rs && ( rs.count > 0 )
107
- rs[0].each do |name, val|
108
- heads << name
109
- end
110
- rs.each_with_index do |row, index|
111
- arr = []
112
- row.each do |name, val|
113
- arr << val
114
- end
115
- data << arr
116
- end
117
- end
118
-
119
- return [ heads, data ]
120
- end
121
-
122
- #
123
- # Based on the result set, build a QueryResult object.
124
- #
125
- def get_query_result( result )
126
- return QueryResult.new result[0], result[1], @engine
127
- end
128
-
129
-
130
- # ---------------------------------------------------------------------
131
- # Private functions
132
- # ---------------------------------------------------------------------
133
-
134
- private
135
-
136
- #
137
- # Get the host from the child object.
138
- # Returns nil if there is none.
139
- #
140
- def host_value
141
- o = find_child HOST
142
- return nil unless o
143
-
144
- o = Gloo::Objs::Alias.resolve_alias( @engine, o )
145
- return o.value
146
- end
147
-
148
- #
149
- # Get the Database name from the child object.
150
- # Returns nil if there is none.
151
- #
152
- def db_value
153
- o = find_child DB
154
- return nil unless o
155
-
156
- o = Gloo::Objs::Alias.resolve_alias( @engine, o )
157
- return o.value
158
- end
159
-
160
- #
161
- # Get the Username from the child object.
162
- # Returns nil if there is none.
163
- #
164
- def user_value
165
- o = find_child USER
166
- return nil unless o
167
-
168
- o = Gloo::Objs::Alias.resolve_alias( @engine, o )
169
- return o.value
170
- end
171
-
172
- #
173
- # Get the Password name from the child object.
174
- # Returns nil if there is none.
175
- #
176
- def passwd_value
177
- o = find_child PASSWD
178
- return nil unless o
179
-
180
- o = Gloo::Objs::Alias.resolve_alias( @engine, o )
181
- return o.value
182
- end
183
-
184
- #
185
- # Try the connection and make sure it works.
186
- # Returns true if we can establish a connection.
187
- #
188
- def connects?
189
- begin
190
- result = pg_conn.exec( "SELECT NOW()" )
191
- rescue => e
192
- @engine.log_exception e
193
- @engine.heap.it.set_to false
194
- return false
195
- end
196
- return true
197
- end
198
-
199
- #
200
- # Get the PG connection.
201
- #
202
- def pg_conn
203
- if host_value
204
- conn = PG.connect(
205
- host_value, 5432, '', '',
206
- db_value,
207
- user_value,
208
- passwd_value )
209
- else
210
- conn = PG.connect( dbname: db_value )
211
- end
212
- end
213
-
214
- end
215
- end
216
- end
1
+ # # Author:: Eric Crane (mailto:eric.crane@mac.com)
2
+ # # Copyright:: Copyright (c) 2023 Eric Crane. All rights reserved.
3
+ # #
4
+ # # A Postgres database connection.
5
+ # #
6
+ # # https://rubygems.org/gems/pg/versions/0.18.4
7
+ # # https://github.com/ged/ruby-pg
8
+ # #
9
+ # require 'pg'
10
+
11
+ # module Gloo
12
+ # module Objs
13
+ # class Pg < Gloo::Core::Obj
14
+
15
+ # KEYWORD = 'postgres'.freeze
16
+ # KEYWORD_SHORT = 'pg'.freeze
17
+
18
+ # HOST = 'host'.freeze
19
+ # DB = 'database'.freeze
20
+ # USER = 'username'.freeze
21
+ # PASSWD = 'password'.freeze
22
+
23
+ # #
24
+ # # The name of the object type.
25
+ # #
26
+ # def self.typename
27
+ # return KEYWORD
28
+ # end
29
+
30
+ # #
31
+ # # The short name of the object type.
32
+ # #
33
+ # def self.short_typename
34
+ # return KEYWORD_SHORT
35
+ # end
36
+
37
+ # # ---------------------------------------------------------------------
38
+ # # Children
39
+ # # ---------------------------------------------------------------------
40
+
41
+ # #
42
+ # # Does this object have children to add when an object
43
+ # # is created in interactive mode?
44
+ # # This does not apply during obj load, etc.
45
+ # #
46
+ # def add_children_on_create?
47
+ # return true
48
+ # end
49
+
50
+ # #
51
+ # # Add children to this object.
52
+ # # This is used by containers to add children needed
53
+ # # for default configurations.
54
+ # #
55
+ # def add_default_children
56
+ # fac = @engine.factory
57
+ # fac.create_string HOST, nil, self
58
+ # fac.create_string DB, nil, self
59
+ # fac.create_string USER, nil, self
60
+ # fac.create_string PASSWD, nil, self
61
+ # end
62
+
63
+ # # ---------------------------------------------------------------------
64
+ # # Messages
65
+ # # ---------------------------------------------------------------------
66
+
67
+ # #
68
+ # # Get a list of message names that this object receives.
69
+ # #
70
+ # def self.messages
71
+ # return super + [ 'verify' ]
72
+ # end
73
+
74
+ # #
75
+ # # SSH to the host and execute the command, then update result.
76
+ # #
77
+ # def msg_verify
78
+ # return unless connects?
79
+
80
+ # @engine.heap.it.set_to true
81
+ # end
82
+
83
+ # # ---------------------------------------------------------------------
84
+ # # DB functions (all database connections)
85
+ # # ---------------------------------------------------------------------
86
+
87
+ # #
88
+ # # Open a connection and execute the SQL statement.
89
+ # # Return the resulting data.
90
+ # #
91
+ # def query( sql, params = nil )
92
+ # heads = []
93
+ # data = []
94
+ # client = pg_conn
95
+
96
+ # if params
97
+ # param_arr = []
98
+ # params.each do |p|
99
+ # param_arr << { :value => p, :type => 0, :format => 0 }
100
+ # end
101
+ # rs = client.exec_params( sql, params )
102
+ # else
103
+ # rs = client.exec( sql )
104
+ # end
105
+
106
+ # if rs && ( rs.count > 0 )
107
+ # rs[0].each do |name, val|
108
+ # heads << name
109
+ # end
110
+ # rs.each_with_index do |row, index|
111
+ # arr = []
112
+ # row.each do |name, val|
113
+ # arr << val
114
+ # end
115
+ # data << arr
116
+ # end
117
+ # end
118
+
119
+ # return [ heads, data ]
120
+ # end
121
+
122
+ # #
123
+ # # Based on the result set, build a QueryResult object.
124
+ # #
125
+ # def get_query_result( result )
126
+ # return QueryResult.new result[0], result[1], @engine
127
+ # end
128
+
129
+
130
+ # # ---------------------------------------------------------------------
131
+ # # Private functions
132
+ # # ---------------------------------------------------------------------
133
+
134
+ # private
135
+
136
+ # #
137
+ # # Get the host from the child object.
138
+ # # Returns nil if there is none.
139
+ # #
140
+ # def host_value
141
+ # o = find_child HOST
142
+ # return nil unless o
143
+
144
+ # o = Gloo::Objs::Alias.resolve_alias( @engine, o )
145
+ # return o.value
146
+ # end
147
+
148
+ # #
149
+ # # Get the Database name from the child object.
150
+ # # Returns nil if there is none.
151
+ # #
152
+ # def db_value
153
+ # o = find_child DB
154
+ # return nil unless o
155
+
156
+ # o = Gloo::Objs::Alias.resolve_alias( @engine, o )
157
+ # return o.value
158
+ # end
159
+
160
+ # #
161
+ # # Get the Username from the child object.
162
+ # # Returns nil if there is none.
163
+ # #
164
+ # def user_value
165
+ # o = find_child USER
166
+ # return nil unless o
167
+
168
+ # o = Gloo::Objs::Alias.resolve_alias( @engine, o )
169
+ # return o.value
170
+ # end
171
+
172
+ # #
173
+ # # Get the Password name from the child object.
174
+ # # Returns nil if there is none.
175
+ # #
176
+ # def passwd_value
177
+ # o = find_child PASSWD
178
+ # return nil unless o
179
+
180
+ # o = Gloo::Objs::Alias.resolve_alias( @engine, o )
181
+ # return o.value
182
+ # end
183
+
184
+ # #
185
+ # # Try the connection and make sure it works.
186
+ # # Returns true if we can establish a connection.
187
+ # #
188
+ # def connects?
189
+ # begin
190
+ # result = pg_conn.exec( "SELECT NOW()" )
191
+ # rescue => e
192
+ # @engine.log_exception e
193
+ # @engine.heap.it.set_to false
194
+ # return false
195
+ # end
196
+ # return true
197
+ # end
198
+
199
+ # #
200
+ # # Get the PG connection.
201
+ # #
202
+ # def pg_conn
203
+ # if host_value
204
+ # conn = PG.connect(
205
+ # host_value, 5432, '', '',
206
+ # db_value,
207
+ # user_value,
208
+ # passwd_value )
209
+ # else
210
+ # conn = PG.connect( dbname: db_value )
211
+ # end
212
+ # end
213
+
214
+ # end
215
+ # end
216
+ # end
@@ -226,6 +226,8 @@ module Gloo
226
226
  e = Gloo::Objs::Alias.resolve_alias( engine, e )
227
227
  if e.class == Element
228
228
  rendered_obj_content << e.send( render_ƒ )
229
+ elsif e.class == Form
230
+ rendered_obj_content << e.render
229
231
  elsif e
230
232
  data = render_thing e, render_ƒ, engine
231
233
  ( rendered_obj_content << data ) if data # e.render( render_ƒ )
@@ -0,0 +1,429 @@
1
+ # Author:: Eric Crane (mailto:eric.crane@mac.com)
2
+ # Copyright:: Copyright (c) 2025 Eric Crane. All rights reserved.
3
+ #
4
+ # An HTML Form Field.
5
+ #
6
+ # A Form Field is the definition of a form field, including label, type, etc.
7
+ #
8
+
9
+ module Gloo
10
+ module Objs
11
+ class Field < Gloo::Core::Obj
12
+
13
+ KEYWORD = 'field'.freeze
14
+ KEYWORD_SHORT = 'field'.freeze
15
+
16
+ # Form
17
+ NAME = 'name'.freeze
18
+ ID = 'id'.freeze
19
+ TYPE = 'type'.freeze
20
+ VALUE = 'value'.freeze
21
+ LABEL = 'label'.freeze
22
+ PLACEHOLDER = 'placeholder'.freeze
23
+ AUTOFOCUS = 'autofocus'.freeze
24
+ COLS = 'cols'.freeze
25
+ ROWS = 'rows'.freeze
26
+ DESCRIPTION = 'description'.freeze
27
+ CHECKED = 'checked'.freeze
28
+ OPTIONS = 'options'.freeze
29
+
30
+ # Style attributes
31
+ FIELD_GROUP = 'field_group'.freeze
32
+ FIELD_LABEL = 'field_label'.freeze
33
+ FIELD_CONTROL = 'field_control'.freeze
34
+
35
+ #
36
+ # The name of the object type.
37
+ #
38
+ def self.typename
39
+ return KEYWORD
40
+ end
41
+
42
+ #
43
+ # The short name of the object type.
44
+ #
45
+ def self.short_typename
46
+ return KEYWORD_SHORT
47
+ end
48
+
49
+ #
50
+ # Get the name for the form field.
51
+ #
52
+ def name_value
53
+ o = find_child NAME
54
+
55
+ # If there is no child, use the obj's name
56
+ return self.name unless o
57
+
58
+ o = Gloo::Objs::Alias.resolve_alias( @engine, o )
59
+ return o ? o.value : nil
60
+ end
61
+
62
+ #
63
+ # Get the type for the form field.
64
+ # For example, 'text', 'password', 'checkbox', etc.
65
+ #
66
+ def type_value
67
+ o = find_child TYPE
68
+ o = Gloo::Objs::Alias.resolve_alias( @engine, o )
69
+ return o ? o.value : nil
70
+ end
71
+
72
+ #
73
+ # Get the value for the form field.
74
+ #
75
+ def field_value
76
+ o = find_child VALUE
77
+ o = Gloo::Objs::Alias.resolve_alias( @engine, o )
78
+ return o ? o.value : nil
79
+ end
80
+
81
+ #
82
+ # Get the value tag for the form field.
83
+ #
84
+ def value_tag
85
+ value = field_value
86
+ return "value='#{value}'" if value
87
+ return ''
88
+ end
89
+
90
+ #
91
+ # Get the label for the form field.
92
+ #
93
+ def label_value
94
+ o = find_child LABEL
95
+
96
+ # If there is no child, use the obj's name
97
+ return self.name_value.capitalize unless o
98
+
99
+ o = Gloo::Objs::Alias.resolve_alias( @engine, o )
100
+ return o ? o.value : nil
101
+ end
102
+
103
+ #
104
+ # Get the label tag for the form field.
105
+ #
106
+ def label_tag
107
+ label = label_value
108
+ label_data = ''
109
+ if label
110
+ label_data = <<~HTML
111
+ <label class="#{field_label_styles}" for="#{name_value}">
112
+ #{label}
113
+ </label>
114
+ HTML
115
+ end
116
+ return label_data
117
+ end
118
+
119
+ #
120
+ # Get the placeholder for the form field.
121
+ #
122
+ def placeholder_value
123
+ o = find_child PLACEHOLDER
124
+ o = Gloo::Objs::Alias.resolve_alias( @engine, o )
125
+ return o ? o.value : nil
126
+ end
127
+
128
+ #
129
+ # Get the placeholder tag for the form field.
130
+ #
131
+ def placeholder_tag
132
+ placeholder = placeholder_value
133
+ return "placeholder='#{placeholder}'" if placeholder
134
+ return ''
135
+ end
136
+
137
+ #
138
+ # Should this field autofocus?
139
+ #
140
+ def autofocus?
141
+ o = find_child AUTOFOCUS
142
+ o = Gloo::Objs::Alias.resolve_alias( @engine, o )
143
+ return nil unless o
144
+ return o.value
145
+ end
146
+
147
+ #
148
+ # Get the autofocus tag for the form field.
149
+ #
150
+ def autofocus_tag
151
+ return "autofocus='autofocus'" if autofocus?
152
+ return ''
153
+ end
154
+
155
+ #
156
+ # Get the cols for the form field.
157
+ #
158
+ def cols_value
159
+ o = find_child COLS
160
+ o = Gloo::Objs::Alias.resolve_alias( @engine, o )
161
+ return o ? o.value : nil
162
+ end
163
+
164
+ #
165
+ # Get the cols tag for the form field.
166
+ #
167
+ def cols_tag
168
+ cols = cols_value
169
+ return "col-#{cols}" if cols
170
+ return ''
171
+ end
172
+
173
+ #
174
+ # Get the rows for the form field.
175
+ # Only applies to textarea fields.
176
+ #
177
+ def rows_value
178
+ o = find_child ROWS
179
+ o = Gloo::Objs::Alias.resolve_alias( @engine, o )
180
+ return o ? o.value : nil
181
+ end
182
+
183
+ #
184
+ # Get the rows tag for the form field.
185
+ # Only applies to textarea fields.
186
+ #
187
+ def rows_tag
188
+ rows = rows_value
189
+ return "rows='#{rows}'" if rows
190
+ return ''
191
+ end
192
+
193
+ #
194
+ # Get the description for the form field.
195
+ #
196
+ def description_value
197
+ o = find_child DESCRIPTION
198
+ o = Gloo::Objs::Alias.resolve_alias( @engine, o )
199
+ return o ? o.value : nil
200
+ end
201
+
202
+ #
203
+ # Should this field be checked?
204
+ #
205
+ def checked?
206
+ o = find_child CHECKED
207
+ o = Gloo::Objs::Alias.resolve_alias( @engine, o )
208
+ return nil unless o
209
+ return o.value
210
+ end
211
+
212
+ #
213
+ # Get the checked tag for the form field.
214
+ #
215
+ def checked_tag
216
+ return "checked='checked'" if checked?
217
+ return ''
218
+ end
219
+
220
+ #
221
+ # Get options for the select list.
222
+ #
223
+ def select_options
224
+ o = find_child OPTIONS
225
+ o = Gloo::Objs::Alias.resolve_alias( @engine, o )
226
+ return nil unless o
227
+
228
+ selected_value = field_value
229
+
230
+ options = ''
231
+ o.children.each do |child|
232
+ if selected_value == child.name || selected_value == child.value
233
+ selected = 'selected="selected"'
234
+ else
235
+ selected = ''
236
+ end
237
+ options += <<~HTML
238
+ <option value="#{child.name}" #{selected}>#{child.value}</option>
239
+ HTML
240
+ end
241
+ return options
242
+ end
243
+
244
+ #
245
+ # Get the field group styles.
246
+ #
247
+ def field_group_styles
248
+ o = find_child FIELD_GROUP
249
+ if o
250
+ o = Gloo::Objs::Alias.resolve_alias( @engine, o )
251
+ return o ? o.value : ''
252
+ end
253
+
254
+ return @styles[FIELD_GROUP] || ''
255
+ end
256
+
257
+ #
258
+ # Get the field label styles.
259
+ #
260
+ def field_label_styles
261
+ o = find_child FIELD_LABEL
262
+ if o
263
+ o = Gloo::Objs::Alias.resolve_alias( @engine, o )
264
+ return o ? o.value : ''
265
+ end
266
+
267
+ return @styles[FIELD_LABEL] || ''
268
+ end
269
+
270
+ #
271
+ # Get the field control styles.
272
+ #
273
+ def field_control_styles
274
+ o = find_child FIELD_CONTROL
275
+ if o
276
+ o = Gloo::Objs::Alias.resolve_alias( @engine, o )
277
+ return o ? o.value : ''
278
+ end
279
+
280
+ return @styles[FIELD_CONTROL] || ''
281
+ end
282
+
283
+
284
+ # ---------------------------------------------------------------------
285
+ # Children
286
+ # ---------------------------------------------------------------------
287
+
288
+ #
289
+ # Does this object have children to add when an object
290
+ # is created in interactive mode?
291
+ # This does not apply during obj load, etc.
292
+ #
293
+ def add_children_on_create?
294
+ return true
295
+ end
296
+
297
+ #
298
+ # Add children to this object.
299
+ # This is used by containers to add children needed
300
+ # for default configurations.
301
+ #
302
+ def add_default_children
303
+ fac = @engine.factory
304
+
305
+ # Create attributes with ID and Classes
306
+ fac.create_string NAME, '', self
307
+ fac.create_string TYPE, 'text', self
308
+ end
309
+
310
+
311
+ # ---------------------------------------------------------------------
312
+ # Messages
313
+ # ---------------------------------------------------------------------
314
+
315
+ #
316
+ # Get a list of message names that this object receives.
317
+ #
318
+ def self.messages
319
+ return super + [ 'render' ]
320
+ end
321
+
322
+ #
323
+ # Render the form field.
324
+ #
325
+ def msg_render
326
+ content = self.render
327
+ @engine.heap.it.set_to content
328
+ return content
329
+ end
330
+
331
+
332
+ # ---------------------------------------------------------------------
333
+ # Render
334
+ # ---------------------------------------------------------------------
335
+
336
+ #
337
+ # Render the field, switch on type.
338
+ def render styles = {}
339
+ @styles = styles
340
+
341
+ case type_value
342
+ when 'text'
343
+ return render_text
344
+ when 'hidden'
345
+ return render_hidden
346
+ when 'textarea'
347
+ return render_textarea
348
+ when 'checkbox'
349
+ return render_checkbox
350
+ when 'search'
351
+ return render_text
352
+ when 'select'
353
+ return render_select
354
+ end
355
+ end
356
+
357
+ #
358
+ # Render the hidden field as HTML.
359
+ #
360
+ def render_hidden
361
+ return <<~HTML
362
+ <input type="hidden" #{value_tag} name="#{name_value}" id="#{name_value}" />
363
+ HTML
364
+ end
365
+
366
+ #
367
+ # Render the text field as HTML.
368
+ #
369
+ def render_text
370
+ return <<~HTML
371
+ <div class="#{field_group_styles} #{cols_tag}">
372
+ #{label_tag}
373
+ <input #{placeholder_tag} #{autofocus_tag} #{rows_tag}
374
+ class="#{field_control_styles}"
375
+ type="#{type_value}" #{value_tag}
376
+ name="#{name_value}" id="#{name_value}" />
377
+ </div>
378
+ HTML
379
+ end
380
+
381
+ #
382
+ # Render the textarea field as HTML.
383
+ #
384
+ def render_textarea
385
+ return <<~HTML
386
+ <div class="#{field_group_styles} #{cols_tag}">
387
+ #{label_tag}
388
+ <textarea #{placeholder_tag} #{autofocus_tag} #{rows_tag}
389
+ class="#{field_control_styles}"
390
+ name="#{name_value}" id="#{name_value}">#{field_value}</textarea>
391
+ </div>
392
+ HTML
393
+ end
394
+
395
+ #
396
+ # Render the checkbox field as HTML.
397
+ #
398
+ def render_checkbox
399
+ return <<~HTML
400
+ <div class="#{field_group_styles} #{cols_tag}">
401
+ #{label_tag}
402
+ <label class="checkbox #{field_control_styles}">
403
+ <input type="checkbox"
404
+ #{checked_tag} value="true"
405
+ name="#{name_value}" id="#{name_value}" />
406
+ #{description_value}
407
+ </label>
408
+ </div>
409
+ HTML
410
+ end
411
+
412
+ #
413
+ # Render the select field as HTML.
414
+ #
415
+ def render_select
416
+ return <<~HTML
417
+ <div class="#{field_group_styles} #{cols_tag}">
418
+ #{label_tag}
419
+ <select class="#{field_control_styles}"
420
+ name="#{name_value}" id="#{name_value}">
421
+ #{select_options}
422
+ </select>
423
+ </div>
424
+ HTML
425
+ end
426
+
427
+ end
428
+ end
429
+ end
@@ -0,0 +1,271 @@
1
+ # Author:: Eric Crane (mailto:eric.crane@mac.com)
2
+ # Copyright:: Copyright (c) 2025 Eric Crane. All rights reserved.
3
+ #
4
+ # An HTML Form.
5
+ #
6
+ # A Form is the definition of a form, with a collection of form fields
7
+ #
8
+
9
+ module Gloo
10
+ module Objs
11
+ class Form < Gloo::Core::Obj
12
+
13
+ KEYWORD = 'form'.freeze
14
+ KEYWORD_SHORT = 'form'.freeze
15
+
16
+ # Form
17
+ NAME = 'name'.freeze
18
+ ID = 'id'.freeze
19
+ METHOD = 'method'.freeze
20
+ METHOD_DEFAULT = 'post'.freeze
21
+ ACTION = 'action'.freeze
22
+ CANCEL_PATH = 'cancel_path'.freeze
23
+ CONTENT = 'content'.freeze
24
+ STYLES = 'styles'.freeze
25
+
26
+
27
+ #
28
+ # The name of the object type.
29
+ #
30
+ def self.typename
31
+ return KEYWORD
32
+ end
33
+
34
+ #
35
+ # The short name of the object type.
36
+ #
37
+ def self.short_typename
38
+ return KEYWORD_SHORT
39
+ end
40
+
41
+ #
42
+ # Get the name for the form.
43
+ #
44
+ def name_value
45
+ o = find_child NAME
46
+ o = Gloo::Objs::Alias.resolve_alias( @engine, o )
47
+ return o ? o.value : nil
48
+ end
49
+
50
+ #
51
+ # Get the method for the form.
52
+ # 'post' is the default.
53
+ #
54
+ def method_value
55
+ o = find_child METHOD
56
+ o = Gloo::Objs::Alias.resolve_alias( @engine, o )
57
+ return o.value || METHOD_DEFAULT
58
+ end
59
+
60
+ #
61
+ # Get the action for the form.
62
+ # This is the path to POST to, for example.
63
+ #
64
+ def action_value
65
+ o = find_child ACTION
66
+ o = Gloo::Objs::Alias.resolve_alias( @engine, o )
67
+ return o ? o.value : nil
68
+ end
69
+
70
+ #
71
+ # Get the cancel path for the form.
72
+ #
73
+ def cancel_path_value
74
+ o = find_child CANCEL_PATH
75
+ o = Gloo::Objs::Alias.resolve_alias( @engine, o )
76
+ return o ? o.value : nil
77
+ end
78
+
79
+ #
80
+ # Get all the form content, the collection of form fields.
81
+ #
82
+ def form_content
83
+ o = find_child CONTENT
84
+ o = Gloo::Objs::Alias.resolve_alias( @engine, o )
85
+ return o
86
+ end
87
+
88
+ #
89
+ # Get the styles for the form.
90
+ # Retuns styles in the form of a hash:
91
+ # { 'field_group' => 'form-group mt-3', … }
92
+ #
93
+ def styles
94
+ style_h = {}
95
+ o = find_child STYLES
96
+ return style_h unless o
97
+ o = Gloo::Objs::Alias.resolve_alias( @engine, o )
98
+
99
+ o.children.each do |c|
100
+ style_h[ c.name ] = c.value
101
+ end
102
+
103
+ # puts "styles: #{style_h}"
104
+ return style_h
105
+ end
106
+
107
+ #
108
+ # Get the form styles.
109
+ # Use the name if none is provided.
110
+ #
111
+ def form_styles
112
+ return @styles['form'] || name_value
113
+ end
114
+
115
+ #
116
+ # Get the submit button styles.
117
+ #
118
+ def submit_button_styles
119
+ return @styles['submit'] || ''
120
+ end
121
+
122
+ #
123
+ # Get the cancel button styles.
124
+ #
125
+ def cancel_button_styles
126
+ return @styles['cancel'] || ''
127
+ end
128
+
129
+
130
+ # ---------------------------------------------------------------------
131
+ # Children
132
+ # ---------------------------------------------------------------------
133
+
134
+ #
135
+ # Does this object have children to add when an object
136
+ # is created in interactive mode?
137
+ # This does not apply during obj load, etc.
138
+ #
139
+ def add_children_on_create?
140
+ return true
141
+ end
142
+
143
+ #
144
+ # Add children to this object.
145
+ # This is used by containers to add children needed
146
+ # for default configurations.
147
+ #
148
+ def add_default_children
149
+ fac = @engine.factory
150
+
151
+ # Create attributes with ID and Classes
152
+ fac.create_string NAME, '', self
153
+ fac.create_string METHOD, 'post', self
154
+ fac.create_string ACTION, '', self
155
+ fac.create_string CANCEL_PATH, '', self
156
+
157
+ fac.create_can CONTENT, self
158
+ end
159
+
160
+
161
+ # ---------------------------------------------------------------------
162
+ # Messages
163
+ # ---------------------------------------------------------------------
164
+
165
+ #
166
+ # Get a list of message names that this object receives.
167
+ #
168
+ def self.messages
169
+ return super + [ 'render' ]
170
+ end
171
+
172
+ #
173
+ # Render the form and all contained fields.
174
+ #
175
+ def msg_render
176
+ content = self.render
177
+ @engine.heap.it.set_to content
178
+ return content
179
+ end
180
+
181
+
182
+ # ---------------------------------------------------------------------
183
+ # Render
184
+ # ---------------------------------------------------------------------
185
+
186
+ #
187
+ # Open the form.
188
+ #
189
+ def open_form
190
+ name = name_value
191
+
192
+ cancel_button = ""
193
+ if cancel_path_value
194
+ cancel_button = <<~HTML
195
+ <a class="#{cancel_button_styles}"
196
+ href="#{cancel_path_value}">
197
+ Cancel</a>
198
+ HTML
199
+ end
200
+ return <<~HTML
201
+ <form class='#{form_styles}'
202
+ id='#{name}'
203
+ method='#{method_value}'
204
+ action='#{action_value}'
205
+ accept-charset='UTF-8'>
206
+ <div class="actions">
207
+ <input type="submit"
208
+ name="commit"
209
+ value="Save"
210
+ class="#{submit_button_styles}"
211
+ data-disable-with="Saving..." />
212
+
213
+ #{cancel_button}
214
+ </div>
215
+ HTML
216
+ end
217
+
218
+ #
219
+ # Close the form.
220
+ #
221
+ def close_form
222
+ return "</form>"
223
+ end
224
+
225
+ #
226
+ # Render the Form as HTML.
227
+ #
228
+ def render
229
+ @styles = styles
230
+ return open_form + render_content + close_form
231
+ end
232
+
233
+ #
234
+ # Render the element content using the specified render function.
235
+ # This is a recursive function (through one of the other render functions).
236
+ #
237
+ def render_content
238
+ fields = ""
239
+ field_can = form_content
240
+ return "" if field_can.nil?
241
+
242
+ field_can.children.each do |o|
243
+ o = Gloo::Objs::Alias.resolve_alias( @engine, o )
244
+ if o.class == Field
245
+ fields << o.render( @styles )
246
+ elsif o.class == Element
247
+ fields << o.render_html
248
+ elsif o
249
+ data = render_thing o
250
+ ( fields << data ) if data
251
+ end
252
+ end
253
+
254
+ return fields
255
+ end
256
+
257
+ #
258
+ # Render a string or other object.
259
+ #
260
+ def render_thing e
261
+ begin
262
+ return e.render( 'render_html' )
263
+ rescue => e
264
+ @engine.log_exception e
265
+ return ''
266
+ end
267
+ end
268
+
269
+ end
270
+ end
271
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gloo
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.2.1
4
+ version: 4.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric Crane
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-05-15 00:00:00.000000000 Z
11
+ date: 2025-07-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -294,20 +294,6 @@ dependencies:
294
294
  - - ">="
295
295
  - !ruby/object:Gem::Version
296
296
  version: 1.1.4
297
- - !ruby/object:Gem::Dependency
298
- name: pg
299
- requirement: !ruby/object:Gem::Requirement
300
- requirements:
301
- - - "~>"
302
- - !ruby/object:Gem::Version
303
- version: 1.5.4
304
- type: :runtime
305
- prerelease: false
306
- version_requirements: !ruby/object:Gem::Requirement
307
- requirements:
308
- - - "~>"
309
- - !ruby/object:Gem::Version
310
- version: 1.5.4
311
297
  - !ruby/object:Gem::Dependency
312
298
  name: thin
313
299
  requirement: !ruby/object:Gem::Requirement
@@ -496,6 +482,8 @@ files:
496
482
  - lib/gloo/objs/web/teams.rb
497
483
  - lib/gloo/objs/web/uri.rb
498
484
  - lib/gloo/objs/web_svr/element.rb
485
+ - lib/gloo/objs/web_svr/field.rb
486
+ - lib/gloo/objs/web_svr/form.rb
499
487
  - lib/gloo/objs/web_svr/page.rb
500
488
  - lib/gloo/objs/web_svr/partial.rb
501
489
  - lib/gloo/objs/web_svr/svr.rb