blob: c99e5296a91d8e0a3e2f3fb5bbe912d0dc9435cb [file] [log] [blame]
#!/usr/bin/env ruby
PAGETITLE = "Example Whimsy Script With Styles" # Wvisible:tools
# Note: PAGETITLE must be double quoted
$LOAD_PATH.unshift '/srv/whimsy/lib'
require 'json'
require 'yaml'
require 'wunderbar'
require 'wunderbar/bootstrap'
require 'wunderbar/jquery'
require 'wunderbar/markdown'
require 'whimsy/asf'
require 'whimsy/asf/forms'
require 'whimsy/public'
# Get data from live whimsy.a.o/public directory
def get_public_data()
return Public.getJSON('public_ldap_authgroups.json')
end
# Get data from a Subversion directory
# See /repository.yml for list of auto-updated dirs
def get_svn_data()
dir = ASF::SVN['comdevtalks']
filename = 'README.yaml'
data = YAML.load(File.read(File.join(dir, filename).untaint))
return data['title']
end
# Gather some data beforehand, if you like, but:
# Note runtime errors here just write to the log, not to user's browser
talktitle = get_svn_data()
# Example of handling POST forms cleanly
def emit_form(title, prev_data)
_whimsy_panel("#{title}", style: 'panel-success') do
_form.form_horizontal method: 'post' do
_div.form_group do
_label.col_sm_offset_3.col_sm_9.strong.text_left 'Example Form Section'
end
field = 'text1'
_whimsy_forms_input(label: 'Example Text Field', name: field, id: field,
value: prev_data[field], helptext: 'Enter some text, keep it polite!'
)
field = 'listbox'
_whimsy_forms_select(label: 'Select Some Values', name: field,
multiple: true, values: prev_data[field],
options: ['another value', 'yet another value'],
icon: 'glyphicon-time', iconlabel: 'clock',
helptext: 'Select as many values as ya like!'
)
field = 'text2'
_whimsy_forms_input(label: 'Another Text Field', name: field, id: field,
value: prev_data[field], helptext: 'Pretty boring form example, huh?'
)
_div.col_sm_offset_3.col_sm_9 do
_input.btn.btn_default type: 'submit', value: 'PUSH ME!'
end
end
end
end
# Validation as needed within the script
def validate_form(formdata: {})
return true # TODO: Futureuse
end
# Handle submission (checkout user's apacheid.json, write form data, checkin file)
# @return true if we think it succeeded; false in all other cases
def send_form(formdata: {})
# Example that uses SVN to update an existing file: members/mentor-update.cgi
_p class: 'system' do
_ 'If this were a real send_form() it would do something with your data:'
_br
formdata.each do |k,v|
_ "#{k} = #{v.inspect}"
_br
end
end
return true
end
# Produce HTML
_html do
_body? do # The ? traps errors inside this block
_whimsy_body( # This emits the entire page shell: header, navbar, basic styles, footer
title: PAGETITLE,
subtitle: 'About This Example Script',
relatedtitle: 'More Useful Links',
related: {
"/committers/tools" => "Whimsy Tool Listing",
"https://incubator.apache.org/images/incubator_feather_egg_logo_sm.png" => "Incubator Logo, to show that graphics can appear",
"https://community.apache.org/" => "Get Community Help",
"https://github.com/apache/whimsy/blob/master/www#{ENV['SCRIPT_NAME']}" => "See This Source Code"
},
helpblock: -> {
_p "This www/test/example.cgi script shows a canonical way to write a simple whimsy tool that processes data and then displays it."
_p %{
This helpblock appears at top left, and should explain to an end user what this script does for the user and why they might be interested.
Any related whimsy or other (projects.a.o, etc.) links should be in the related: listing on the top right to help users find other useful things.
This provides a consistent user experience.
}
_p "You can output data previously processed as well like: #{talktitle}"
_ul.list_inline do
_li do
_a 'example-table', href: '#example-table'
end
_li do
_a 'example-accordion', href: '#example-accordion'
end
_li do
_a 'example-form', href: '#example-form'
end
end
},
breadcrumbs: {
dataflow: '/test/dataflow.cgi',
testscript: '/test/example.cgi'
}
) do
# IF YOUR SCRIPT EMITS A LARGE TABLE
_div id: 'example-table'
_whimsy_panel_table(
title: "Data Table H2 Title Goes Here",
helpblock: -> {
_p "If your script displays a sizeable table(s) of data, then use this area to provide a Key: to the data."
}
) do
# Gather or process your data **here**, so if an error is raised, the _body?
# scope will trap it - and will then display the above help information
# to the user before emitting a polite error traceback.
datums = {'one' => 1, 'two' => 2 }
_table.table.table_hover.table_striped do
_thead_ do
_tr do
_th 'Row Number'
_th 'Column Two'
end
_tbody do
datums.each do | key, val |
_tr_ do
_td do
_ key
end
_td do
_ val
end
end
end
end
end
end
end
# IF YOUR SCRIPT ONLY EMITS SIMPLE DATA
_h2 "Simple Data Can Just Use A List"
_ul do
[1,2,3].each do |row|
_li "This is row number #{row}."
end
end
# NIFTY ACCORDION EXPAND-O LISTING: the _whimsy_accordion_item does most of the work
_h2 id: 'example-accordion' do
_ 'Lists of Complex Data Can Use An Accordion'
end
accordionid = 'accordion'
officers = get_public_data()
_div.panel_group id: accordionid, role: 'tablist', aria_multiselectable: 'true' do
officers['auth'].each_with_index do |(listname, rosters), n|
_whimsy_accordion_item(listid: accordionid, itemid: listname, itemtitle: "#{listname}", n: n, itemclass: 'panel-primary') do
_ul do
rosters['roster'].each do |usr|
_li usr
end
end
end
end
end
# IF YOU WANT TO DO WORK BASED ON ?QUERY=value
query = CGI::parse(ENV['QUERY_STRING'])
if query.has_key?('value')
_p "Query Value Passed: #{query['value']}" # Will be array
else
val = Array(query['query']).last
_p "Value Query Passed: #{query['query']}"
_p query.inspect
end
# IF YOU WANT TO DISPLAY A FORM and handle the POST
_div id: 'example-form'
if _.post?
# Use magic _. callouts to CGI class to gather POST data into submission hash
submission = {}
keyz = _.keys
keyz.each do |k|
submission[k] = _.params[k] # Always as ['val'] or ['one', 'two', ...]
end
if validate_form(formdata: submission)
if send_form(formdata: submission)
_p.lead "Thanks for Submitting This Form!"
_p do
_ "The send_form method would have done any procesing needed with the data, after calling validate_data."
end
else
_div.alert.alert_warning role: 'alert' do
_p "SORRY! Your submitted form data failed send_form, please try again."
end
end
else
_div.alert.alert_danger role: 'alert' do
_p "SORRY! Your submitted form data failed validate_form, please try again."
end
end
else # if _.post?
emit_form('Form Title Here', officers)
end
end
end
end