scout-camp 0.1.13 → 0.1.14
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/.vimproject +52 -11
- data/Rakefile +5 -0
- data/VERSION +1 -1
- data/bin/scout-camp +46 -0
- data/doc/terraform.md +188 -0
- data/lib/scout/aws/s3.rb +6 -4
- data/lib/scout/offsite/resource.rb +110 -5
- data/lib/scout/offsite/step.rb +21 -14
- data/lib/scout/offsite/sync.rb +38 -10
- data/lib/scout/offsite.rb +1 -0
- data/lib/scout/render/engine.rb +119 -0
- data/lib/scout/render/helpers.rb +92 -0
- data/lib/scout/render/resource.rb +54 -0
- data/lib/scout/render.rb +3 -0
- data/lib/scout/sinatra/auth.rb +158 -0
- data/lib/scout/sinatra/base/assets.rb +245 -0
- data/lib/scout/sinatra/base/favicon.rb +43 -0
- data/lib/scout/sinatra/base/headers.rb +77 -0
- data/lib/scout/sinatra/base/helpers.rb +14 -0
- data/lib/scout/sinatra/base/parameters.rb +147 -0
- data/lib/scout/sinatra/base/post_processing.rb +18 -0
- data/lib/scout/sinatra/base/session.rb +72 -0
- data/lib/scout/sinatra/base.rb +253 -0
- data/lib/scout/sinatra/entity.rb +259 -0
- data/lib/scout/sinatra/finder.rb +9 -0
- data/lib/scout/sinatra/fragment.rb +275 -0
- data/lib/scout/sinatra/htmx.rb +68 -0
- data/lib/scout/sinatra/knowledge_base.rb +14 -0
- data/lib/scout/sinatra/tool.rb +11 -0
- data/lib/scout/sinatra/workflow.rb +129 -0
- data/lib/scout-camp.rb +1 -1
- data/scout-camp.gemspec +39 -3
- data/scout_commands/find +83 -0
- data/scout_commands/glob +90 -0
- data/share/aws/lambda_function.rb +53 -30
- data/share/terraform/aws/efs_host/data.tf +1 -2
- data/share/terraform/aws/efs_host/main.tf +1 -1
- data/share/terraform/aws/efs_host/variables.tf +5 -1
- data/test/scout/render/test_engine.rb +88 -0
- data/test/scout/render/test_resource.rb +29 -0
- data/test/scout/sinatra/base/test_headers.rb +125 -0
- data/test/scout/sinatra/base/test_parameters.rb +88 -0
- data/test/scout/sinatra/test_base.rb +27 -0
- data/test/scout/sinatra/test_entity.rb +44 -0
- data/test/scout/sinatra/test_render.rb +44 -0
- data/test/scout/sinatra/test_workflow.rb +157 -0
- data/test/test_helper.rb +26 -0
- metadata +103 -2
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
module SinatraScoutAssets
|
|
2
|
+
def self.registered(app)
|
|
3
|
+
app.helpers do
|
|
4
|
+
def reset_js_css
|
|
5
|
+
@recorded_js_files = []
|
|
6
|
+
@recorded_css_files = []
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def recorded_js_files_global
|
|
10
|
+
@recorded_js_files ||= []
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def recorded_css_files_global
|
|
14
|
+
@recorded_css_files ||= []
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def recorded_js_files
|
|
18
|
+
global = recorded_js_files_global
|
|
19
|
+
return global unless @step
|
|
20
|
+
(global + (@step.info[:js_files] || [])).uniq
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def recorded_css_files
|
|
24
|
+
global = recorded_css_files_global
|
|
25
|
+
return global unless @step
|
|
26
|
+
(global + (@step.info[:css_files] || [])).uniq
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def record_js_global(file)
|
|
30
|
+
if Array === file
|
|
31
|
+
recorded_js_files.concat file
|
|
32
|
+
else
|
|
33
|
+
recorded_js_files << file
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def record_css_global(file)
|
|
38
|
+
if Array === file
|
|
39
|
+
recorded_css_files.concat file
|
|
40
|
+
else
|
|
41
|
+
recorded_css_files << file
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def record_js(js_files)
|
|
46
|
+
return record_js_global(js_files) unless @step
|
|
47
|
+
js_files = [js_files] unless Array === js_files
|
|
48
|
+
current_js_files = @step.info[:js_files] || []
|
|
49
|
+
|
|
50
|
+
new_files = js_files - current_js_files
|
|
51
|
+
@step.set_info :js_files, new_files if new_files.any?
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def record_css(css_files)
|
|
55
|
+
return record_css_global(css_files) unless @step
|
|
56
|
+
css_files = [css_files] unless Array === css_files
|
|
57
|
+
current_css_files = @step.info[:css_files] || []
|
|
58
|
+
|
|
59
|
+
new_files = css_files - current_css_files
|
|
60
|
+
@step.set_info :css_files, new_files if new_files.any?
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def link_css(file)
|
|
64
|
+
file << "?_update=reload" if @debug_css
|
|
65
|
+
html_tag('link', nil, :rel => 'stylesheet', :type => 'text/css', :href => file)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def link_js(file)
|
|
69
|
+
html_tag('script', " ", :src => file, :type => 'text/javascript')
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def purge_paths(paths)
|
|
73
|
+
@served_paths ||= []
|
|
74
|
+
new = paths - @served_paths
|
|
75
|
+
@served_paths.concat new
|
|
76
|
+
new
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def serve_css
|
|
80
|
+
md5 = Misc.digest(recorded_css_files * ",")
|
|
81
|
+
filename = ScoutRender.cache_dir["all_css-#{md5}.css"].find
|
|
82
|
+
|
|
83
|
+
paths = recorded_css_files.collect do |file|
|
|
84
|
+
if Open.remote?(file)
|
|
85
|
+
path = file
|
|
86
|
+
else
|
|
87
|
+
path = ScoutRender.find_js(file)
|
|
88
|
+
path = ScoutRender.find_js("public/#{file}") unless path.exists?
|
|
89
|
+
end
|
|
90
|
+
path
|
|
91
|
+
end.uniq
|
|
92
|
+
|
|
93
|
+
paths = purge_paths paths
|
|
94
|
+
|
|
95
|
+
update = _update == :css
|
|
96
|
+
checks = paths.select{|p| Open.mtime(p) }
|
|
97
|
+
|
|
98
|
+
Persist.persist 'all', :text, prefix: 'css', path: filename, other: {files: paths}, check: checks, update: update, no_load: true do
|
|
99
|
+
Log.debug{ "Regenerating CSS Compressed file: #{ filename }" }
|
|
100
|
+
paths.collect do |path|
|
|
101
|
+
TmpFile.with_file do |tmpfile|
|
|
102
|
+
cmd_str = "-i '#{path}' -o '#{tmpfile}'"
|
|
103
|
+
CMD.cmd(:tailwindcss, cmd_str)
|
|
104
|
+
Open.read tmpfile
|
|
105
|
+
end
|
|
106
|
+
end * "\n"
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
res = "<link href='/file/#{File.basename(filename)}' rel='stylesheet' type='text/css'/>"
|
|
110
|
+
|
|
111
|
+
res
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def serve_js
|
|
115
|
+
md5 = Misc.digest(recorded_js_files * ",")
|
|
116
|
+
filename = ScoutRender.cache_dir["all_js-#{md5}.js"].find
|
|
117
|
+
|
|
118
|
+
paths = recorded_js_files.collect do |file|
|
|
119
|
+
if Open.remote?(file)
|
|
120
|
+
path = file
|
|
121
|
+
else
|
|
122
|
+
path = ScoutRender.find_js(file)
|
|
123
|
+
path = ScoutRender.find_js("public/#{file}") unless path.exists?
|
|
124
|
+
end
|
|
125
|
+
path
|
|
126
|
+
end.uniq
|
|
127
|
+
|
|
128
|
+
paths = purge_paths paths
|
|
129
|
+
|
|
130
|
+
update = _update == :js
|
|
131
|
+
|
|
132
|
+
minify = false
|
|
133
|
+
checks = paths.select{|p| Open.mtime(p) }
|
|
134
|
+
|
|
135
|
+
Persist.persist 'all', :text, prefix: 'js', path: filename, other: {files: paths}, check: checks, update: update, no_load: true do
|
|
136
|
+
Log.debug{ "Regenerating JS Compressed file: #{ filename }, from: #{Log.fingerprint paths}" }
|
|
137
|
+
TmpFile.with_file nil, false do |tmp_file|
|
|
138
|
+
Open.write tmp_file do |f|
|
|
139
|
+
paths.each do |path|
|
|
140
|
+
f.write(Open.read(path) + "\n")
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
cmd_str = "esbuild ".dup
|
|
145
|
+
cmd_str << "'#{tmp_file}' "
|
|
146
|
+
cmd_str << "--outfile='#{filename}' "
|
|
147
|
+
cmd_str << "--bundle " if paths.length > 1
|
|
148
|
+
cmd_str << "--minify " if minify
|
|
149
|
+
cmd_str << "--platform='browser' "
|
|
150
|
+
CMD.cmd(:npx, cmd_str)
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
res = "<script src='/file/#{File.basename(filename)}' type='text/javascript' defer></script>"
|
|
155
|
+
|
|
156
|
+
recorded_js_files.clear
|
|
157
|
+
|
|
158
|
+
res
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def mime_file(file, content_type = nil)
|
|
162
|
+
if file.end_with?('.js')
|
|
163
|
+
content_type = 'text/javascript'
|
|
164
|
+
elsif file.end_with?('.css')
|
|
165
|
+
content_type = 'text/css'
|
|
166
|
+
else
|
|
167
|
+
content_type = 'text/html'
|
|
168
|
+
end if content_type.nil?
|
|
169
|
+
|
|
170
|
+
Log.debug "Serving #{file} as #{content_type}"
|
|
171
|
+
content_type content_type if content_type
|
|
172
|
+
send_file(file)
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
# helpers for REST-style responses & params
|
|
177
|
+
# expose method to register a workflow at runtime
|
|
178
|
+
app.get "/plugins/*" do
|
|
179
|
+
splat = consume_parameter(:splat)
|
|
180
|
+
|
|
181
|
+
splat.unshift 'public/plugins'
|
|
182
|
+
|
|
183
|
+
name = splat * "/"
|
|
184
|
+
|
|
185
|
+
file = ScoutRender.find_resource(name)
|
|
186
|
+
status 200
|
|
187
|
+
mime_file file
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
app.get '/(stylesheets|css)/*' do
|
|
191
|
+
splat = consume_parameter(:splat)
|
|
192
|
+
|
|
193
|
+
splat.unshift 'public/css'
|
|
194
|
+
|
|
195
|
+
name = splat * "/"
|
|
196
|
+
|
|
197
|
+
file = ScoutRender.find_resource(name)
|
|
198
|
+
|
|
199
|
+
if file.exists?
|
|
200
|
+
content_type 'text/css', :charset => 'utf-8'
|
|
201
|
+
cache_control :public, :max_age => 360000 if production?
|
|
202
|
+
|
|
203
|
+
mime_file file, false
|
|
204
|
+
else
|
|
205
|
+
splat.shift
|
|
206
|
+
|
|
207
|
+
splat.unshift 'compass'
|
|
208
|
+
|
|
209
|
+
name = splat * "/"
|
|
210
|
+
|
|
211
|
+
content_type 'text/css', :charset => 'utf-8'
|
|
212
|
+
cache_control :public, :max_age => 360000 if production?
|
|
213
|
+
|
|
214
|
+
render_template(name.sub(/\.css/, '.sass'))
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
app.get '/js/*' do
|
|
219
|
+
splat = consume_parameter(:splat)
|
|
220
|
+
|
|
221
|
+
splat.unshift 'public/js'
|
|
222
|
+
|
|
223
|
+
name = splat * "/"
|
|
224
|
+
|
|
225
|
+
file = ScoutRender.find_resource(name)
|
|
226
|
+
content_type 'application/javascript'
|
|
227
|
+
status 200
|
|
228
|
+
mime_file file, false
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
app.get '/file/*' do
|
|
232
|
+
splat = consume_parameter(:splat)
|
|
233
|
+
|
|
234
|
+
name = splat * "/"
|
|
235
|
+
if ScoutRender.cache_dir[name].exists?
|
|
236
|
+
mime_file ScoutRender.cache_dir[name].find
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
splat.unshift 'public'
|
|
240
|
+
name = splat * "/"
|
|
241
|
+
file = ScoutRender.find_resource(name)
|
|
242
|
+
mime_file file
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
module SinatraScoutFavicon
|
|
2
|
+
def self.registered(app)
|
|
3
|
+
app.get '/favicon.ico' do
|
|
4
|
+
content_type 'image/svg+xml'
|
|
5
|
+
cache_control :public, max_age: 86_400 # 1 day
|
|
6
|
+
|
|
7
|
+
<<~SVG
|
|
8
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
9
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="64" height="64" role="img" aria-label="Compass favicon">
|
|
10
|
+
<!-- outer circle -->
|
|
11
|
+
<circle cx="32" cy="32" r="28" fill="none" stroke="currentColor" stroke-width="2" />
|
|
12
|
+
<!-- ticks for N/E/S/W -->
|
|
13
|
+
<line x1="32" y1="4" x2="32" y2="10" fill="none" stroke="currentColor" stroke-width="2" />
|
|
14
|
+
<line x1="60" y1="32" x2="54" y2="32" fill="none" stroke="currentColor" stroke-width="2" />
|
|
15
|
+
<line x1="32" y1="60" x2="32" y2="54" fill="none" stroke="currentColor" stroke-width="2" />
|
|
16
|
+
<line x1="4" y1="32" x2="10" y2="32" fill="none" stroke="currentColor" stroke-width="2" />
|
|
17
|
+
<!-- inner degree markers -->
|
|
18
|
+
<g stroke="currentColor" stroke-width="1">
|
|
19
|
+
<line x1="32" y1="12" x2="32" y2="14"/>
|
|
20
|
+
<line x1="45" y1="19" x2="43" y2="21"/>
|
|
21
|
+
<line x1="52" y1="32" x2="50" y2="32"/>
|
|
22
|
+
<line x1="45" y1="45" x2="43" y2="43"/>
|
|
23
|
+
<line x1="32" y1="52" x2="32" y2="50"/>
|
|
24
|
+
<line x1="19" y1="45" x2="21" y2="43"/>
|
|
25
|
+
<line x1="12" y1="32" x2="14" y2="32"/>
|
|
26
|
+
<line x1="19" y1="19" x2="21" y2="21"/>
|
|
27
|
+
</g>
|
|
28
|
+
<!-- compass needle (line drawing) -->
|
|
29
|
+
<g stroke="currentColor" stroke-width="1.8" stroke-linejoin="round" stroke-linecap="round" fill="none">
|
|
30
|
+
<!-- main spine -->
|
|
31
|
+
<line x1="32" y1="32" x2="42" y2="12"/>
|
|
32
|
+
<line x1="32" y1="32" x2="22" y2="52"/>
|
|
33
|
+
<!-- needle outlines (simple triangular tips) -->
|
|
34
|
+
<path d="M42 12 L36 20 L32 18 Z" fill="none" stroke="currentColor" stroke-width="1.6"/>
|
|
35
|
+
<path d="M22 52 L28 44 L32 46 Z" fill="none" stroke="currentColor" stroke-width="1.6"/>
|
|
36
|
+
</g>
|
|
37
|
+
<!-- center hub -->
|
|
38
|
+
<circle cx="32" cy="32" r="2" fill="currentColor" />
|
|
39
|
+
</svg>
|
|
40
|
+
SVG
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
module SinatraScoutHeaders
|
|
2
|
+
def self.registered(app)
|
|
3
|
+
app.helpers do
|
|
4
|
+
def environment
|
|
5
|
+
settings.environment
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def production?
|
|
9
|
+
environment == :production
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def development?
|
|
13
|
+
environment == :development
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def script_name
|
|
17
|
+
request.script_name ||= request.env["HTTP_SCRIPT_NAME"]
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def xhr?
|
|
21
|
+
request.xhr?
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def ajax?
|
|
25
|
+
request.xhr?
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def request_method
|
|
29
|
+
request.env["REQUEST_METHOD"]
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def post?
|
|
33
|
+
request_method.to_s.downcase == 'post'
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def clean_uri(uri)
|
|
37
|
+
return nil if uri.nil?
|
|
38
|
+
remove_GET_param(uri, ["_update", "_"])
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def original_uri
|
|
42
|
+
clean_uri(request.env["REQUEST_URI"])
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def post_uri
|
|
46
|
+
new_params = {}
|
|
47
|
+
params.each do |k,v|
|
|
48
|
+
if m = k.match(/(.*)__param_file/)
|
|
49
|
+
new_params[m[1]] = v['filename']
|
|
50
|
+
else
|
|
51
|
+
new_params[k] = v
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
hash = Misc.digest(new_params)
|
|
55
|
+
params[:_layout]
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def path_info
|
|
59
|
+
@path_info ||= request.env["PATH_INFO"]
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def query
|
|
63
|
+
@query ||= request.env["QUERY_STRING"]
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def fullpath
|
|
67
|
+
@fullpath ||= (query && ! query.empty?) ? clean_uri(path_info + "?" + query) : path_info
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
alias url fullpath
|
|
71
|
+
|
|
72
|
+
def script_name
|
|
73
|
+
@script_name ||= request.script_name = request.env["HTTP_SCRIPT_NAME"]
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
require_relative 'post_processing'
|
|
2
|
+
module SinatraScoutHelpers
|
|
3
|
+
def self.registered(app)
|
|
4
|
+
|
|
5
|
+
app.helpers do
|
|
6
|
+
def format_name(name)
|
|
7
|
+
parts = name.split("_")
|
|
8
|
+
hash = parts.pop
|
|
9
|
+
clean_name = parts * "_"
|
|
10
|
+
"<span class='name' jobname='#{ name }'>#{ clean_name }</span> <span class='hash'>#{ hash }</span>"
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
module SinatraScoutParameters
|
|
2
|
+
def self.registered(app)
|
|
3
|
+
app.set :common_parameters, []
|
|
4
|
+
|
|
5
|
+
app.define_singleton_method(:register_common_parameter) do |name,type=:string,default=nil,&block|
|
|
6
|
+
settings.common_parameters << name
|
|
7
|
+
app.helpers do
|
|
8
|
+
attr_accessor name
|
|
9
|
+
|
|
10
|
+
define_method(name) do
|
|
11
|
+
value = self.instance_variable_get(:"@#{name}")
|
|
12
|
+
return value unless value.nil?
|
|
13
|
+
value = consume_parameter(name)
|
|
14
|
+
if value.nil?
|
|
15
|
+
value = if default
|
|
16
|
+
default
|
|
17
|
+
elsif block
|
|
18
|
+
self.instance_eval &block
|
|
19
|
+
else
|
|
20
|
+
nil
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
value = case type
|
|
25
|
+
when :string
|
|
26
|
+
value.to_s if value
|
|
27
|
+
when :symbol
|
|
28
|
+
if String === value
|
|
29
|
+
value.to_sym
|
|
30
|
+
else
|
|
31
|
+
value
|
|
32
|
+
end
|
|
33
|
+
when :integer
|
|
34
|
+
value.to_i
|
|
35
|
+
when :float
|
|
36
|
+
value.to_f
|
|
37
|
+
when :boolean
|
|
38
|
+
value.to_s.downcase == "true" unless value.nil?
|
|
39
|
+
when :escaped
|
|
40
|
+
restore_element(value) if value
|
|
41
|
+
when :array
|
|
42
|
+
value = case value
|
|
43
|
+
when Array
|
|
44
|
+
value
|
|
45
|
+
when String
|
|
46
|
+
value.split(",")
|
|
47
|
+
else
|
|
48
|
+
value
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
self.instance_variable_set(:"@#{name}", value)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
app.helpers do
|
|
58
|
+
def clean_element(elem)
|
|
59
|
+
elem.to_s.gsub('&', '--AND--').
|
|
60
|
+
gsub('/', '-..-').
|
|
61
|
+
gsub("|", '-...-').
|
|
62
|
+
gsub('%', 'o-o').
|
|
63
|
+
gsub('[','(.-(').
|
|
64
|
+
gsub(']',').-)')
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def restore_element(elem)
|
|
68
|
+
CGI.unescape(CGI.unescape(
|
|
69
|
+
elem.gsub('--AND--', '&').
|
|
70
|
+
gsub('-..-', '/').
|
|
71
|
+
gsub('-...-', '|').
|
|
72
|
+
gsub('o-o', '%').
|
|
73
|
+
gsub('(.-(','[').
|
|
74
|
+
gsub(').-)',']')
|
|
75
|
+
))
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def consume_parameter(name, source = params)
|
|
79
|
+
return nil if source.nil?
|
|
80
|
+
val = IndiferentHash.process_options source, name
|
|
81
|
+
val = nil if val == ''
|
|
82
|
+
val
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def clean_params
|
|
86
|
+
@clean_params ||= begin
|
|
87
|
+
params = IndiferentHash.setup(self.params)
|
|
88
|
+
params.keys.each do |param|
|
|
89
|
+
if param =~ /(.*)_checkbox_false$/
|
|
90
|
+
params[$1] = false if params[$1].nil?
|
|
91
|
+
params.delete param
|
|
92
|
+
elsif param =~ /(.*)_upload_file$/
|
|
93
|
+
file = params[param]
|
|
94
|
+
params[$1] = file['tempfile'].read
|
|
95
|
+
params[$1 + "_upload_filename"] = file['filename']
|
|
96
|
+
elsif param.to_s.start_with? '_'
|
|
97
|
+
params.delete param
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
params
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def process_common_parameters
|
|
105
|
+
settings.common_parameters.each{|name,*_| self.send(name) }
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def form(**kwgars, &block)
|
|
109
|
+
inputs = []
|
|
110
|
+
input_types = {}
|
|
111
|
+
input_descriptions = {}
|
|
112
|
+
input_defaults = {}
|
|
113
|
+
input_options = {}
|
|
114
|
+
|
|
115
|
+
self.define_singleton_method :input do |name, type=nil, description=nil, default=nil, options=nil|
|
|
116
|
+
inputs << name
|
|
117
|
+
input_types[name] = type
|
|
118
|
+
input_descriptions[name] = description
|
|
119
|
+
input_defaults[name] = default
|
|
120
|
+
input_options[name] = options
|
|
121
|
+
end
|
|
122
|
+
self.instance_exec &block
|
|
123
|
+
|
|
124
|
+
self.singleton_class.remove_method(:input)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
render_partial 'partial/form', kwgars.merge( inputs: inputs, types: input_types, descriptions: input_descriptions, defaults: input_defaults, options: input_options)
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
app.register_common_parameter(:splat, :array)
|
|
132
|
+
app.register_common_parameter(:_layout, :boolean) do ! ajax? end
|
|
133
|
+
app.register_common_parameter(:_format, :symbol) do :html end
|
|
134
|
+
app.register_common_parameter(:_update, :symbol) do
|
|
135
|
+
if development? && ! _step
|
|
136
|
+
:development
|
|
137
|
+
elsif request_method != 'GET'
|
|
138
|
+
request_method
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
app.register_common_parameter(:_cache_type, :symbol, :asynchronous)
|
|
142
|
+
app.register_common_parameter(:_debug_js, :boolean)
|
|
143
|
+
app.register_common_parameter(:_debug_css, :boolean)
|
|
144
|
+
app.register_common_parameter(:_step, :string)
|
|
145
|
+
app.register_common_parameter(:_)
|
|
146
|
+
end
|
|
147
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module SinatraScoutPostProcessing
|
|
2
|
+
def self.registered(app)
|
|
3
|
+
app.set :post_processing_blocks, []
|
|
4
|
+
|
|
5
|
+
app.define_singleton_method(:register_post_processing) do |&block|
|
|
6
|
+
settings.post_processing_blocks << block
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
app.helpers do
|
|
10
|
+
def post_processing(step)
|
|
11
|
+
return unless settings.post_processing_blocks
|
|
12
|
+
settings.post_processing_blocks.each do |block|
|
|
13
|
+
self.instance_exec step, &block
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
require "sinatra"
|
|
2
|
+
|
|
3
|
+
module SinatraScoutSession
|
|
4
|
+
def self.registered(app)
|
|
5
|
+
secret = Scout::Config.get :secret, :sinatra_session, :sinatra, :session, env:"SESSION_SECRET", default: "scout_and_rbbt_super_secret"
|
|
6
|
+
|
|
7
|
+
app.configure do
|
|
8
|
+
app.enable :sessions
|
|
9
|
+
app.set :sessions, true
|
|
10
|
+
app.set :session_secret, secret
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
app.use Rack::Session::Cookie, secret: secret
|
|
14
|
+
|
|
15
|
+
app.get '/debug_session' do
|
|
16
|
+
"Session contents: #{session.inspect}"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
app.post_get '/preference/:key' do
|
|
20
|
+
key = consume_parameter :key
|
|
21
|
+
value = consume_parameter :value
|
|
22
|
+
|
|
23
|
+
if value.nil?
|
|
24
|
+
consume_parameter :key
|
|
25
|
+
case _format
|
|
26
|
+
when :json
|
|
27
|
+
content_type 'application/json'
|
|
28
|
+
get_preference(key).to_json
|
|
29
|
+
else
|
|
30
|
+
get_preference(key)
|
|
31
|
+
end
|
|
32
|
+
else
|
|
33
|
+
|
|
34
|
+
case _format
|
|
35
|
+
when :json
|
|
36
|
+
value = JSON.parse(value)
|
|
37
|
+
else
|
|
38
|
+
record_preference(key, value)
|
|
39
|
+
end
|
|
40
|
+
halt 200
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
app.helpers do
|
|
45
|
+
|
|
46
|
+
def csrf_token
|
|
47
|
+
session[:csrf] ||= SecureRandom.hex(16)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def preferences
|
|
51
|
+
session['preferences'] ||= {}
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def record_preference(key, value)
|
|
55
|
+
preferences[key] = value
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def get_preference(key)
|
|
59
|
+
preferences[key]
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def preference_url(key, value=nil, params = {})
|
|
63
|
+
url = "/preference/#{key}"
|
|
64
|
+
if value
|
|
65
|
+
add_GET_params("/preference/#{key}", params.merge(value: value))
|
|
66
|
+
else
|
|
67
|
+
add_GET_params("/preference/#{key}", params)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|