305 lines
9.5 KiB
Ruby
305 lines
9.5 KiB
Ruby
|
# SPDX-License-Identifier: Apache-2.0
|
||
|
# Copyright (C) 2021 OKTET Labs Ltd. All rights reserved.
|
||
|
|
||
|
#
|
||
|
# General CGI helpers
|
||
|
#
|
||
|
|
||
|
HEADER_FILE = "header.html"
|
||
|
FOOTER_FILE = "footer.html"
|
||
|
|
||
|
CURRENT_MONTH = "- Current -"
|
||
|
# Where to place it in the months list
|
||
|
CURRENT_MONTH_NUMBER = 0
|
||
|
|
||
|
def cgi_debug_log(msg)
|
||
|
STDERR.puts "DEBUG: " + msg
|
||
|
end
|
||
|
|
||
|
class MyCGI < CGI
|
||
|
|
||
|
# http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/23950?help-en
|
||
|
def MyCGI::pretty(string, shift = " ")
|
||
|
i = 0; preserve = {}
|
||
|
lines = string.gsub(/\n*<pre.*<\/pre>\n*/inm) {
|
||
|
t = "%PRE#{i}"; i += 1
|
||
|
preserve[t] = $&
|
||
|
t
|
||
|
}
|
||
|
lines = lines.gsub(/\n*<textarea.*<\/textarea>\n*/inm) {
|
||
|
t = "%TEXTAREA#{i}"; i += 1
|
||
|
preserve[t] = $&
|
||
|
t
|
||
|
}
|
||
|
lines = lines.gsub(/(?!\A)<(?:.|\n)*?>/n,
|
||
|
"\n\\0").gsub(/<(?:.|\n)*?>(?!\n)/n, "\\0\n")
|
||
|
end_pos = 0
|
||
|
while end_pos = lines.index(/^<\/(\w+)/n, end_pos)
|
||
|
element = $1.dup
|
||
|
start_pos = lines.rindex(/^\s*<#{element}/ni, end_pos)
|
||
|
lines[start_pos ... end_pos] = "__" +
|
||
|
lines[start_pos ... end_pos].
|
||
|
gsub(/\n(?!\z)/n, "\n" + shift) +
|
||
|
"__"
|
||
|
end
|
||
|
lines = lines.gsub(/^((?:#{Regexp::quote(shift)})*)__(?=<\/?\w)/n,
|
||
|
'\1')
|
||
|
preserve.each { |t, s|
|
||
|
lines.sub!(/#{Regexp::quote(t)}/, s)
|
||
|
}
|
||
|
lines
|
||
|
end
|
||
|
|
||
|
def MyCGI::list_select(list, param)
|
||
|
param = Array.new if not param
|
||
|
list.collect do |entry|
|
||
|
param.include?(entry[0]) ? entry.dup.push(true) : entry
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def initialize(form_type, default_params, multiple_key, multiline_key, *args)
|
||
|
super(*args)
|
||
|
@form_type = form_type
|
||
|
@tree_params = default_params
|
||
|
@multiple_key = multiple_key
|
||
|
@multiline_key = multiline_key
|
||
|
self.params.each do |key, value|
|
||
|
@tree_params = add_value(@tree_params, key, value, @multiple_key.include?(key))
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def add_value(hash, key, value, multiple)
|
||
|
hash = Hash.new if not hash
|
||
|
if /^(.*?):(.*)$/ =~ key
|
||
|
hash[$1] = add_value(hash[$1], $2, value, @multiple_key.include?($1))
|
||
|
elsif @multiline_key.include?(key)
|
||
|
hash[key] = value.join
|
||
|
else
|
||
|
hash[key] = (multiple or value.length > 1) ? value : value[0]
|
||
|
end
|
||
|
hash
|
||
|
end
|
||
|
|
||
|
def hiddens(value)
|
||
|
value.inject([]) do |res, item|
|
||
|
res + [Amrita.a(:name => item[0], :value => item[1])]
|
||
|
end
|
||
|
end
|
||
|
|
||
|
# Create array of pairs [name, value] from the parameters subtree
|
||
|
def tree_flatten(keys)
|
||
|
hash = @tree_params
|
||
|
keys.each do |key|
|
||
|
return [] if not hash[key]
|
||
|
hash = hash[key]
|
||
|
end
|
||
|
add_flatten(keys[0..-2], keys[-1], hash)
|
||
|
end
|
||
|
|
||
|
def add_flatten(prefix, field, data)
|
||
|
names = field ? prefix + [field] : prefix
|
||
|
if data.is_a? Hash
|
||
|
data.inject([]) do |res, pair|
|
||
|
res + add_flatten(names, pair[0], pair[1])
|
||
|
end
|
||
|
elsif data.is_a? Array
|
||
|
data.inject([]) do |res, value|
|
||
|
res << [names.join(":"), value.to_s]
|
||
|
end
|
||
|
else
|
||
|
# single value
|
||
|
[[names.join(":"), data.to_s]]
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def tree_hidden(keys)
|
||
|
hash = @tree_params
|
||
|
keys.each do |key|
|
||
|
return "" if not hash[key]
|
||
|
hash = hash[key]
|
||
|
end
|
||
|
add_hidden(keys[0..-2], keys[-1], hash)
|
||
|
end
|
||
|
|
||
|
def MyCGI::list_options(data, selections = nil)
|
||
|
selection = ((selections.is_a? Array) ? selections[0] : selections).to_s
|
||
|
data.collect do |pair|
|
||
|
item = Amrita.a(:value => pair[0]){ pair[1] }
|
||
|
item << Amrita.a(:selected => "selected")[0] if
|
||
|
pair[0].to_s == selection
|
||
|
item
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def tree_hidden_e(keys)
|
||
|
hash = @tree_params
|
||
|
keys.each do |key|
|
||
|
return [] if not hash[key]
|
||
|
hash = hash[key]
|
||
|
end
|
||
|
add_hidden_e(keys[0..-2], keys[-1], hash)
|
||
|
end
|
||
|
|
||
|
def add_hidden_e(prefix, field, value)
|
||
|
if value.is_a? Hash
|
||
|
value.inject([]) do |res, pair|
|
||
|
res + add_hidden_e(prefix + [field], pair[0], pair[1])
|
||
|
end
|
||
|
else
|
||
|
value.inject([]) do |res, value1|
|
||
|
res + [ Amrita.a(:name => (prefix + [field]).join(":"),
|
||
|
:value => value1) ]
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def add_hidden(prefix, field, value)
|
||
|
if value.is_a?Hash
|
||
|
value.inject("") do |res, pair|
|
||
|
res + add_hidden(prefix + [field], pair[0], pair[1])
|
||
|
end
|
||
|
else
|
||
|
value.inject("") do |res, value1|
|
||
|
res + hidden((prefix + [field]).join(":"), value1)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def MyCGI::hash2date(hash)
|
||
|
begin
|
||
|
value = %w(year month day).collect do |p|
|
||
|
hash[p].is_a?(Array) ? hash[p][0] : hash[p]
|
||
|
end
|
||
|
value[0] = case value[0]
|
||
|
when '$' then 9999
|
||
|
when '#' then Date.today.year
|
||
|
else value[0].to_i
|
||
|
end
|
||
|
value[1] = case value[1]
|
||
|
when '$' then Date::MONTHNAMES.length - 1
|
||
|
when CURRENT_MONTH then Date.today.month
|
||
|
when CURRENT_MONTH_NUMBER.to_s then Date.today.month
|
||
|
else value[1].to_i
|
||
|
end
|
||
|
|
||
|
if value[2] == '$'
|
||
|
value[2] = 1
|
||
|
(Date.new(*value) >> 1) - 1
|
||
|
elsif value[2] == '#'
|
||
|
value[2] = Date.today.day
|
||
|
Date.new(*value)
|
||
|
else
|
||
|
value[2] = value[2].to_i
|
||
|
Date.new(*value)
|
||
|
end
|
||
|
rescue ArgumentError
|
||
|
raise "Invalid date #{hash["year"]}-#{hash["month"]}-#{hash["day"]}"
|
||
|
end
|
||
|
end
|
||
|
def MyCGI::date2hash(date)
|
||
|
{
|
||
|
"year" => [date.year.to_s],
|
||
|
"month" => [date.mon.to_s],
|
||
|
"day" => [date.day.to_s]
|
||
|
}
|
||
|
end
|
||
|
|
||
|
def MyCGI::select_date(prefix = "", value = nil, edit = false)
|
||
|
if value == nil
|
||
|
edit = true
|
||
|
value = MyCGI::date2hash(Date.today)
|
||
|
elsif value.is_a?Hash
|
||
|
# TODO: !!!!
|
||
|
value = { "year" => [value["year"]],
|
||
|
"month" => [value["month"]],
|
||
|
"day" => [value["day"]] } unless value["year"].is_a?Array
|
||
|
edit = true
|
||
|
else
|
||
|
value = MyCGI::date2hash(value)
|
||
|
end
|
||
|
if edit
|
||
|
template = Amrita::TemplateText.new(
|
||
|
"<input class='form-control' id='day' size='2' type='text'>
|
||
|
<select class='form-control' id='month'><option id='item'></select>
|
||
|
<input class='form-control' id='year' size='4' type='text'>")
|
||
|
template.asxml = true
|
||
|
s = String.new
|
||
|
template.expand(s,
|
||
|
{:day => Amrita.a(
|
||
|
:name => prefix + ":day",
|
||
|
:value => value["day"][0]),
|
||
|
:month => Amrita.a(
|
||
|
:name => prefix + ":month"){
|
||
|
{:item => list_options(
|
||
|
(0..(Date::MONTHNAMES.length - 1)).collect do |m|
|
||
|
case m
|
||
|
when CURRENT_MONTH_NUMBER then [m.to_s, CURRENT_MONTH]
|
||
|
else [m.to_s, Date::MONTHNAMES[m]]
|
||
|
end
|
||
|
end, value["month"][0])
|
||
|
}
|
||
|
},
|
||
|
:year => Amrita.a(
|
||
|
:name => prefix + ":year",
|
||
|
:value => value["year"][0])
|
||
|
})
|
||
|
s
|
||
|
else
|
||
|
d = Date.new(value["year"][0].to_i, value["month"][0].to_i,
|
||
|
value["day"][0].to_i)
|
||
|
sprintf("%s %s %s (%s)", value["day"][0],
|
||
|
Date::MONTHNAMES[value["month"][0].to_i],
|
||
|
value["year"][0],
|
||
|
Date::ABBR_DAYNAMES[d.wday])
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def MyCGI::select_date_e(prefix = "", value = nil, edit = false)
|
||
|
noescape{ select_date(prefix, value, edit) }
|
||
|
end
|
||
|
|
||
|
# Assign values to the all-site common parts of the page
|
||
|
#
|
||
|
# @param data Hash of data for amrita template of the page
|
||
|
def MyCGI::add_commons(data)
|
||
|
data[:header] = noescape{ File.open(HEADER_FILE) { |f| f.read }}
|
||
|
data[:footer] = noescape{ File.open(FOOTER_FILE) { |f| f.read }}
|
||
|
end
|
||
|
|
||
|
def MyCGI::optional(data)
|
||
|
{ :value => data }
|
||
|
end
|
||
|
|
||
|
# Create string from the 'value' that can be used
|
||
|
# as a value of HTML DOM attribute 'id'
|
||
|
#
|
||
|
# @return String of proposed attribute value
|
||
|
def MyCGI::element_id(value)
|
||
|
id = value.to_s
|
||
|
if id.empty? or id !~ /[A-Za-z].*/
|
||
|
"s" + id
|
||
|
else
|
||
|
id
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def MyCGI.dump(value)
|
||
|
case value.class.to_s
|
||
|
when "Hash" then
|
||
|
"{" + value.collect do |key, x|
|
||
|
"#{key} => #{dump(x)}"
|
||
|
end.join(", ") + "}"
|
||
|
when "String" then
|
||
|
"\"#{value}\""
|
||
|
when "Array" then
|
||
|
"[#{value.collect {|x| dump(x)}.join(",")}]"
|
||
|
else
|
||
|
"#{value.class}(#{value.to_s})"
|
||
|
end
|
||
|
end
|
||
|
|
||
|
attr_accessor :form_type, :tree_params, :multiple_key
|
||
|
private :add_value
|
||
|
end
|
||
|
|