gloo 3.1.0 → 3.2.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 +4 -4
- data/lib/VERSION +1 -1
- data/lib/VERSION_NOTES +10 -0
- data/lib/gloo/app/log.rb +46 -6
- data/lib/gloo/app/running_app.rb +42 -1
- data/lib/gloo/core/obj.rb +34 -1
- data/lib/gloo/exec/exec_env.rb +4 -0
- data/lib/gloo/exec/script.rb +9 -1
- data/lib/gloo/objs/basic/container.rb +18 -2
- data/lib/gloo/objs/cli/menu.rb +9 -3
- data/lib/gloo/objs/data/mysql.rb +35 -7
- data/lib/gloo/objs/data/pg.rb +8 -0
- data/lib/gloo/objs/data/query.rb +66 -11
- data/lib/gloo/objs/data/query_result.rb +22 -1
- data/lib/gloo/objs/data/sqlite.rb +17 -2
- data/lib/gloo/objs/data/table.rb +143 -4
- data/lib/gloo/objs/web/json.rb +2 -0
- data/lib/gloo/objs/web_svr/element.rb +13 -5
- data/lib/gloo/objs/web_svr/page.rb +41 -3
- data/lib/gloo/objs/web_svr/partial.rb +7 -2
- data/lib/gloo/objs/web_svr/svr.rb +71 -4
- data/lib/gloo/verbs/break.rb +44 -0
- data/lib/gloo/verbs/create.rb +6 -0
- data/lib/gloo/verbs/log.rb +26 -5
- data/lib/gloo/verbs/redirect.rb +54 -6
- data/lib/gloo/web_svr/asset.rb +28 -0
- data/lib/gloo/web_svr/handler.rb +4 -2
- data/lib/gloo/web_svr/request.rb +35 -2
- data/lib/gloo/web_svr/routing/resource_router.rb +47 -0
- data/lib/gloo/web_svr/routing/router.rb +218 -0
- data/lib/gloo/web_svr/routing/show_routes.rb +98 -0
- data/lib/gloo/web_svr/server.rb +10 -2
- data/lib/gloo/web_svr/table_renderer.rb +147 -0
- data/lib/gloo/web_svr/web_method.rb +54 -0
- metadata +9 -4
- data/lib/gloo/web_svr/router.rb +0 -179
data/lib/gloo/web_svr/handler.rb
CHANGED
@@ -36,7 +36,9 @@ module Gloo
|
|
36
36
|
def handle request
|
37
37
|
@request = request
|
38
38
|
|
39
|
-
page = @server_obj.router.page_for_route @request.path
|
39
|
+
page, id = @server_obj.router.page_for_route( @request.path, @request.method )
|
40
|
+
@engine.log.debug "Found Page: #{page&.name}" if page
|
41
|
+
request.id = id
|
40
42
|
if page
|
41
43
|
if page.is_a? Gloo::Objs::FileHandle
|
42
44
|
return handle_file page
|
@@ -53,7 +55,7 @@ module Gloo
|
|
53
55
|
# Render the page, with possible redirect.
|
54
56
|
#
|
55
57
|
def handle_page page
|
56
|
-
result = page.render
|
58
|
+
result = page.render @request
|
57
59
|
if redirect_set?
|
58
60
|
page = @engine.running_app.obj.redirect
|
59
61
|
@log.debug "Redirecting to: #{page.pn}"
|
data/lib/gloo/web_svr/request.rb
CHANGED
@@ -19,7 +19,8 @@ module Gloo
|
|
19
19
|
HTTP_HOST = 'HTTP_HOST'.freeze
|
20
20
|
QUERY_STRING = 'QUERY_STRING'.freeze
|
21
21
|
|
22
|
-
attr_reader :method, :host, :path, :query
|
22
|
+
attr_reader :method, :host, :path, :query, :body
|
23
|
+
attr_accessor :id
|
23
24
|
|
24
25
|
|
25
26
|
# ---------------------------------------------------------------------
|
@@ -66,6 +67,10 @@ module Gloo
|
|
66
67
|
@path = @env[ REQUEST_PATH ]
|
67
68
|
@host = @env[ HTTP_HOST ]
|
68
69
|
@query = @env[ QUERY_STRING ]
|
70
|
+
|
71
|
+
@body = @env[ 'rack.input' ].read
|
72
|
+
@body = Rack::Utils.parse_query @body
|
73
|
+
check_body_method
|
69
74
|
end
|
70
75
|
|
71
76
|
|
@@ -78,6 +83,7 @@ module Gloo
|
|
78
83
|
#
|
79
84
|
def start_timer
|
80
85
|
@start = Time.now
|
86
|
+
@engine.running_app.reset_db_time
|
81
87
|
end
|
82
88
|
|
83
89
|
#
|
@@ -86,7 +92,8 @@ module Gloo
|
|
86
92
|
def finish_timer
|
87
93
|
@finish = Time.now
|
88
94
|
@elapsed = ( ( @finish - @start ) * 1000.0 ).round(2)
|
89
|
-
|
95
|
+
db = @engine.running_app.db_time
|
96
|
+
@log.info "*** Web request complete. DB: #{db} ms. Elapsed time: #{@elapsed} ms"
|
90
97
|
end
|
91
98
|
|
92
99
|
|
@@ -94,12 +101,38 @@ module Gloo
|
|
94
101
|
# Helper functions
|
95
102
|
# ---------------------------------------------------------------------
|
96
103
|
|
104
|
+
#
|
105
|
+
# Check the body to see if there is a PATCH or a PUT in
|
106
|
+
# the method override.
|
107
|
+
#
|
108
|
+
def check_body_method
|
109
|
+
if @body[ '_method' ]
|
110
|
+
@method = @body[ '_method' ].upcase
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
#
|
115
|
+
# Get the hash of query parameters.
|
116
|
+
#
|
117
|
+
def query_params
|
118
|
+
return {} unless @query
|
119
|
+
return Rack::Utils.parse_query( @query )
|
120
|
+
end
|
121
|
+
|
122
|
+
#
|
123
|
+
# Get the hash of body parameters.
|
124
|
+
#
|
125
|
+
def body_params
|
126
|
+
return @body ? @body : {}
|
127
|
+
end
|
128
|
+
|
97
129
|
#
|
98
130
|
# Write the request information to the log.
|
99
131
|
#
|
100
132
|
def log
|
101
133
|
@log.info "#{@method} #{@host}#{@path}"
|
102
134
|
@log.info "Parameters: #{@query}"
|
135
|
+
@log.info "Body: #{@body}" unless @body.empty?
|
103
136
|
end
|
104
137
|
|
105
138
|
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# Author:: Eric Crane (mailto:eric.crane@mac.com)
|
2
|
+
# Copyright:: Copyright (c) 2024 Eric Crane. All rights reserved.
|
3
|
+
#
|
4
|
+
# A helper class for Resource routing.
|
5
|
+
#
|
6
|
+
|
7
|
+
module Gloo
|
8
|
+
module WebSvr
|
9
|
+
module Routing
|
10
|
+
class ResourceRouter
|
11
|
+
|
12
|
+
INDEX = 'index'.freeze
|
13
|
+
SHOW = 'show'.freeze
|
14
|
+
DELETE = 'delete'.freeze
|
15
|
+
UPDATE = 'update'.freeze
|
16
|
+
|
17
|
+
POST_ROUTE = 'create'.freeze
|
18
|
+
|
19
|
+
|
20
|
+
#
|
21
|
+
# Is the given route segment an implicit create resource?
|
22
|
+
# It is explicit if it is 'create'
|
23
|
+
# and implicit if it is a POST to the resource.
|
24
|
+
#
|
25
|
+
def self.is_implicit_create?( method, route_segment )
|
26
|
+
return false unless Gloo::WebSvr::WebMethod.is_post?( method )
|
27
|
+
|
28
|
+
return ! route_segment.eql?( POST_ROUTE )
|
29
|
+
end
|
30
|
+
|
31
|
+
#
|
32
|
+
# Add the segment based on the method.
|
33
|
+
#
|
34
|
+
def self.segment_for_method( method )
|
35
|
+
if Gloo::WebSvr::WebMethod.is_delete?( method )
|
36
|
+
return DELETE
|
37
|
+
elsif Gloo::WebSvr::WebMethod.is_patch?( method )
|
38
|
+
return UPDATE
|
39
|
+
else
|
40
|
+
return SHOW
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,218 @@
|
|
1
|
+
# Author:: Eric Crane (mailto:eric.crane@mac.com)
|
2
|
+
# Copyright:: Copyright (c) 20124 Eric Crane. All rights reserved.
|
3
|
+
#
|
4
|
+
# A helper class for page routing.
|
5
|
+
#
|
6
|
+
require 'tty-table'
|
7
|
+
|
8
|
+
module Gloo
|
9
|
+
module WebSvr
|
10
|
+
module Routing
|
11
|
+
class Router
|
12
|
+
|
13
|
+
PAGE_CONTAINER = 'page'.freeze
|
14
|
+
SEGMENT_DIVIDER = '/'.freeze
|
15
|
+
|
16
|
+
attr_reader :route_segments
|
17
|
+
|
18
|
+
|
19
|
+
# ---------------------------------------------------------------------
|
20
|
+
# Initialization
|
21
|
+
# ---------------------------------------------------------------------
|
22
|
+
|
23
|
+
#
|
24
|
+
# Set up the web server.
|
25
|
+
#
|
26
|
+
def initialize( engine, web_svr_obj )
|
27
|
+
@engine = engine
|
28
|
+
@log = @engine.log
|
29
|
+
|
30
|
+
@web_svr_obj = web_svr_obj
|
31
|
+
@show_routes = ShowRoutes.new( @engine )
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
# ---------------------------------------------------------------------
|
36
|
+
# Routing
|
37
|
+
# ---------------------------------------------------------------------
|
38
|
+
|
39
|
+
#
|
40
|
+
# Find and return the page for the given route.
|
41
|
+
#
|
42
|
+
def page_for_route( path, method )
|
43
|
+
@log.info "routing to #{path} for method #{method}"
|
44
|
+
@method = method
|
45
|
+
|
46
|
+
detect_segments path
|
47
|
+
|
48
|
+
return @web_svr_obj.home_page if is_root_path?
|
49
|
+
|
50
|
+
pages = @web_svr_obj.pages_container
|
51
|
+
if pages
|
52
|
+
# If the method is POST and the last segment is NOT 'create',
|
53
|
+
# we'll add create to the route segments.
|
54
|
+
if Gloo::WebSvr::Routing::ResourceRouter.is_implicit_create?( method, @route_segments.last )
|
55
|
+
@route_segments << Gloo::WebSvr::Routing::ResourceRouter::POST_ROUTE
|
56
|
+
page = find_route_segment( pages.children )
|
57
|
+
return [ page, @id ] if page
|
58
|
+
|
59
|
+
# We didn't find the page, so remove the last segment and try again
|
60
|
+
# posting to the resource.
|
61
|
+
@route_segments.pop
|
62
|
+
end
|
63
|
+
|
64
|
+
page = find_route_segment( pages.children )
|
65
|
+
return [ page, @id ] if page
|
66
|
+
end
|
67
|
+
|
68
|
+
return nil
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
# ---------------------------------------------------------------------
|
73
|
+
# Dynamic Add Page Routes
|
74
|
+
# ---------------------------------------------------------------------
|
75
|
+
|
76
|
+
#
|
77
|
+
# Get the root level page container.
|
78
|
+
#
|
79
|
+
def page_container
|
80
|
+
pn = Gloo::Core::Pn.new( @engine, PAGE_CONTAINER )
|
81
|
+
return pn.resolve
|
82
|
+
end
|
83
|
+
|
84
|
+
#
|
85
|
+
# Add all page routes to the web server pages (routes).
|
86
|
+
#
|
87
|
+
def add_page_routes
|
88
|
+
can = page_container
|
89
|
+
return unless can
|
90
|
+
|
91
|
+
@log.debug 'Adding page routes to web server…'
|
92
|
+
@factory = @engine.factory
|
93
|
+
|
94
|
+
add_pages can, @web_svr_obj.pages_container
|
95
|
+
end
|
96
|
+
|
97
|
+
#
|
98
|
+
# Add the pages to the web server pages.
|
99
|
+
# This is a recursive function that will add all
|
100
|
+
# pages in the folder and subfolders.
|
101
|
+
#
|
102
|
+
def add_pages can, parent
|
103
|
+
# for each file in the page container
|
104
|
+
# create a page object and add it to the routes
|
105
|
+
can.children.each do |obj|
|
106
|
+
if obj.class == Gloo::Objs::Container
|
107
|
+
child_can = parent.find_add_child( obj.name, 'container' )
|
108
|
+
add_pages( obj, child_can )
|
109
|
+
elsif obj.class == Gloo::Objs::Page
|
110
|
+
add_route_alias( parent, obj.name, obj.pn )
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
#
|
116
|
+
# Add route alias to the page.
|
117
|
+
#
|
118
|
+
def add_route_alias( parent, name, pn )
|
119
|
+
name = name.gsub( '.', '_' )
|
120
|
+
|
121
|
+
# First make sure the child doesn't already exist.
|
122
|
+
child = parent.find_child( name )
|
123
|
+
return if child
|
124
|
+
|
125
|
+
@factory.create_alias( name, pn, parent )
|
126
|
+
end
|
127
|
+
|
128
|
+
|
129
|
+
# ---------------------------------------------------------------------
|
130
|
+
# Helper funcions
|
131
|
+
# ---------------------------------------------------------------------
|
132
|
+
|
133
|
+
#
|
134
|
+
# Show the routes in the running app.
|
135
|
+
# This uses the ShowRoutes helper class.
|
136
|
+
#
|
137
|
+
def show_routes
|
138
|
+
@show_routes.show page_container
|
139
|
+
end
|
140
|
+
|
141
|
+
#
|
142
|
+
# Find the route segment in the object container.
|
143
|
+
#
|
144
|
+
def find_route_segment objs
|
145
|
+
this_segment = next_segment
|
146
|
+
|
147
|
+
if this_segment.blank? # && Gloo::WebSvr::WebMethod.is_post?( @method )
|
148
|
+
this_segment = Gloo::WebSvr::Routing::ResourceRouter::INDEX
|
149
|
+
end
|
150
|
+
|
151
|
+
objs.each do |o|
|
152
|
+
o = Gloo::Objs::Alias.resolve_alias( @engine, o )
|
153
|
+
|
154
|
+
if o.name == this_segment
|
155
|
+
if o.class == Gloo::Objs::Page
|
156
|
+
@log.debug "found page for route: #{o.pn}"
|
157
|
+
return o
|
158
|
+
elsif o.class == Gloo::Objs::FileHandle
|
159
|
+
@log.debug "found static file for route: #{o.pn}"
|
160
|
+
return o
|
161
|
+
else
|
162
|
+
return nil unless o.child_count > 0
|
163
|
+
|
164
|
+
return find_route_segment( o.children )
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
return nil
|
170
|
+
end
|
171
|
+
|
172
|
+
#
|
173
|
+
# Get the next segment in the route.
|
174
|
+
#
|
175
|
+
def next_segment
|
176
|
+
this_segment = @route_segments.shift
|
177
|
+
return nil if this_segment.nil?
|
178
|
+
|
179
|
+
# A URL might include a dot in a name, but we can't do that
|
180
|
+
# because dot is a reserve path thing. So we replace it with
|
181
|
+
# an underscore.
|
182
|
+
this_segment = this_segment.gsub( '.', '_' )
|
183
|
+
|
184
|
+
return this_segment
|
185
|
+
end
|
186
|
+
|
187
|
+
#
|
188
|
+
# Is this the root path?
|
189
|
+
def is_root_path?
|
190
|
+
return @route_segments.count == 0
|
191
|
+
end
|
192
|
+
|
193
|
+
#
|
194
|
+
# Create a list of path segments.
|
195
|
+
#
|
196
|
+
def detect_segments path
|
197
|
+
# Split the path into segments.
|
198
|
+
@route_segments = path.split SEGMENT_DIVIDER
|
199
|
+
|
200
|
+
# Remove the first segment if it is empty.
|
201
|
+
@route_segments.shift if @route_segments.first.blank?
|
202
|
+
|
203
|
+
@route_segments.each do |seg|
|
204
|
+
if seg.to_i.to_s == seg
|
205
|
+
@id = seg.to_i
|
206
|
+
@log.info "found id for route: #{@id}"
|
207
|
+
@route_segments.delete seg
|
208
|
+
@route_segments << ResourceRouter.segment_for_method( @method )
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
return @route_segments
|
213
|
+
end
|
214
|
+
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
# Author:: Eric Crane (mailto:eric.crane@mac.com)
|
2
|
+
# Copyright:: Copyright (c) 20124 Eric Crane. All rights reserved.
|
3
|
+
#
|
4
|
+
# A helper class for to show routes for a running app.
|
5
|
+
#
|
6
|
+
require 'tty-table'
|
7
|
+
|
8
|
+
module Gloo
|
9
|
+
module WebSvr
|
10
|
+
module Routing
|
11
|
+
class ShowRoutes
|
12
|
+
|
13
|
+
SEGMENT_DIVIDER = '/'.freeze
|
14
|
+
RETURN = "\n".freeze
|
15
|
+
|
16
|
+
|
17
|
+
# ---------------------------------------------------------------------
|
18
|
+
# Initialization
|
19
|
+
# ---------------------------------------------------------------------
|
20
|
+
|
21
|
+
#
|
22
|
+
# Set up the web server.
|
23
|
+
#
|
24
|
+
def initialize( engine )
|
25
|
+
@engine = engine
|
26
|
+
@log = @engine.log
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
# ---------------------------------------------------------------------
|
31
|
+
# Show Routes
|
32
|
+
# ---------------------------------------------------------------------
|
33
|
+
|
34
|
+
#
|
35
|
+
# Show all available routes.
|
36
|
+
#
|
37
|
+
def show page_container
|
38
|
+
@log.debug "showing routes"
|
39
|
+
|
40
|
+
@found_routes = []
|
41
|
+
@log.debug "building route table"
|
42
|
+
add_container_routes( page_container, SEGMENT_DIVIDER )
|
43
|
+
|
44
|
+
show_table
|
45
|
+
end
|
46
|
+
|
47
|
+
#
|
48
|
+
# Show the routes in the given container.
|
49
|
+
# This is a recursive function travese the object tree.
|
50
|
+
#
|
51
|
+
def add_container_routes can, route_path
|
52
|
+
can.children.each do |obj|
|
53
|
+
if obj.class == Gloo::Objs::Container
|
54
|
+
add_container_routes obj, "#{route_path}#{obj.name}#{SEGMENT_DIVIDER}"
|
55
|
+
elsif obj.class == Gloo::Objs::Page
|
56
|
+
route = "#{route_path}#{obj.name}"
|
57
|
+
@found_routes << [ obj.name, obj.pn, route, Gloo::WebSvr::WebMethod::GET ]
|
58
|
+
|
59
|
+
# If the method is POST, add a route alias for the create.
|
60
|
+
if obj.name.eql? ResourceRouter::POST_ROUTE
|
61
|
+
@found_routes << [ '', '', route_path, Gloo::WebSvr::WebMethod::POST ]
|
62
|
+
elsif obj.name.eql? ResourceRouter::UPDATE
|
63
|
+
@found_routes << [ '', '', route_path, Gloo::WebSvr::WebMethod::PATCH ]
|
64
|
+
elsif obj.name.eql? ResourceRouter::DELETE
|
65
|
+
@found_routes << [ '', '', route_path, Gloo::WebSvr::WebMethod::DELETE ]
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
# ---------------------------------------------------------------------
|
73
|
+
# Show Routes
|
74
|
+
# ---------------------------------------------------------------------
|
75
|
+
|
76
|
+
#
|
77
|
+
# Show the Routes title.
|
78
|
+
#
|
79
|
+
def show_table
|
80
|
+
@log.show "\n\tRoutes in Running Web App\n", :white
|
81
|
+
|
82
|
+
table = TTY::Table.new( headers, @found_routes )
|
83
|
+
renderer = TTY::Table::Renderer::Unicode.new( table, padding: [0,1] )
|
84
|
+
puts renderer.render
|
85
|
+
puts RETURN
|
86
|
+
end
|
87
|
+
|
88
|
+
#
|
89
|
+
# Get the table headers.
|
90
|
+
#
|
91
|
+
def headers
|
92
|
+
return [ 'Obj Name', 'Obj Path', 'Route', 'Method' ]
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
data/lib/gloo/web_svr/server.rb
CHANGED
@@ -34,8 +34,9 @@ module Gloo
|
|
34
34
|
#
|
35
35
|
# Set up the web server.
|
36
36
|
#
|
37
|
-
def initialize( engine, handler, config = nil )
|
37
|
+
def initialize( engine, handler, config = nil, ssl_config = nil )
|
38
38
|
@config = config ? config : Gloo::WebSvr::Config.new
|
39
|
+
@ssl_config = ssl_config
|
39
40
|
@engine = engine
|
40
41
|
@log = @engine.log
|
41
42
|
@handler = handler
|
@@ -57,7 +58,14 @@ module Gloo
|
|
57
58
|
:Host => @config.host
|
58
59
|
}
|
59
60
|
Thread.abort_on_exception = true
|
60
|
-
@server_thread = Thread.new {
|
61
|
+
@server_thread = Thread.new {
|
62
|
+
Rack::Handler::Thin.run( self, **options=opts ) do |server|
|
63
|
+
if @ssl_config
|
64
|
+
server.ssl = true
|
65
|
+
server.ssl_options = @ssl_config
|
66
|
+
end
|
67
|
+
end
|
68
|
+
}
|
61
69
|
@log.debug 'Web server has started.'
|
62
70
|
end
|
63
71
|
|
@@ -0,0 +1,147 @@
|
|
1
|
+
# Author:: Eric Crane (mailto:eric.crane@mac.com)
|
2
|
+
# Copyright:: Copyright (c) 20124 Eric Crane. All rights reserved.
|
3
|
+
#
|
4
|
+
# A helper class used to render HTML tables.
|
5
|
+
#
|
6
|
+
|
7
|
+
module Gloo
|
8
|
+
module WebSvr
|
9
|
+
class TableRenderer
|
10
|
+
|
11
|
+
TABLE = 'table'.freeze
|
12
|
+
THEAD = 'thead'.freeze
|
13
|
+
HEAD_CELL = 'head_cell'.freeze
|
14
|
+
ROW = 'row'.freeze
|
15
|
+
CELL = 'cell'.freeze
|
16
|
+
|
17
|
+
# ---------------------------------------------------------------------
|
18
|
+
# Initialization
|
19
|
+
# ---------------------------------------------------------------------
|
20
|
+
|
21
|
+
#
|
22
|
+
# Set up the web server.
|
23
|
+
#
|
24
|
+
def initialize( engine )
|
25
|
+
@engine = engine
|
26
|
+
@log = @engine.log
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
# ---------------------------------------------------------------------
|
31
|
+
# Container Renderer
|
32
|
+
# ---------------------------------------------------------------------
|
33
|
+
|
34
|
+
#
|
35
|
+
# Render the query result set to an HTML table.
|
36
|
+
#
|
37
|
+
# params = {
|
38
|
+
# head: head,
|
39
|
+
# cols: result[0],
|
40
|
+
# rows: rows,
|
41
|
+
# styles: self.styles,
|
42
|
+
# cell_renderers: self.cell_renderers
|
43
|
+
# }
|
44
|
+
#
|
45
|
+
def data_to_table params
|
46
|
+
data = params[ :rows ]
|
47
|
+
|
48
|
+
if data.nil? || ( data.length == 0 )
|
49
|
+
return "<p>No data found.</p>"
|
50
|
+
elsif data.length == 1
|
51
|
+
return data_to_single_row_table( params )
|
52
|
+
else
|
53
|
+
return data_to_table_rows( params )
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
#
|
58
|
+
# Show in single-row (form) format.
|
59
|
+
#
|
60
|
+
def data_to_single_row_table( params )
|
61
|
+
styles = params[ :styles ]
|
62
|
+
str = "<table class='#{styles[ TABLE ]}'> <tbody>"
|
63
|
+
row = params[ :rows ].first
|
64
|
+
|
65
|
+
params[ :columns ].each do |head|
|
66
|
+
next unless head[ :visible ]
|
67
|
+
cell = row[ head[ :data_index ] ]
|
68
|
+
|
69
|
+
if head[ :cell_renderer ]
|
70
|
+
cell_value = render_cell( row, head, params[ :columns ] )
|
71
|
+
else
|
72
|
+
cell_value = cell
|
73
|
+
end
|
74
|
+
|
75
|
+
str += "<tr class='#{styles[ ROW ]}'>"
|
76
|
+
str += "<th style='#{styles[ HEAD_CELL ]}'>#{head[ :title ]}</th>"
|
77
|
+
str += "<td style='#{styles[ CELL ]}'>#{cell_value}</td>"
|
78
|
+
str += "</tr>"
|
79
|
+
end
|
80
|
+
|
81
|
+
str += "</tbody></table>"
|
82
|
+
return str
|
83
|
+
end
|
84
|
+
|
85
|
+
#
|
86
|
+
# Show in normal, multi-row format.
|
87
|
+
#
|
88
|
+
def data_to_table_rows( params )
|
89
|
+
styles = params[ :styles ]
|
90
|
+
# headers = params[ :head ]
|
91
|
+
|
92
|
+
str = "<table class='#{styles[ TABLE ]}'>"
|
93
|
+
str << "<thead class='#{styles[ THEAD ]}'><tr>"
|
94
|
+
|
95
|
+
params[ :columns ].each do |head|
|
96
|
+
next unless head[ :visible ]
|
97
|
+
str += "<th class='#{styles[ HEAD_CELL ]}'>#{head[ :title ]}</th>"
|
98
|
+
end
|
99
|
+
str << "</tr></thead><tbody>"
|
100
|
+
|
101
|
+
params[ :rows ].each do |row|
|
102
|
+
str += "<tr class='#{styles[ ROW ]}'>"
|
103
|
+
|
104
|
+
# row.each_with_index do |cell, i|
|
105
|
+
params[ :columns ].each do |head|
|
106
|
+
next unless head[ :visible ]
|
107
|
+
|
108
|
+
cell = row[ head[ :data_index ] ]
|
109
|
+
this_col_name = head[ :name ]
|
110
|
+
|
111
|
+
if head[ :cell_renderer ]
|
112
|
+
cell_value = render_cell( row, head, params[ :columns ] )
|
113
|
+
else
|
114
|
+
cell_value = cell
|
115
|
+
end
|
116
|
+
str += "<td style='#{styles[ CELL ]}'>#{cell_value}</td>"
|
117
|
+
end
|
118
|
+
str += "</tr>"
|
119
|
+
end
|
120
|
+
str += "</tbody></table>"
|
121
|
+
|
122
|
+
return str
|
123
|
+
end
|
124
|
+
|
125
|
+
#
|
126
|
+
# Render a cell using the cell renderer and the given
|
127
|
+
# context data (the row's values).
|
128
|
+
#
|
129
|
+
def render_cell row, col, cols
|
130
|
+
params = {}
|
131
|
+
|
132
|
+
cols.each_with_index do |c, i|
|
133
|
+
params[ c[ :name ] ] = row[ c[ :data_index ] ]
|
134
|
+
end
|
135
|
+
|
136
|
+
content = col[ :cell_renderer ]
|
137
|
+
content = @engine.running_app.obj.embedded_renderer.render content, params
|
138
|
+
|
139
|
+
# renderer = ERB.new( col[ :cell_renderer ] )
|
140
|
+
# content = renderer.result_with_hash( params )
|
141
|
+
|
142
|
+
return content
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
end
|
147
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# Author:: Eric Crane (mailto:eric.crane@mac.com)
|
2
|
+
# Copyright:: Copyright (c) 2024 Eric Crane. All rights reserved.
|
3
|
+
#
|
4
|
+
# A helper class for Web Methods.
|
5
|
+
#
|
6
|
+
|
7
|
+
module Gloo
|
8
|
+
module WebSvr
|
9
|
+
class WebMethod
|
10
|
+
|
11
|
+
GET = 'GET'.freeze
|
12
|
+
POST = 'POST'.freeze
|
13
|
+
PUT = 'PUT'.freeze
|
14
|
+
DELETE = 'DELETE'.freeze
|
15
|
+
PATCH = 'PATCH'.freeze
|
16
|
+
|
17
|
+
#
|
18
|
+
# Is the method a GET?
|
19
|
+
#
|
20
|
+
def self.is_get?( method )
|
21
|
+
return method.upcase == GET
|
22
|
+
end
|
23
|
+
|
24
|
+
#
|
25
|
+
# Is the method a POST?
|
26
|
+
#
|
27
|
+
def self.is_post?( method )
|
28
|
+
return method.upcase == POST
|
29
|
+
end
|
30
|
+
|
31
|
+
#
|
32
|
+
# Is the method a PUT?
|
33
|
+
#
|
34
|
+
def self.is_put?( method )
|
35
|
+
return method.upcase == PUT
|
36
|
+
end
|
37
|
+
|
38
|
+
#
|
39
|
+
# Is the method a PATCH?
|
40
|
+
#
|
41
|
+
def self.is_patch?( method )
|
42
|
+
return method.upcase == PATCH
|
43
|
+
end
|
44
|
+
|
45
|
+
#
|
46
|
+
# Is the method a DELETE?
|
47
|
+
#
|
48
|
+
def self.is_delete?( method )
|
49
|
+
return method.upcase == DELETE
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|