wabur 0.4.0d1 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +20 -66
- data/bin/wabur +48 -11
- data/export/assets/css/wab.css +2 -0
- data/export/assets/css/wab.css.map +7 -0
- data/export/assets/fonts/wabfont/README +18 -0
- data/export/assets/fonts/wabfont/fonts/WAB.eot +0 -0
- data/export/assets/fonts/wabfont/fonts/WAB.svg +25 -0
- data/export/assets/fonts/wabfont/fonts/WAB.ttf +0 -0
- data/export/assets/fonts/wabfont/fonts/WAB.woff +0 -0
- data/export/assets/fonts/wabfont/selection.json +460 -0
- data/export/assets/fonts/wabfont/style.css +74 -0
- data/export/assets/js/transpile.js +8 -0
- data/export/assets/js/ui.js +377 -0
- data/export/assets/js/vendor/plugin-babel/babel-helpers.js +558 -0
- data/export/assets/js/vendor/plugin-babel/babel-helpers/asyncGenerator.js +112 -0
- data/export/assets/js/vendor/plugin-babel/babel-helpers/asyncGeneratorDelegate.js +51 -0
- data/export/assets/js/vendor/plugin-babel/babel-helpers/asyncIterator.js +14 -0
- data/export/assets/js/vendor/plugin-babel/babel-helpers/asyncToGenerator.js +28 -0
- data/export/assets/js/vendor/plugin-babel/babel-helpers/classCallCheck.js +5 -0
- data/export/assets/js/vendor/plugin-babel/babel-helpers/createClass.js +17 -0
- data/export/assets/js/vendor/plugin-babel/babel-helpers/defaults.js +14 -0
- data/export/assets/js/vendor/plugin-babel/babel-helpers/defineEnumerableProperties.js +10 -0
- data/export/assets/js/vendor/plugin-babel/babel-helpers/defineProperty.js +14 -0
- data/export/assets/js/vendor/plugin-babel/babel-helpers/extends.js +13 -0
- data/export/assets/js/vendor/plugin-babel/babel-helpers/get.js +24 -0
- data/export/assets/js/vendor/plugin-babel/babel-helpers/inherits.js +15 -0
- data/export/assets/js/vendor/plugin-babel/babel-helpers/instanceof.js +7 -0
- data/export/assets/js/vendor/plugin-babel/babel-helpers/interopRequireDefault.js +5 -0
- data/export/assets/js/vendor/plugin-babel/babel-helpers/interopRequireWildcard.js +16 -0
- data/export/assets/js/vendor/plugin-babel/babel-helpers/jsx.js +42 -0
- data/export/assets/js/vendor/plugin-babel/babel-helpers/newArrowCheck.js +5 -0
- data/export/assets/js/vendor/plugin-babel/babel-helpers/objectDestructuringEmpty.js +3 -0
- data/export/assets/js/vendor/plugin-babel/babel-helpers/objectWithoutProperties.js +11 -0
- data/export/assets/js/vendor/plugin-babel/babel-helpers/possibleConstructorReturn.js +7 -0
- data/export/assets/js/vendor/plugin-babel/babel-helpers/selfGlobal.js +1 -0
- data/export/assets/js/vendor/plugin-babel/babel-helpers/set.js +21 -0
- data/export/assets/js/vendor/plugin-babel/babel-helpers/slicedToArray.js +37 -0
- data/export/assets/js/vendor/plugin-babel/babel-helpers/slicedToArrayLoose.js +17 -0
- data/export/assets/js/vendor/plugin-babel/babel-helpers/taggedTemplateLiteral.js +7 -0
- data/export/assets/js/vendor/plugin-babel/babel-helpers/taggedTemplateLiteralLoose.js +4 -0
- data/export/assets/js/vendor/plugin-babel/babel-helpers/temporalRef.js +7 -0
- data/export/assets/js/vendor/plugin-babel/babel-helpers/temporalUndefined.js +1 -0
- data/export/assets/js/vendor/plugin-babel/babel-helpers/toArray.js +3 -0
- data/export/assets/js/vendor/plugin-babel/babel-helpers/toConsumableArray.js +9 -0
- data/export/assets/js/vendor/plugin-babel/babel-helpers/typeof.js +5 -0
- data/export/assets/js/vendor/plugin-babel/plugin-babel.js +222 -0
- data/export/assets/js/vendor/plugin-babel/regenerator-runtime.js +685 -0
- data/export/assets/js/vendor/plugin-babel/systemjs-babel-browser.js +1 -0
- data/export/assets/js/vendor/plugin-babel/systemjs-babel-node.js +55086 -0
- data/export/assets/js/vendor/systemjs/system-production.js +4 -0
- data/export/assets/js/vendor/systemjs/system-production.js.map +1 -0
- data/export/assets/js/vendor/systemjs/system-production.src.js +1711 -0
- data/export/assets/js/vendor/systemjs/system-production.src.js.map +1 -0
- data/export/assets/js/vendor/systemjs/system.js +4 -0
- data/export/assets/js/vendor/systemjs/system.js.map +1 -0
- data/export/assets/js/vendor/systemjs/system.src.js +4000 -0
- data/export/assets/js/vendor/systemjs/system.src.js.map +1 -0
- data/export/assets/js/wab.js +109 -0
- data/export/index.html +41 -0
- data/lib/wab.rb +13 -0
- data/lib/wab/controller.rb +2 -2
- data/lib/wab/errors.rb +12 -0
- data/lib/wab/impl.rb +2 -0
- data/lib/wab/impl/configuration.rb +24 -6
- data/lib/wab/impl/export_proxy.rb +39 -0
- data/lib/wab/impl/exprs/regex.rb +1 -1
- data/lib/wab/impl/handler.rb +14 -14
- data/lib/wab/impl/init.rb +108 -0
- data/lib/wab/impl/model.rb +4 -3
- data/lib/wab/impl/shell.rb +14 -4
- data/lib/wab/impl/templates/opo-rub.conf.template +253 -0
- data/lib/wab/impl/templates/opo.conf.template +224 -0
- data/lib/wab/impl/templates/spawn.rb.template +42 -0
- data/lib/wab/impl/templates/ui_controller.rb.template +12 -0
- data/lib/wab/impl/templates/wabur.conf.template +40 -0
- data/lib/wab/ui.rb +19 -0
- data/lib/wab/ui/create.rb +26 -0
- data/lib/wab/ui/display.rb +34 -0
- data/lib/wab/ui/flow.rb +54 -0
- data/lib/wab/ui/list.rb +59 -0
- data/lib/wab/ui/multi_flow.rb +23 -0
- data/lib/wab/ui/rest_flow.rb +89 -0
- data/lib/wab/ui/update.rb +27 -0
- data/lib/wab/ui/view.rb +62 -0
- data/lib/wab/utils.rb +4 -4
- data/lib/wab/version.rb +1 -1
- data/pages/Architecture.md +104 -1
- data/test/test_configuration.rb +1 -1
- data/test/test_impl.rb +1 -0
- data/test/test_init.rb +33 -0
- metadata +94 -7
- data/pages/Plan.md +0 -27
@@ -0,0 +1,42 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
$VERBOSE = true
|
5
|
+
|
6
|
+
$: << __dir__
|
7
|
+
while (index = ARGV.index('-I'))
|
8
|
+
_, path = ARGV.slice!(index, 2)
|
9
|
+
$: << path
|
10
|
+
end
|
11
|
+
|
12
|
+
require 'optparse'
|
13
|
+
require 'wab'
|
14
|
+
require 'wab/io'
|
15
|
+
|
16
|
+
# This app is expected to be spawned from a WAB runner. This demonstrates one
|
17
|
+
# possible mode for running WAB applications. It is the least performant of
|
18
|
+
# the WAB run options.
|
19
|
+
|
20
|
+
$verbose = false
|
21
|
+
$thread_count = 1
|
22
|
+
$opts = OptionParser.new("Usage: sample [options]
|
23
|
+
|
24
|
+
Acts as a remote Controller in a WAB deployment. Input is from stdin and output
|
25
|
+
is on stdout. If verbosity is turned on it is sent to stderr.
|
26
|
+
")
|
27
|
+
$opts.on('-v', 'verbose output on stderr') { $verbose = true }
|
28
|
+
$opts.on('-t', '--thread-count Integer', Integer, 'thread count') { |t| $thread_count = t }
|
29
|
+
$opts.on('-h', '--help', 'show this page') { $stderr.puts $opts.help; Process.exit!(0) }
|
30
|
+
|
31
|
+
$opts.parse(ARGV)
|
32
|
+
|
33
|
+
shell = WAB::IO::Shell.new($thread_count, 'kind', 1)
|
34
|
+
shell.logger.level = Logger::INFO if $verbose
|
35
|
+
|
36
|
+
shell.register_controller('ui', UIController.new(shell))%{controllers}
|
37
|
+
|
38
|
+
begin
|
39
|
+
shell.start
|
40
|
+
rescue Interrupt
|
41
|
+
# ignore
|
42
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# wabur.conf
|
2
|
+
|
3
|
+
# Configuration file for the Pure Ruby WAB Runner.
|
4
|
+
|
5
|
+
# The directory to store the runner data (relative to source directory).
|
6
|
+
store.dir = wabur/data
|
7
|
+
|
8
|
+
# URL path prefix for the data records.
|
9
|
+
path_prefix = /v1
|
10
|
+
|
11
|
+
# Field to expect the type, class, or kind of record in the stored JSON.
|
12
|
+
type_key = kind
|
13
|
+
|
14
|
+
# HTTP site directory.
|
15
|
+
http.dir = site
|
16
|
+
|
17
|
+
# HTTP port to listen on.
|
18
|
+
http.port = 6363
|
19
|
+
|
20
|
+
# Logging verbosity. Can be ERROR, WARN, INFO, or DEBUG.
|
21
|
+
verbosity = WARN
|
22
|
+
|
23
|
+
# The Ruby requires. Generally what ever class in the lib directory that
|
24
|
+
# should be imported.
|
25
|
+
require = ui_controller
|
26
|
+
|
27
|
+
# If export_proxy is true the wab default index.html, CSS, JavaScript, and
|
28
|
+
# fonts are loaded from the gem's export directory is they are not found in
|
29
|
+
# the site directory.
|
30
|
+
export_proxy = true
|
31
|
+
|
32
|
+
# The number of spaces to indent the JSON written to disk by the model and the
|
33
|
+
# JSON sent as a response to View requests.
|
34
|
+
indent = 0
|
35
|
+
|
36
|
+
# Handlers for each type of record and for the UI shich are Ruby generated UI
|
37
|
+
# configuration records.
|
38
|
+
handler.0.type = ui
|
39
|
+
handler.0.handler = UIController
|
40
|
+
%{handlers}
|
data/lib/wab/ui.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
|
2
|
+
require 'wab'
|
3
|
+
|
4
|
+
module WAB
|
5
|
+
# Web Application Builder reference implemenation UI.
|
6
|
+
module UI
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
require 'wab/ui/display'
|
11
|
+
require 'wab/ui/flow'
|
12
|
+
require 'wab/ui/multi_flow'
|
13
|
+
|
14
|
+
# These are the classes needed for the REST displays/flow.
|
15
|
+
require 'wab/ui/rest_flow'
|
16
|
+
require 'wab/ui/list'
|
17
|
+
require 'wab/ui/view'
|
18
|
+
require 'wab/ui/create'
|
19
|
+
require 'wab/ui/update'
|
@@ -0,0 +1,26 @@
|
|
1
|
+
|
2
|
+
module WAB
|
3
|
+
module UI
|
4
|
+
|
5
|
+
# An object create display.
|
6
|
+
class Create < View
|
7
|
+
|
8
|
+
# Create an instance that will generate the HTML for a display.
|
9
|
+
def initialize(kind, id, template, transitions)
|
10
|
+
super(kind, id, template, transitions, 'ui.Create')
|
11
|
+
end
|
12
|
+
|
13
|
+
# Returns the HTML for a display.
|
14
|
+
def html
|
15
|
+
html = %{<div class="obj-form-frame"><table class="obj-form">}
|
16
|
+
html = append_fields(html, @name, template, false)
|
17
|
+
html << '</table>'
|
18
|
+
html << %{<div class="btn" id="#{@name}.save_button"><span>Save</span></div>}
|
19
|
+
html << %{<div class="btn" style="float:right;" id="#{@name}.cancel_button"><span>Cancel</span></div>}
|
20
|
+
html << '</div>'
|
21
|
+
end
|
22
|
+
|
23
|
+
end # Create
|
24
|
+
end # UI
|
25
|
+
end # WAB
|
26
|
+
|
@@ -0,0 +1,34 @@
|
|
1
|
+
|
2
|
+
module WAB
|
3
|
+
module UI
|
4
|
+
|
5
|
+
# Base class for other displays.
|
6
|
+
class Display
|
7
|
+
|
8
|
+
attr_reader :name
|
9
|
+
attr_reader :kind
|
10
|
+
attr_accessor :template
|
11
|
+
attr_accessor :display_class
|
12
|
+
attr_accessor :transitions
|
13
|
+
|
14
|
+
def initialize(kind, name, template, transitions, display_class)
|
15
|
+
@kind = kind
|
16
|
+
@name = name
|
17
|
+
@template = template
|
18
|
+
@display_class = display_class
|
19
|
+
@transitions = transitions
|
20
|
+
end
|
21
|
+
|
22
|
+
def spec
|
23
|
+
{
|
24
|
+
name: @name,
|
25
|
+
kind: @kind,
|
26
|
+
display_class: @display_class,
|
27
|
+
transitions: @transitions,
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
end # Display
|
32
|
+
end # UI
|
33
|
+
end # WAB
|
34
|
+
|
data/lib/wab/ui/flow.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
|
2
|
+
module WAB
|
3
|
+
module UI
|
4
|
+
|
5
|
+
# A controller that provides a description of the UI for the WAB UI
|
6
|
+
# reference implementation.
|
7
|
+
class Flow < WAB::Controller
|
8
|
+
|
9
|
+
attr_accessor :entry
|
10
|
+
attr_reader :displays
|
11
|
+
|
12
|
+
def initialize(shell)
|
13
|
+
super
|
14
|
+
@displays = {}
|
15
|
+
end
|
16
|
+
|
17
|
+
# Adds a display to the flow.
|
18
|
+
def add_display(display, entry=false)
|
19
|
+
name = display.name
|
20
|
+
raise DuplicateError.new(name) if @displays.has_key?(name)
|
21
|
+
@displays[name] = display
|
22
|
+
@entry = name if entry
|
23
|
+
end
|
24
|
+
|
25
|
+
def get_display(name)
|
26
|
+
@displays[name]
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns a description of the UI to be used. If a display name is
|
30
|
+
# includd in the path thenn just that display description is returned.
|
31
|
+
#
|
32
|
+
# path:: array of tokens in the path.
|
33
|
+
def read(path, _query)
|
34
|
+
results = []
|
35
|
+
if @shell.path_pos + 2 == path.length
|
36
|
+
# Return the description of the named display.
|
37
|
+
name = path[@shell.path_pos + 1]
|
38
|
+
display = get_display(name)
|
39
|
+
display[:entry] = true if !display.nil? && display.name == @entry
|
40
|
+
results << {id: name, data: display.spec} unless display.nil?
|
41
|
+
else
|
42
|
+
@displays.each_value { |display|
|
43
|
+
spec = display.spec
|
44
|
+
spec[:entry] = true if display.name == @entry
|
45
|
+
results << spec
|
46
|
+
}
|
47
|
+
end
|
48
|
+
@shell.data({code: 0, results: results})
|
49
|
+
end
|
50
|
+
|
51
|
+
end # Flow
|
52
|
+
end # UI
|
53
|
+
end # WAB
|
54
|
+
|
data/lib/wab/ui/list.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
|
2
|
+
module WAB
|
3
|
+
module UI
|
4
|
+
|
5
|
+
# Represents a list display.
|
6
|
+
class List < Display
|
7
|
+
|
8
|
+
attr_accessor :list_paths
|
9
|
+
|
10
|
+
def initialize(kind, id, template, list_paths, transitions)
|
11
|
+
super(kind, id, template, transitions, 'ui.List')
|
12
|
+
@list_paths = list_paths
|
13
|
+
end
|
14
|
+
|
15
|
+
def spec
|
16
|
+
ui_spec = super
|
17
|
+
ui_spec[:table] = html_table
|
18
|
+
ui_spec[:row] = html_row
|
19
|
+
ui_spec
|
20
|
+
end
|
21
|
+
|
22
|
+
# Returns an HTML string to be used as the table of a list of
|
23
|
+
# objects. The table must have an +id+ attribute value of the +name+
|
24
|
+
# argument. Generally the column header should include the list_paths or
|
25
|
+
# more friendly alternatives. If a create button is desired then an
|
26
|
+
# element with the name joined with '.create_button' should be the +id+ of
|
27
|
+
# the element.
|
28
|
+
def html_table
|
29
|
+
html = %{<div class="table-wrapper"><h2 style="float: left; margin-top: 2px">#{@kind} List</h2><div class="btn" style="float: left" id="#{@name}.create_button"><span>Create</span></div><table class="obj-list-table" id="#{@name}.table"><tr>}
|
30
|
+
# The column headers.
|
31
|
+
@list_paths.map { |path| html << "<th>#{path.capitalize}</th>" }
|
32
|
+
# Add the view, edit, and delete buttons header.
|
33
|
+
html << %{<th colspan="3">Actions</th>}
|
34
|
+
html << %{</tr></table></div>}
|
35
|
+
end
|
36
|
+
|
37
|
+
# Returns an HTML string to be used as a row in a table of a list of
|
38
|
+
# objects. Each column element should include the list_paths identifier
|
39
|
+
# as a +path+ element attribute.
|
40
|
+
#
|
41
|
+
# Each row can contain the buttons +view_button+, +edit_button+, and
|
42
|
+
# +delete_button+. These will be used to set up the transitions.
|
43
|
+
def html_row
|
44
|
+
html = '<tr>'
|
45
|
+
@list_paths.map { |path| html << %{<td class="obj-list" path="#{path}"></td>} }
|
46
|
+
buttons = [
|
47
|
+
{ title: 'View', icon: 'icon icon-eye', cn: 'actions' },
|
48
|
+
{ title: 'Edit', icon: 'icon icon-pencil', cn: 'actions' },
|
49
|
+
{ title: 'Delete', icon: 'icon icon-trash-o', cn: 'actions delete' }
|
50
|
+
].map { |spec|
|
51
|
+
html << %{<td class="#{spec[:cn]}"><span class="#{spec[:icon]}" title="#{spec[:title]}"></span></td>}
|
52
|
+
}
|
53
|
+
html << '</tr>'
|
54
|
+
end
|
55
|
+
|
56
|
+
end # List
|
57
|
+
end # UI
|
58
|
+
end # WAB
|
59
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
|
2
|
+
module WAB
|
3
|
+
module UI
|
4
|
+
|
5
|
+
# A Flow controller that merges multiple flows into one single flow.
|
6
|
+
class MultiFlow < Flow
|
7
|
+
|
8
|
+
# Create a new instance that can be used to merge multiple flows into
|
9
|
+
# one single flow.
|
10
|
+
#
|
11
|
+
# shell:: shell containing the instancec
|
12
|
+
def initialize(shell)
|
13
|
+
super(shell)
|
14
|
+
end
|
15
|
+
|
16
|
+
def add_flow(flow)
|
17
|
+
flow.displays.each_pair { |name,display| @displays[name] = display }
|
18
|
+
@entry = flow.entry if @entry.nil?
|
19
|
+
end
|
20
|
+
|
21
|
+
end # MultiFlow
|
22
|
+
end # UI
|
23
|
+
end # WAB
|
@@ -0,0 +1,89 @@
|
|
1
|
+
|
2
|
+
module WAB
|
3
|
+
module UI
|
4
|
+
|
5
|
+
# A Flow controller that builds up a set of displays and provides those display descriptions
|
6
|
+
# when a read is called. The REST UI is built based on the template and
|
7
|
+
# list_paths provided in the initializer.
|
8
|
+
#
|
9
|
+
# The display can be modified or subclassing by changing the View, Create,
|
10
|
+
# and Update classes.
|
11
|
+
class RestFlow < Flow
|
12
|
+
|
13
|
+
# Creae a new instance based on the record template and path for the
|
14
|
+
# list display.
|
15
|
+
#
|
16
|
+
# shell:: shell containing the instancec
|
17
|
+
# template:: and example object with default values
|
18
|
+
# list_paths:: paths to values for the list display
|
19
|
+
def initialize(shell, template, list_paths)
|
20
|
+
super(shell)
|
21
|
+
kind = template[:kind]
|
22
|
+
raise WAB::ParseError.new('kind field missing from object template') if kind.nil?
|
23
|
+
add_list(kind, template, list_paths)
|
24
|
+
add_view(kind, template)
|
25
|
+
add_create(kind, template)
|
26
|
+
add_update(kind, template)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Add a listdisplay to the spec delivered to the UI.
|
30
|
+
#
|
31
|
+
# kind:: the type of record to create the list for
|
32
|
+
# template:: and example object with default values
|
33
|
+
# list_paths:: paths to values for the list display
|
34
|
+
def add_list(kind, template, list_paths)
|
35
|
+
id = "#{kind}.list"
|
36
|
+
transitions = {
|
37
|
+
create: "#{kind}.create",
|
38
|
+
view: "#{kind}.view",
|
39
|
+
edit: "#{kind}.update",
|
40
|
+
delete: id,
|
41
|
+
}
|
42
|
+
add_display(List.new(kind, id, template, list_paths, transitions), true)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Adds an object view specification.
|
46
|
+
#
|
47
|
+
# kind:: the type of record to create the list for
|
48
|
+
# template:: and example object with default values
|
49
|
+
def add_view(kind, template)
|
50
|
+
id = "#{kind}.view"
|
51
|
+
transitions = {
|
52
|
+
edit: "#{kind}.update",
|
53
|
+
list: "#{kind}.list",
|
54
|
+
delete: "#{kind}.list",
|
55
|
+
}
|
56
|
+
add_display(View.new(kind, id, template, transitions))
|
57
|
+
end
|
58
|
+
|
59
|
+
# Adds an object creation specification.
|
60
|
+
#
|
61
|
+
# kind:: the type of record to create the list for
|
62
|
+
# template:: and example object with default values
|
63
|
+
def add_create(kind, template)
|
64
|
+
id = "#{kind}.create"
|
65
|
+
transitions = {
|
66
|
+
save: "#{kind}.view",
|
67
|
+
cancel: "#{kind}.list",
|
68
|
+
}
|
69
|
+
add_display(Create.new(kind, id, template, transitions))
|
70
|
+
end
|
71
|
+
|
72
|
+
# Adds an object update specification.
|
73
|
+
#
|
74
|
+
# kind:: the type of record to create the list for
|
75
|
+
# template:: and example object with default values
|
76
|
+
def add_update(kind, template)
|
77
|
+
id = "#{kind}.update"
|
78
|
+
transitions = {
|
79
|
+
save: "#{kind}.view",
|
80
|
+
cancel: "#{kind}.view",
|
81
|
+
list: "#{kind}.list",
|
82
|
+
delete: "#{kind}.list",
|
83
|
+
}
|
84
|
+
add_display(Update.new(kind, id, template, transitions))
|
85
|
+
end
|
86
|
+
|
87
|
+
end # RestFlow
|
88
|
+
end # UI
|
89
|
+
end # WAB
|
@@ -0,0 +1,27 @@
|
|
1
|
+
|
2
|
+
module WAB
|
3
|
+
module UI
|
4
|
+
|
5
|
+
# An object update display.
|
6
|
+
class Update < View
|
7
|
+
|
8
|
+
# TBD pass in fields for the update
|
9
|
+
def initialize(kind, id, template, transitions)
|
10
|
+
super(kind, id, template, transitions, 'ui.Update')
|
11
|
+
end
|
12
|
+
|
13
|
+
def html
|
14
|
+
html = %{<div class="obj-form-frame"><table class="obj-form">}
|
15
|
+
html = append_fields(html, @name, template, false)
|
16
|
+
html << '</table>'
|
17
|
+
html << %{<div class="btn" id="#{@name}.save_button"><span>Save</span></div>}
|
18
|
+
html << %{<div class="btn" id="#{@name}.cancel_button"><span>Cancel</span></div>}
|
19
|
+
html << %{<div class="btn" id="#{@name}.list_button"><span>List</span></div>}
|
20
|
+
html << %{<div class="btn delete-btn" style="float:right;" id="#{@name}.delete_button"><span>Delete</span></div>}
|
21
|
+
html << '</div>'
|
22
|
+
end
|
23
|
+
|
24
|
+
end # Update
|
25
|
+
end # UI
|
26
|
+
end # WAB
|
27
|
+
|
data/lib/wab/ui/view.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
|
2
|
+
module WAB
|
3
|
+
module UI
|
4
|
+
|
5
|
+
# An object view display.
|
6
|
+
class View < Display
|
7
|
+
|
8
|
+
def initialize(kind, id, template, transitions, display_class='ui.View')
|
9
|
+
super(kind, id, template, transitions, display_class)
|
10
|
+
end
|
11
|
+
|
12
|
+
def spec
|
13
|
+
ui_spec = super
|
14
|
+
ui_spec[:html] = html
|
15
|
+
ui_spec
|
16
|
+
end
|
17
|
+
|
18
|
+
def html
|
19
|
+
html = %{<div class="obj-form-frame readonly"><table class="obj-form">}
|
20
|
+
html = append_fields(html, @name, template, true)
|
21
|
+
html << '</table>'
|
22
|
+
html << %{<div class="btn" id="#{@name}.edit_button"><span>Edit</span></div>}
|
23
|
+
html << %{<div class="btn" id="#{@name}.list_button"><span>List</span></div>}
|
24
|
+
html << %{<div class="btn delete-btn" style="float:right;" id="#{@name}.delete_button"><span>Delete</span></div>}
|
25
|
+
html << '</div>'
|
26
|
+
end
|
27
|
+
|
28
|
+
def append_fields(html, path, template, readonly)
|
29
|
+
disabled = readonly ? ' disabled="disabled"' : ''
|
30
|
+
readonly = readonly ? ' readonly' : ''
|
31
|
+
template.each_pair { |id,value|
|
32
|
+
next if :kind == id
|
33
|
+
input = nil
|
34
|
+
input_id = "#{path}.#{id}"
|
35
|
+
text_input = %{<input class="form-field" id="#{input_id}" type="text" value="#{value}" #{readonly}>}
|
36
|
+
|
37
|
+
if value.is_a?(String)
|
38
|
+
count = value.count("\n")
|
39
|
+
if 0 < count # a text area
|
40
|
+
input = %{<textarea class="form-field" id="#{input_id}" rows="#{count}" #{readonly}>#{value.strip}</textarea>}
|
41
|
+
else
|
42
|
+
input = text_input
|
43
|
+
end
|
44
|
+
elsif value.is_a?(TrueClass)
|
45
|
+
input = %{<input class="form-field" id="#{input_id}" type="checkbox"#{disabled} checked>}
|
46
|
+
elsif value.is_a?(FalseClass)
|
47
|
+
input = %{<input class="form-field" id="#{input_id}" type="checkbox"#{disabled}>}
|
48
|
+
elsif value.is_a?(Integer) || WAB::Utils.pre_24_fixnum?(value) || value.is_a?(Number)
|
49
|
+
input = %{<input class="form-field" id="#{input_id}" type="number" value="#{value}" #{readonly}>}
|
50
|
+
elsif value.is_a?(Hash)
|
51
|
+
append_fields(html, input_id, value)
|
52
|
+
else
|
53
|
+
input = text_input
|
54
|
+
end
|
55
|
+
html << %{<tr><td class="field-label">#{id.capitalize}</td><td>#{input}</td></tr>}
|
56
|
+
}
|
57
|
+
html
|
58
|
+
end
|
59
|
+
|
60
|
+
end # View
|
61
|
+
end # UI
|
62
|
+
end # WAB
|