#. "$_EXEC"/session_lock.sh
. "$_EXEC"/widgets.sh
+export MD_HTML="false"
+if [ "$(which awk)" ]; then
+ markdown() { awk -f "$_EXEC/cgilite/markdown.awk"; }
+else
+ markdown() { busybox awk -f "$_EXEC/cgilite/markdown.awk"; }
+fi
+
PATH_INFO="$(PATH "/${PATH_INFO#${_BASE}}")"
#git init "$_DATA" >/dev/null &
[link rel="stylesheet" type="text/css" href="%s/webpoll.css"]
[title %s]
] [body class="%s"
- ' "$_BASE" "$_BASE" "$_BASE" "$title" "$page"
+ ' "$_BASE" "$_BASE" "$_BASE" "$(HTML "$title")" "$page"
cat
printf '] ]'
} |"$_EXEC/cgilite/html-sh.sed" -u
fi
}
page_newdate() { . "$_EXEC"/newdate.sh; }
+page_poll() { . "$_EXEC/poll.sh"; }
case ${PATH_INFO} in
/favicon.ico) printf '%s\r\n' 'Content-Length: 0' '';;
/) page_home;;
/*/newdate) page_newdate;;
/*/newoptions);;
- *);;
+ /[0-9a-zA-Z:=]???????????????) page_poll;;
esac
exit 0
--- /dev/null
+#!/bin/sh
+
+id="$(checkid "${PATH_INFO#/}")"
+file="${_DATA}/${id}"
+
+#cancel if poll is invalid
+[ "$id" -a -f "$file" ] || REDIRECT "$_BASE/"
+
+tkey() {
+ # convert time stamps for use in POST keys
+ local str="$1" out
+ while [ "$str" ]; do
+ case $str in
+ :*) out="${out}.";;
+ *) out="${out}${str%"${str#?}"}";;
+ esac
+ str="${str#?}"
+ done
+ printf %s "$out"
+}
+
+timelist() {
+ local dates todall splittimes
+ local date tod todsplit
+
+ if [ "$splittimes" = no -a "$dates" -a "$todall" ]; then
+ for date in $dates; do for tod in $todall; do
+ printf %s\\n "${date}_${tod%-}"
+ done ;done
+
+ elif [ "$splittimes" = no -a "$dates" ]; then
+ for date in $dates; do
+ printf %s\\n "${date}"
+ done
+
+ elif [ "$splittimes" = no -a "$todall" ]; then
+ for tod in $todall; do
+ printf %s\\n "${tod%-}"
+ done
+
+ elif [ "$splittimes" = yes ]; then
+ for date in $dates; do
+ todsplit="$(DBM "$file" get "tod_$date")"
+ [ "$todsplit" ] \
+ && for tod in $todsplit; do printf %s\\n "${date}_${tod%-}"; done \
+ || printf %s\\n "${date}"
+ done
+
+ else
+ return 1
+
+ fi
+}
+
+table_poll() {
+ local splittimes="$(DBM "$file" get splittimes || printf no)"
+ local dates="$(DBM "$file" get dates)"
+ local todall="$(DBM "$file" get todall)"
+ local timelist="$(timelist)"
+ local time date span name
+
+ [ "$timelist" ] || return 1
+
+ printf '[table .poll [thead\n'
+ # date header
+ if [ "$dates" ]; then
+ printf '[tr .dates [th]'
+ for date in $dates; do
+ span=0; for time in $timelist; do case $time in
+ ${date}*) span=$((span + 1));;
+ esac; done
+ date -d "$date" +"[th colspan=\"${span}\" . %A <br/> %B %_d, %Y]";
+ done
+ printf '[th]]\n'
+ fi
+
+ # tod header
+ if [ "$splittimes" = yes -o "$todall" ]; then
+ printf '[tr .tod [th]'
+ for time in $timelist; do
+ [ "${time#*_}" = "${time}" ] && time="${time}_"
+ printf '[th . %s]' "${time#*_}"
+ done
+ printf '[th]]\n'
+ fi
+
+ printf '][tbody\n'
+
+ { DBM "$file" get participants; printf \\n; } |while read -r name; do
+ yes="$(DBM "$file" get "reply_yes_${name}")"
+ no="$(DBM "$file" get "reply_no_${name}")"
+ maybe="$(DBM "$file" get "reply_maybe_${name}")"
+
+ printf '[tr [th .name . %s]' "$(HTML "$name")"
+ for time in $timelist; do
+ printf %s "$yes" |grep -qwF "$time" && printf '[td .yes Yes]' && continue
+ printf %s "$no" |grep -qwF "$time" && printf '[td .no No]' && continue
+ printf %s "$maybe" |grep -qwF "$time" && printf '[td .maybe Maybe]' && continue
+ printf '[td .missing . ?]'
+ done
+ printf '[td]]'
+ done
+
+ # Submit line
+ printf '[tr .new [td [input name="name" value="" placeholder="Your Name" autocomplete=off]]'
+ for time in $timelist; do
+ time="$(tkey "$time")"
+ printf '[td [radio "%s" "yes" #yes_%s][label for="yes_%s" Yes]
+ [radio "%s" "no" #no_%s][label for="no_%s" No]
+ [radio "%s" "maybe" #maybe_%s][label for="maybe_%s" Maybe]
+ ]' "${time}" "${time}" "${time}" \
+ "${time}" "${time}" "${time}" \
+ "${time}" "${time}" "${time}"
+ done
+ printf '[td [submit "new" "new" Submit]]]\n'
+
+ printf ']]'
+}
+
+if [ "$REQUEST_METHOD" = POST ]; then
+ local name="$(POST name |grep -m 1 -xE '.*[^ ].*')"
+ local splittimes="$(DBM "$file" get splittimes || printf no)"
+ local dates="$(DBM "$file" get dates)"
+ local todall="$(DBM "$file" get todall)"
+ local timelist="$(timelist)"
+ local time yes no maybe reply
+
+ if [ "$(POST new)" = new ]; then
+ if [ ! "$name" ]; then
+ REDIRECT "${_BASE}${PATH_INFO}#ERROR_NONAME"
+ elif DBM "$file" get participants |grep -qxF "$name"; then
+ REDIRECT "${_BASE}${PATH_INFO}#ERROR_NAMEEXISTS"
+ fi
+ DBM "$file" append participants "${BR}${name}" || DBM "$file" insert participants "${name}" \
+ || REDIRECT "${_BASE}${PATH_INFO}#ERROR_DBACCESS"
+
+ for time in $timelist; do reply="$(POST "$(tkey "$time")")"; case $reply in
+ yes) yes="${yes}${yes:+ }${time}";;
+ no) no="${no}${no:+ }${time}";;
+ maybe) maybe="${maybe}${maybe:+ }${time}";;
+ esac; done
+ DBM "$file" set "reply_yes_${name}" "$yes"
+ DBM "$file" set "reply_no_${name}" "$no"
+ DBM "$file" set "reply_maybe_${name}" "$maybe"
+ REDIRECT "${_BASE}${PATH_INFO}"
+ fi
+
+else
+ pagename="$(pagename "$id")"
+
+ yield_page "$pagename" poll <<-EOF
+ [form method=POST
+ [section .description
+ [h1 .title $(HTML "$pagename")]
+ $(DBM "$file" get description |markdown)
+ ]
+ $(table_poll || printf '[p Poll parameters are invalid]')
+ ]
+ EOF
+fi
transform: translate(-50%, -50%);
}
+body.poll form {
+ text-align: center;
+ max-width: 95%;
+}
+body.poll .description {
+ text-align: left;
+ max-width: 50em;
+ padding: 1pt 1em 1em 1em;
+ margin: auto;
+ margin-bottom: 1em;
+ background-color: rgba(255,255,255,.5);
+}
+body.poll .description .title {
+ text-align: center;
+}
+body.poll table {
+ background-color: rgba(255,255,255,.5);
+ border-collapse: collapse;
+ margin: auto;
+ -border: .5pt solid;
+ box-shadow: #000 .25em .25em .5em;
+ border-radius: 2pt;
+}
+body.poll table thead tr.dates th {
+ padding: .25em;
+}
+body.poll table thead tr.tod th {
+ border-width: .5pt;
+ border-style: none solid none solid;
+ padding: .25em;
+}
+body.poll table tbody tr td {
+ text-align: center;
+ border: .5pt solid;
+ padding: 0 .25em;
+}
+body.poll table tbody tr td:first-child,
+body.poll table tbody tr td:last-child,
+body.poll table thead tr th:first-child,
+body.poll table thead tr th:last-child { border: none; }
+
+body.poll table tbody tr th.name { padding: .25em .5em; text-align: right; }
+body.poll table tbody tr td.yes { background-color: #AFA; }
+body.poll table tbody tr td.no { background-color: #FAA; }
+body.poll table tbody tr td.maybe { background-color: #FFA; }
+
+body.poll table td input[type=radio] { display: none; }
+body.poll table td input[type=radio] + label {
+ font-size: .875em;
+ text-decoration: underline;
+ color: #066;
+ padding: .25em;
+ margin: 0;
+}
+body.poll table td input[type=radio]:checked + label {
+ font-weight: bold;
+}
+body.poll table td input[type=radio][value=yes]:checked + label {
+ background-color: #AFA;
+ margin: 0 -1.5pt;
+}
+body.poll table td input[type=radio][value=no]:checked + label {
+ background-color: #FAA;
+ margin: 0 -.75pt;
+}
+body.poll table td input[type=radio][value=maybe]:checked + label {
+ background-color: #FFA;
+ margin: 0 -1.75pt;
+}
+
body.newdate form {
text-align: center;
max-width: 100%;