gloo 3.1.1 → 3.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -13,6 +13,8 @@ module Gloo
13
13
  KEYWORD_SHORT = 'tbl'.freeze
14
14
  HEADERS = 'headers'.freeze
15
15
  DATA = 'data'.freeze
16
+ CELLS = 'cells'.freeze
17
+ STYLES = 'styles'.freeze
16
18
 
17
19
  #
18
20
  # The name of the object type.
@@ -58,12 +60,64 @@ module Gloo
58
60
  return [] unless o
59
61
 
60
62
  o = Gloo::Objs::Alias.resolve_alias( @engine, o )
61
- cols = self.columns
62
- return o.children.map do |e|
63
- cols.map { |h| e.find_child( h ).value }
63
+
64
+ if o.is_a? Gloo::Objs::Query
65
+ @engine.log.debug "Table getting data from query."
66
+ begin
67
+ result = o.run_query
68
+ return result
69
+ rescue => e
70
+ @engine.err e.message
71
+ return nil
72
+ end
73
+ else
74
+ cols = self.columns
75
+
76
+ if o.children&.first.children.empty?
77
+ # It is a simgle row table.
78
+ rows = [ cols.map { |h| o.find_child( h )&.value } ]
79
+ else
80
+ rows = o.children.map do |e|
81
+ cols.map { |h| e.find_child( h )&.value }
82
+ end
83
+ end
84
+
85
+ return [ cols, rows ]
64
86
  end
65
87
  end
66
88
 
89
+ #
90
+ # Get the styles for the table, if any.
91
+ #
92
+ def styles
93
+ style_h = {}
94
+ o = find_child STYLES
95
+ return style_h unless o
96
+ o = Gloo::Objs::Alias.resolve_alias( @engine, o )
97
+
98
+ o.children.each do |c|
99
+ style_h[ c.name ] = c.value
100
+ end
101
+
102
+ return style_h
103
+ end
104
+
105
+ #
106
+ # Get cell renderer hash keyed by column name.
107
+ #
108
+ def cell_renderers
109
+ h = {}
110
+ o = find_child CELLS
111
+ return h unless o
112
+
113
+ o.children.each do |c|
114
+ h[ c.name ] = c.value
115
+ end
116
+
117
+ return h
118
+ end
119
+
120
+
67
121
  # ---------------------------------------------------------------------
68
122
  # Children
69
123
  # ---------------------------------------------------------------------
@@ -88,6 +142,7 @@ module Gloo
88
142
  fac.create_can DATA, self
89
143
  end
90
144
 
145
+
91
146
  # ---------------------------------------------------------------------
92
147
  # Messages
93
148
  # ---------------------------------------------------------------------
@@ -96,7 +151,7 @@ module Gloo
96
151
  # Get a list of message names that this object receives.
97
152
  #
98
153
  def self.messages
99
- return super + %w[show]
154
+ return super + %w[show render]
100
155
  end
101
156
 
102
157
  #
@@ -107,6 +162,90 @@ module Gloo
107
162
  @engine.platform.show_table headers, data, title
108
163
  end
109
164
 
165
+ def msg_render
166
+ return render
167
+ end
168
+
169
+
170
+ # ---------------------------------------------------------------------
171
+ # Render
172
+ # ---------------------------------------------------------------------
173
+
174
+ #
175
+ # Render the table.
176
+ # The render_ƒ is 'render_html', 'render_text', 'render_json', etc.
177
+ #
178
+ def render render_ƒ
179
+ begin
180
+ result = self.data
181
+ head = self.headers
182
+ head = result[0] if head.empty?
183
+ rows = result[1]
184
+
185
+ columns = build_columns result[0]
186
+
187
+ params = {
188
+ head: head,
189
+ cols: result[0],
190
+ columns: columns,
191
+ rows: rows,
192
+ styles: self.styles,
193
+ cell_renderers: self.cell_renderers
194
+ }
195
+
196
+ helper = Gloo::WebSvr::TableRenderer.new( @engine )
197
+ return helper.data_to_table params
198
+ rescue => e
199
+ @engine.err e.message
200
+ return nil
201
+ end
202
+ end
203
+
204
+ #
205
+ # Build the column list based on the result data and
206
+ # the headers defined in the table object.
207
+ #
208
+ def build_columns result_data
209
+ head_children = find_child HEADERS
210
+ cell_renderers = find_child CELLS
211
+
212
+ columns = []
213
+ return columns unless result_data
214
+
215
+ result_data.each_with_index do |c,index|
216
+ visible = true
217
+ name = c
218
+ title = c
219
+ display_index = index
220
+
221
+ if head_children
222
+ child = head_children.find_child c
223
+ if child
224
+ title = child.value
225
+ display_index = head_children.child_index( c )
226
+ else
227
+ visible = false
228
+ end
229
+ end
230
+
231
+ cell_renderer = nil
232
+ if cell_renderers
233
+ this_cr = cell_renderers.find_child( c )
234
+ cell_renderer = this_cr.value if this_cr
235
+ end
236
+
237
+ columns << {
238
+ name: name,
239
+ title: title,
240
+ visible: visible,
241
+ data_index: index,
242
+ display_index: display_index,
243
+ cell_renderer: cell_renderer
244
+ }
245
+ end
246
+ return columns.sort_by { |hsh| hsh[ :display_index ] }
247
+ end
248
+
110
249
  end
111
250
  end
112
251
  end
@@ -63,6 +63,8 @@ module Gloo
63
63
  # Make the JSON pretty.
64
64
  #
65
65
  def msg_pretty
66
+ return unless self.value
67
+
66
68
  json = JSON.parse( self.value )
67
69
  pretty = JSON.pretty_generate( json )
68
70
  set_value pretty
@@ -173,7 +173,7 @@ module Gloo
173
173
  # Get the expiration date for the certificate.
174
174
  #
175
175
  def msg_render
176
- content = self.render
176
+ content = self.render_html
177
177
  @engine.heap.it.set_to content
178
178
  return content
179
179
  end
@@ -226,10 +226,9 @@ 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 == Partial
230
- rendered_obj_content << e.render( render_ƒ )
231
229
  else
232
- rendered_obj_content << e.value.to_s
230
+ data = render_thing e, render_ƒ, engine
231
+ ( rendered_obj_content << data ) if data # e.render( render_ƒ )
233
232
  end
234
233
  end
235
234
  else
@@ -238,7 +237,16 @@ module Gloo
238
237
 
239
238
  return rendered_obj_content
240
239
  end
241
-
240
+
241
+ def self.render_thing e, render_ƒ, engine
242
+ begin
243
+ return e.render( render_ƒ )
244
+ rescue => e
245
+ engine.err e.message
246
+ return ''
247
+ end
248
+ end
249
+
242
250
  end
243
251
  end
244
252
  end
@@ -17,6 +17,7 @@ module Gloo
17
17
 
18
18
  # Parameters used during render.
19
19
  PARAMS = 'params'.freeze
20
+ ID = 'id'.freeze
20
21
 
21
22
  # Content
22
23
  HEAD = 'head'.freeze
@@ -112,6 +113,19 @@ module Gloo
112
113
  params_can = find_child PARAMS
113
114
  return nil unless params_can
114
115
 
116
+ if @request
117
+ url_params = @request.query_params
118
+ url_params.each do |k,v|
119
+ o = params_can.find_child k
120
+ o.set_value( v ) if o
121
+ end
122
+
123
+ @request.body_params.each do |k,v|
124
+ o = params_can.find_child k
125
+ o.set_value( v ) if o
126
+ end
127
+ end
128
+
115
129
  h = {}
116
130
  params_can.children.each do |o|
117
131
  h[ o.name ] = o.value
@@ -281,15 +295,38 @@ module Gloo
281
295
  return @engine.running_app.obj.redirect
282
296
  end
283
297
 
298
+ #
299
+ # Set the ID parameter if there is one.
300
+ #
301
+ def set_id
302
+ return unless @request.id
303
+ @engine.log.info "Setting ID: #{@request.id}"
304
+
305
+ params_can = find_child PARAMS
306
+ return nil unless params_can
307
+
308
+ id_obj = params_can.find_child( ID )
309
+ return unless id_obj
310
+
311
+ id_obj.set_value( @request.id )
312
+ end
313
+
284
314
  #
285
315
  # Render the page.
316
+ # If this is being called from the web server,
317
+ # the request will be passed in and will include
318
+ # request context such as params.
286
319
  #
287
- def render
288
- run_on_render
289
- return nil if redirect_set?
320
+ def render request=nil
321
+ @request = request
322
+ set_id if @request
290
323
 
324
+ # Set Params before running on render
291
325
  params = params_hash
292
326
 
327
+ run_on_render
328
+ return nil if redirect_set?
329
+
293
330
  if is_html?
294
331
  contents = render_html params
295
332
  elsif is_json?
@@ -302,6 +339,7 @@ module Gloo
302
339
  end
303
340
 
304
341
  run_on_rendered
342
+ @request = nil
305
343
  return nil if redirect_set?
306
344
 
307
345
  return contents
@@ -161,8 +161,13 @@ module Gloo
161
161
  run_on_render
162
162
 
163
163
  part_content = ''
164
- content.children.each do |e|
165
- part_content << e.send( render_ƒ )
164
+ data = content
165
+ if data.children.empty?
166
+ part_content = data.value
167
+ else
168
+ data.children.each do |e|
169
+ part_content << e.send( render_ƒ )
170
+ end
166
171
  end
167
172
 
168
173
  # part_content = Page.render_params part_content, params_hash
@@ -16,6 +16,10 @@ module Gloo
16
16
  HOST = 'host'.freeze
17
17
  PORT = 'port'.freeze
18
18
 
19
+ # SSL Configuration
20
+ SSL_CERT = 'ssl_cert'.freeze
21
+ SSL_KEY = 'ssl_key'.freeze
22
+
19
23
  # Events
20
24
  ON_START = 'on_start'.freeze
21
25
  ON_STOP = 'on_stop'.freeze
@@ -32,7 +36,7 @@ module Gloo
32
36
 
33
37
 
34
38
  # Messages
35
- SERVER_NOT_RUNNING = 'The web server is not running and cannot be stopped'.freeze
39
+ SERVER_NOT_RUNNING = 'The web server is not running!'.freeze
36
40
 
37
41
  #
38
42
  # Should the current request be redirected?
@@ -115,6 +119,56 @@ module Gloo
115
119
  return o
116
120
  end
117
121
 
122
+
123
+ # ---------------------------------------------------------------------
124
+ # SSL
125
+ # ---------------------------------------------------------------------
126
+
127
+ #
128
+ # Is SSL configured for this server?
129
+ # True if the Cert and Key are both present.
130
+ #
131
+ def use_ssl?
132
+ return ssl_cert && ssl_key
133
+ end
134
+
135
+ #
136
+ # Get the SSL certificate from the child object.
137
+ # Returns nil if there is none.
138
+ #
139
+ def ssl_cert
140
+ cert = find_child SSL_CERT
141
+ return nil unless cert
142
+
143
+ cert = Gloo::Objs::Alias.resolve_alias( @engine, cert )
144
+ return cert
145
+ end
146
+
147
+ #
148
+ # Get the SSL key from the child object.
149
+ # Returns nil if there is none.
150
+ #
151
+ def ssl_key
152
+ key = find_child SSL_KEY
153
+ return nil unless key
154
+
155
+ key = Gloo::Objs::Alias.resolve_alias( @engine, key )
156
+ return key
157
+ end
158
+
159
+ #
160
+ # Get the SSL configuration for the server.
161
+ #
162
+ def ssl_config
163
+ return nil unless use_ssl?
164
+
165
+ return {
166
+ :private_key_file => ssl_key.value,
167
+ :cert_chain_file => ssl_cert.value,
168
+ :verify_peer => false,
169
+ }
170
+ end
171
+
118
172
  # ---------------------------------------------------------------------
119
173
  # Children
120
174
  # ---------------------------------------------------------------------
@@ -156,7 +210,7 @@ module Gloo
156
210
  # Get a list of message names that this object receives.
157
211
  #
158
212
  def self.messages
159
- return super + [ 'start', 'stop' ]
213
+ return super + [ 'start', 'stop', 'routes' ]
160
214
  end
161
215
 
162
216
  #
@@ -183,6 +237,18 @@ module Gloo
183
237
  end
184
238
  end
185
239
 
240
+ #
241
+ # Helper message to show all routes in the running server.
242
+ #
243
+ def msg_routes
244
+ if @router
245
+ @router.show_routes
246
+ else
247
+ @engine.log.error SERVER_NOT_RUNNING
248
+ end
249
+ end
250
+
251
+
186
252
  # ---------------------------------------------------------------------
187
253
  # Start and Stop Events
188
254
  # Might come from messages or from other application events.
@@ -197,10 +263,10 @@ module Gloo
197
263
  @engine.log.info "Web Server URL: #{config.base_url}"
198
264
 
199
265
  handler = Gloo::WebSvr::Handler.new( @engine, self )
200
- @web_server = Gloo::WebSvr::Server.new( @engine, handler, config )
266
+ @web_server = Gloo::WebSvr::Server.new( @engine, handler, config, ssl_config )
201
267
  @web_server.start
202
268
 
203
- @router = Gloo::WebSvr::Router.new( @engine, self )
269
+ @router = Gloo::WebSvr::Routing::Router.new( @engine, self )
204
270
  @router.add_page_routes
205
271
 
206
272
  @asset = Gloo::WebSvr::Asset.new( @engine, self )
@@ -219,6 +285,7 @@ module Gloo
219
285
  @engine.log.info "Stopping web server…"
220
286
  @web_server.stop
221
287
  @web_server = nil
288
+ @router = nil
222
289
 
223
290
  run_on_stop
224
291
  @engine.log.info "Web server stopped…"
@@ -0,0 +1,44 @@
1
+ # Author:: Eric Crane (mailto:eric.crane@mac.com)
2
+ # Copyright:: Copyright (c) 2024 Eric Crane. All rights reserved.
3
+ #
4
+ # Break out of the script without error.
5
+ #
6
+
7
+ module Gloo
8
+ module Verbs
9
+ class Break < Gloo::Core::Verb
10
+
11
+ KEYWORD = 'break'.freeze
12
+ KEYWORD_SHORT = 'stop'.freeze
13
+
14
+ #
15
+ # Run the verb.
16
+ # Stop the execution of the current script.
17
+ #
18
+ def run
19
+ @engine.exec_env.running_script.break_out
20
+ end
21
+
22
+ #
23
+ # Get the Verb's keyword.
24
+ #
25
+ def self.keyword
26
+ return KEYWORD
27
+ end
28
+
29
+ #
30
+ # Get the Verb's keyword shortcut.
31
+ #
32
+ def self.keyword_shortcut
33
+ return KEYWORD_SHORT
34
+ end
35
+
36
+ # ---------------------------------------------------------------------
37
+ # Private functions
38
+ # ---------------------------------------------------------------------
39
+
40
+ private
41
+
42
+ end
43
+ end
44
+ end
@@ -57,6 +57,12 @@ module Gloo
57
57
  if Gloo::Expr::LString.string?( value )
58
58
  value = Gloo::Expr::LString.strip_quotes( value )
59
59
  end
60
+
61
+ # Check to see if this is an alias
62
+ pn = Gloo::Core::Pn.new( @engine, name )
63
+ obj = pn.resolve if pn
64
+ name = obj.value if obj&.is_alias?
65
+
60
66
  obj = @engine.factory.create( { name: name, type: type, value: value } )
61
67
 
62
68
  obj.add_default_children if obj&.add_children_on_create?
@@ -16,11 +16,11 @@ module Gloo
16
16
  #
17
17
  def run
18
18
  if @tokens.token_count > 1
19
- expr = Gloo::Expr::Expression.new( @engine, @tokens.params )
20
- result = expr.evaluate
21
- level = log_level_specified( result )
22
- @engine.log.write result, level
23
- @engine.heap.it.set_to result
19
+ if is_clear_cmd?
20
+ @engine.log.clear
21
+ else
22
+ write_to_log
23
+ end
24
24
  else
25
25
  @engine.log.debug ''
26
26
  end
@@ -46,6 +46,27 @@ module Gloo
46
46
 
47
47
  private
48
48
 
49
+ #
50
+ # Write to the specified logger.
51
+ #
52
+ def write_to_log
53
+ expr = Gloo::Expr::Expression.new( @engine, @tokens.params )
54
+ result = expr.evaluate
55
+ level = log_level_specified( result )
56
+ @engine.log.write result, level
57
+ @engine.heap.it.set_to result
58
+ end
59
+
60
+ #
61
+ # Is this a clear logs command?
62
+ #
63
+ def is_clear_cmd?
64
+ return true if ( ( @tokens.token_count == 2 ) &&
65
+ ( @tokens.params.first == 'clear' ) )
66
+
67
+ return false
68
+ end
69
+
49
70
  #
50
71
  # Get the formatted string.
51
72
  #
@@ -12,7 +12,11 @@ module Gloo
12
12
  KEYWORD = 'redirect'.freeze
13
13
  KEYWORD_SHORT = 'go'.freeze
14
14
 
15
+ RUN_MESSAGE = 'run'.freeze
16
+
15
17
  MISSING_EXPR_ERR = 'Missing Expression!'.freeze
18
+ APP_NOT_RUNING_ERR = 'The application is not running!'.freeze
19
+ BAD_TARGET_ERR = 'Bad redirect target!'.freeze
16
20
 
17
21
  #
18
22
  # Run the verb.
@@ -23,12 +27,8 @@ module Gloo
23
27
  return
24
28
  end
25
29
 
26
- # Send the redirect page to the running app.
27
- if @engine.app_running?
28
- obj_name = @tokens.second
29
- pn = Gloo::Core::Pn.new( @engine, obj_name )
30
- @engine.running_app.obj.redirect = pn.resolve
31
- end
30
+ determine_target
31
+ redirect_to_target
32
32
  end
33
33
 
34
34
  #
@@ -51,6 +51,54 @@ module Gloo
51
51
 
52
52
  private
53
53
 
54
+ #
55
+ # Send the control to the redirect target.
56
+ # This could be a page or a script.
57
+ #
58
+ def redirect_to_target
59
+ if @target_obj.class == Gloo::Objs::Page
60
+ redirect_to_page
61
+ elsif @target_obj.can_receive_message?( RUN_MESSAGE )
62
+ redirect_to_script
63
+ else
64
+ @engine.err BAD_TARGET_ERR
65
+ end
66
+ end
67
+
68
+ #
69
+ # Find the target of the redirect.
70
+ #
71
+ def determine_target
72
+ obj_name = @tokens.second
73
+ pn = Gloo::Core::Pn.new( @engine, obj_name )
74
+
75
+ @target_obj = pn.resolve
76
+
77
+ @engine.log.info "obj type: #{@target_obj.class}"
78
+ end
79
+
80
+ #
81
+ # Redirect to a page.
82
+ # This requires a running web server.
83
+ #
84
+ def redirect_to_page
85
+ if @engine.app_running?
86
+ @engine.running_app.obj.redirect = @target_obj
87
+ else
88
+ @engine.err APP_NOT_RUNING_ERR
89
+ end
90
+ end
91
+
92
+ #
93
+ # Redirect to another script.
94
+ # This stops execution of the current script.
95
+ #
96
+ def redirect_to_script
97
+ @engine.exec_env.running_script.break_out
98
+
99
+ Gloo::Exec::Dispatch.message( @engine, RUN_MESSAGE, @target_obj )
100
+ end
101
+
54
102
  end
55
103
  end
56
104
  end
@@ -11,6 +11,7 @@ module Gloo
11
11
  ASSETS_FOLDER = 'assets'.freeze
12
12
  IMAGES_FOLDER = 'images'.freeze
13
13
  STYLESHEETS_FOLDER = 'stylesheets'.freeze
14
+ JAVASCRIPT_FOLDER = 'javascript'.freeze
14
15
 
15
16
  CSS_TYPE = 'text/css'.freeze
16
17
  JS_TYPE = 'text/javascript'.freeze
@@ -59,6 +60,13 @@ module Gloo
59
60
  return File.join( assets_folder, STYLESHEETS_FOLDER )
60
61
  end
61
62
 
63
+ #
64
+ # Get the stylesheets folder in the project.
65
+ #
66
+ def javascript_folder
67
+ return File.join( assets_folder, JAVASCRIPT_FOLDER )
68
+ end
69
+
62
70
  #
63
71
  # Find and return the page for the given route.
64
72
  #
@@ -125,6 +133,7 @@ module Gloo
125
133
  add_containers
126
134
  add_images
127
135
  add_stylesheets
136
+ add_javascript
128
137
  end
129
138
 
130
139
  #
@@ -141,6 +150,9 @@ module Gloo
141
150
 
142
151
  @stylesheets = @assets.find_child( STYLESHEETS_FOLDER ) ||
143
152
  @factory.create_can( STYLESHEETS_FOLDER, @assets )
153
+
154
+ @javascript = @assets.find_child( JAVASCRIPT_FOLDER ) ||
155
+ @factory.create_can( JAVASCRIPT_FOLDER, @assets )
144
156
  end
145
157
 
146
158
  #
@@ -175,6 +187,22 @@ module Gloo
175
187
  end
176
188
  end
177
189
 
190
+ #
191
+ # Add the Javascript files to the web server pages.
192
+ #
193
+ def add_javascript
194
+ @log.debug 'Adding javascript asset routes to web server…'
195
+
196
+ return unless File.exist? javascript_folder
197
+
198
+ # for each file in the javascript folder
199
+ # create a file object and add it to the javascript container
200
+ Dir.each_child( javascript_folder ) do |name|
201
+ pn = File.join( JAVASCRIPT_FOLDER, name )
202
+ add_file_obj( @javascript, name, pn )
203
+ end
204
+ end
205
+
178
206
  #
179
207
  # Add a file object (page route) to the given container.
180
208
  #