gloo 3.1.1 → 3.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/VERSION +1 -1
- data/lib/VERSION_NOTES +6 -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
|