| 105 |
bgadell |
1 |
#!/usr/bin/perl
|
|
|
2 |
|
|
|
3 |
# Redirect error messages to a log of my choosing. (it's annoying to filter for errors in the shared env)
|
|
|
4 |
my $error_log_path = $ENV{SERVER_NAME} eq "volunteers.rollercon.com" ? "/home3/rollerco/logs/" : "/tmp/";
|
|
|
5 |
close STDERR;
|
|
|
6 |
open STDERR, '>>', $error_log_path.'vorc_error.log' or warn "Failed to open redirected logfile ($0): $!";
|
|
|
7 |
#warn "Redirecting errors to ${error_log_path}vorc_error.log";
|
|
|
8 |
|
|
|
9 |
use strict;
|
|
|
10 |
use cPanelUserConfig;
|
|
|
11 |
use WebDB;
|
|
|
12 |
use HTML::Tiny;
|
|
|
13 |
use RollerCon;
|
|
|
14 |
use CGI qw/param header start_html url/;
|
|
|
15 |
my $h = HTML::Tiny->new( mode => 'html' );
|
|
|
16 |
my $dbh = WebDB::connect;
|
|
|
17 |
my $homeURL = '/schedule/';
|
|
|
18 |
my $pageTitle = "MVP Class Feedback";
|
|
|
19 |
|
|
|
20 |
my $cookie_string = authenticate (RollerCon::USER) || die;
|
|
|
21 |
my $RCAUTH_cookie = CGI::Cookie->new(-name=>'RCAUTH',-value=>"$cookie_string",-expires=>"+30m");
|
|
|
22 |
my @ERRORS;
|
|
|
23 |
my $DEBUG = 0;
|
|
|
24 |
|
| 109 |
bgadell |
25 |
my $classid = param ("classid") // get_query_string_param ("classid");
|
| 105 |
bgadell |
26 |
error ("No ClassID.") unless $classid;
|
|
|
27 |
|
| 208 |
- |
28 |
my ($registered) = $dbh->selectrow_array ("select id from v_class_signup_new where id = ? and RCid = ?", undef, $classid, $ORCUSER->{RCid});
|
| 105 |
bgadell |
29 |
error ("You don't appear to be registered for this class.") unless $registered;
|
|
|
30 |
|
| 208 |
- |
31 |
my ($started) = $dbh->selectrow_array ("select id from v_class_signup_new where id = ? and RCid = ? and concat_ws(date, end_time) < date_sub(now(), interval 2 hour)", undef, $classid, $ORCUSER->{RCid});
|
| 105 |
bgadell |
32 |
error ("You can't provide feedback until after the class has ended.") unless $started;
|
|
|
33 |
|
|
|
34 |
my $insert_question = $dbh->prepare ("insert into survey_answer (classid, qid, RCid, response, added, page, maxpage) values (?, ?, ?, ?, date_sub(now(), interval 2 hour), ?, ?)");
|
|
|
35 |
my $update_maxpage = $dbh->prepare ("update survey_answer set maxpage = ? where classid = ? and qid = ? and RCid = ?");
|
|
|
36 |
|
|
|
37 |
my $updated = save_survey ($classid) if param("submit") eq "Save";
|
|
|
38 |
|
|
|
39 |
my ($existing) = $dbh->selectrow_array ("select count(*) from v_survey_answer where classid = ? and RCid = ?", undef, $classid, $ORCUSER->{RCid});
|
|
|
40 |
my $mode = $existing ? "disabled" : "edit";
|
|
|
41 |
$mode = "edit" if param("submit") eq "Edit";
|
|
|
42 |
|
|
|
43 |
display_survey ($classid, $mode, $updated);
|
|
|
44 |
|
|
|
45 |
|
| 109 |
bgadell |
46 |
sub get_query_string_param {
|
|
|
47 |
my $field = shift // "";
|
|
|
48 |
|
|
|
49 |
foreach (split (/&/, $ENV{'QUERY_STRING'})) {
|
|
|
50 |
my ($name, $value) = split (/=/);
|
|
|
51 |
$value =~ tr/+/ /;
|
|
|
52 |
$value =~ s/%([a-fA-F0-9] [a-fA-F0-9])/pack("C", hex($1))/eg;
|
|
|
53 |
$value =~ s/~!/ ~!/g;
|
|
|
54 |
return $value if $name eq $field;
|
|
|
55 |
}
|
|
|
56 |
return "";
|
|
|
57 |
}
|
| 105 |
bgadell |
58 |
|
|
|
59 |
|
|
|
60 |
sub save_survey {
|
|
|
61 |
my $CID = shift // error ("No ClassID");
|
|
|
62 |
warn "Saving survey for RCID: $ORCUSER->{RCid}, Class: $CID" if $DEBUG;
|
|
|
63 |
my $changes = 0;
|
|
|
64 |
|
|
|
65 |
foreach (grep { /Question/ } param ()) {
|
|
|
66 |
my ($prefix, $q) = split /_/;
|
|
|
67 |
$changes += save_question ({ cid=>$CID, q=>$q, a=>WebDB::trim (scalar param ($_)) });
|
|
|
68 |
}
|
|
|
69 |
|
|
|
70 |
return $changes;
|
|
|
71 |
}
|
|
|
72 |
|
|
|
73 |
sub save_question {
|
|
|
74 |
my $Q = shift // error ("No data provided to save.");
|
|
|
75 |
return 0 unless answerChanged ($Q);
|
|
|
76 |
warn "Saving question $Q->{q}: $Q->{a}" if $DEBUG;
|
|
|
77 |
my ($maxpage) = $dbh->selectrow_array ("select ifnull(max(page), 0) from survey_answer where RCid = ? and classid = ? and qid = ?", undef, $ORCUSER->{RCid}, $Q->{cid}, $Q->{q});
|
|
|
78 |
$maxpage++;
|
|
|
79 |
$insert_question->execute ($Q->{cid}, $Q->{q}, $ORCUSER->{RCid}, $Q->{a}, $maxpage, $maxpage);
|
|
|
80 |
$update_maxpage->execute ($maxpage, $Q->{cid}, $Q->{q}, $ORCUSER->{RCid});
|
|
|
81 |
return 1;
|
|
|
82 |
}
|
|
|
83 |
|
|
|
84 |
sub answerChanged {
|
|
|
85 |
my $A = shift // error ("No answer provided to check.");
|
|
|
86 |
warn "Checking question $A->{q}: $A->{a}" if $DEBUG;
|
|
|
87 |
my ($check) = $dbh->selectrow_array ("select count(*) from v_survey_answer where classid = ? and qid = ? and RCid = ? and response = ?", undef, $A->{cid}, $A->{q}, $ORCUSER->{RCid}, $A->{a});
|
|
|
88 |
warn "Answer hasn't changed [$check], not saving." if $check and $DEBUG;
|
|
|
89 |
return $check ? 0 : 1;
|
|
|
90 |
}
|
|
|
91 |
|
|
|
92 |
sub display_survey {
|
|
|
93 |
my $CID = shift // error ("No ClassID");
|
|
|
94 |
my $mode = shift // "disabled";
|
|
|
95 |
my $saved = shift // "";
|
|
|
96 |
|
|
|
97 |
print header (-cookie=> [ $RCAUTH_cookie ] ),
|
|
|
98 |
start_html (-title => $pageTitle, -style => [{'src' => "/style.css"},{'src' => "/survey.css"}] );
|
|
|
99 |
print<<JAVASCRIPT;
|
|
|
100 |
<SCRIPT language="JavaScript">
|
|
|
101 |
<!--
|
|
|
102 |
function displayScore(score, targetspan) {
|
|
|
103 |
sliderscore = document.getElementById(score);
|
|
|
104 |
emojis = document.getElementById(targetspan);
|
|
|
105 |
|
|
|
106 |
if (sliderscore.value == 5) {
|
|
|
107 |
emojis.innerHTML = "<img src='/images/star-icon.png' align='middle'><img src='/images/star-icon.png' align='middle'><img src='/images/star-icon.png' align='middle'><img src='/images/star-icon.png' align='middle'><img src='/images/star-icon.png' align='middle'>";
|
|
|
108 |
} else if (sliderscore.value >= 4) {
|
|
|
109 |
emojis.innerHTML = "<img src='/images/star-icon.png' align='middle'><img src='/images/star-icon.png' align='middle'><img src='/images/star-icon.png' align='middle'><img src='/images/star-icon.png' align='middle'>";
|
|
|
110 |
} else if (sliderscore.value >= 3) {
|
|
|
111 |
emojis.innerHTML = "<img src='/images/star-icon.png' align='middle'><img src='/images/star-icon.png' align='middle'><img src='/images/star-icon.png' align='middle'>";
|
|
|
112 |
} else if (sliderscore.value >= 2) {
|
|
|
113 |
emojis.innerHTML = "<img src='/images/star-icon.png' align='middle'><img src='/images/star-icon.png' align='middle'>";
|
|
|
114 |
} else if (sliderscore.value >= 1) {
|
|
|
115 |
emojis.innerHTML = "<img src='/images/star-icon.png' align='middle'>";
|
|
|
116 |
} else if (sliderscore.value > -1) {
|
|
|
117 |
emojis.innerHTML = "<img src='/images/meh.png' align='middle'>";
|
|
|
118 |
} else if (sliderscore.value > -2) {
|
|
|
119 |
emojis.innerHTML = "<img src='/images/angry.png' align='middle'>";
|
|
|
120 |
} else if (sliderscore.value > -3) {
|
|
|
121 |
emojis.innerHTML = "<img src='/images/angry.png' align='middle'><img src='/images/angry.png' align='middle'>";
|
|
|
122 |
} else if (sliderscore.value > -4) {
|
|
|
123 |
emojis.innerHTML = "<img src='/images/angry.png' align='middle'><img src='/images/angry.png' align='middle'><img src='/images/angry.png' align='middle'>";
|
|
|
124 |
} else if (sliderscore.value > -5) {
|
|
|
125 |
emojis.innerHTML = "<img src='/images/angry.png' align='middle'><img src='/images/angry.png' align='middle'><img src='/images/angry.png' align='middle'><img src='/images/angry.png' align='middle'>";
|
|
|
126 |
} else if (sliderscore.value == -5) {
|
|
|
127 |
emojis.innerHTML = "<img src='/images/angry.png' align='middle'><img src='/images/angry.png' align='middle'><img src='/images/angry.png' align='middle'><img src='/images/angry.png' align='middle'><img src='/images/angry.png' align='middle'>";
|
|
|
128 |
} else {
|
|
|
129 |
emojis.innerHTML = sliderscore.value;
|
|
|
130 |
}
|
|
|
131 |
}
|
|
|
132 |
//-->
|
|
|
133 |
</SCRIPT>
|
|
|
134 |
JAVASCRIPT
|
|
|
135 |
|
|
|
136 |
print $h->div ({ class => "accent pageheader" }, [
|
|
|
137 |
$h->h1 ($pageTitle),
|
|
|
138 |
$h->div ({ class=>"sp0" }, [
|
|
|
139 |
$h->div ({ class=>"spLeft" }, [
|
|
|
140 |
]),
|
|
|
141 |
$h->div ({ class=>"spRight" }, [
|
|
|
142 |
$h->input ({ type=>"button", value=>"Home", onClick=>"window.location.href='$homeURL'" }),
|
|
|
143 |
]),
|
|
|
144 |
]),
|
|
|
145 |
]);
|
|
|
146 |
|
|
|
147 |
print $h->div ({ id=>"savedmsg", class=>"saved fadeOut"}, "Changes Saved!") unless !$saved;
|
|
|
148 |
|
| 208 |
- |
149 |
my ($CREF) = $dbh->selectrow_hashref ("select * from v_class_new where id = ?", undef, $classid);
|
| 105 |
bgadell |
150 |
$CREF->{time} = convertTime $CREF->{time};
|
|
|
151 |
$CREF->{date} = $CREF->{date}." [".$CREF->{dayofweek}."]";
|
|
|
152 |
print $h->ul ( { style=>"max-width:610px" }, [ map { $h->li ({ class=>"shaded", style=>"margin:4px;" },
|
|
|
153 |
$h->div ({ class=>"lisp0" }, [
|
|
|
154 |
$h->div ({ class=>"liNarrowLeft" }, ucfirst $_),
|
|
|
155 |
$h->div ({ class=>"liWideRight" }, $CREF->{$_})
|
|
|
156 |
])
|
|
|
157 |
) } ("name", "coach", "date", "time", "location") ]);
|
|
|
158 |
|
|
|
159 |
|
|
|
160 |
|
|
|
161 |
# print $h->div (["Class Details:",
|
|
|
162 |
# $h->p ("Name: ".$CREF->{name},
|
|
|
163 |
# "Coach: ".$CREF->{coach}
|
|
|
164 |
# ),
|
|
|
165 |
# ]), $h->hr;
|
|
|
166 |
|
|
|
167 |
print $h->open ("form");
|
|
|
168 |
print $h->input ({ type=>"hidden", name=>"classid", value=>$CID });
|
|
|
169 |
foreach my $question (@{$dbh->selectall_arrayref ("select qid, question, type, required from survey_question order by qorder")}) {
|
|
|
170 |
my ($qid, $text, $type, $required) = @{$question};
|
|
|
171 |
my ($PRIOR_ANSWER) = $dbh->selectrow_array ("select response from v_survey_answer where classid = ? and qid=? and RCid=?", undef, $CID, $qid, $ORCUSER->{RCid});
|
|
|
172 |
|
|
|
173 |
no strict;
|
|
|
174 |
&{$type."_input"} ($qid, $text, $required, $PRIOR_ANSWER, $mode);
|
|
|
175 |
print $h->br;
|
|
|
176 |
|
|
|
177 |
}
|
|
|
178 |
|
|
|
179 |
my $leftbutton = $mode eq "disabled" ?
|
|
|
180 |
$h->input ({ type=>"button", name=>"back", value=>"Home", onClick=>"window.location.href='$homeURL'" }) :
|
|
|
181 |
$h->input ({ type=>"reset", name=>"Reset", onClick=>"return confirm('Are you sure you want to reset all of your changes?');" });
|
|
|
182 |
|
|
|
183 |
print $leftbutton,
|
|
|
184 |
' ',
|
|
|
185 |
$h->input ({ type=>"submit", name=>"submit", value=> $mode eq "disabled" ? "Edit" : "Save" });
|
|
|
186 |
|
|
|
187 |
print $h->close ("form", "html");
|
|
|
188 |
exit;
|
|
|
189 |
}
|
|
|
190 |
|
|
|
191 |
|
|
|
192 |
sub range_input {
|
|
|
193 |
my $Q = shift // "";
|
|
|
194 |
my $T = shift // "";
|
|
|
195 |
my $R = shift // "";
|
|
|
196 |
my $V = shift // 0;
|
|
|
197 |
my $M = shift // "disabled";
|
|
|
198 |
|
|
|
199 |
my $question_id = "Question_".$Q;
|
|
|
200 |
|
|
|
201 |
print $h->div ({ class => "slidecontainer"}, [
|
|
|
202 |
$h->label ({ for => $question_id }, $T), $h->br,
|
|
|
203 |
$h->input ({ type => "range",
|
|
|
204 |
id => $question_id,
|
|
|
205 |
name => $question_id,
|
|
|
206 |
tabindex => $Q,
|
| 166 |
- |
207 |
min => "0",
|
| 105 |
bgadell |
208 |
max => "5",
|
|
|
209 |
value => $V,
|
|
|
210 |
step => ".1",
|
|
|
211 |
class => "rangeslider",
|
|
|
212 |
onInput => "displayScore('$question_id', 'question$Q');",
|
|
|
213 |
$M => [],
|
|
|
214 |
}),
|
|
|
215 |
$h->span ({ id => "question".$Q }, $h->img ({ src=>"/images/meh.png", align=>"middle" }))
|
|
|
216 |
]);
|
|
|
217 |
print "<SCRIPT language='JavaScript'>displayScore('$question_id', 'question$Q');</SCRIPT>\n" if $V;
|
|
|
218 |
}
|
|
|
219 |
|
|
|
220 |
sub text_input {
|
|
|
221 |
my $Q = shift // "";
|
|
|
222 |
my $T = shift // "";
|
|
|
223 |
my $R = shift // "";
|
|
|
224 |
my $V = shift // "";
|
|
|
225 |
my $M = shift // "disabled";
|
|
|
226 |
|
|
|
227 |
my $question_id = "Question_".$Q;
|
|
|
228 |
|
|
|
229 |
print $h->div ({ class=>"" }, [
|
|
|
230 |
$h->label ({ for => $question_id }, $T), $h->br,
|
|
|
231 |
$h->textarea ({ style => "width: 610px; height: 85px;",
|
|
|
232 |
name => $question_id,
|
|
|
233 |
tabindex => $Q,
|
|
|
234 |
$M => [],
|
|
|
235 |
}, $V)
|
|
|
236 |
]);
|
|
|
237 |
}
|
|
|
238 |
|
|
|
239 |
|
|
|
240 |
sub error {
|
|
|
241 |
my $msg = shift // "";
|
|
|
242 |
|
|
|
243 |
print header (-cookie=> [ $RCAUTH_cookie ] ),
|
|
|
244 |
start_html (-title => $pageTitle, -style => {'src' => "/style.css"} );
|
|
|
245 |
|
|
|
246 |
print $h->div ({ class => "accent pageheader" }, [
|
|
|
247 |
$h->h1 ($pageTitle),
|
|
|
248 |
$h->div ({ class=>"sp0" }, [
|
|
|
249 |
$h->div ({ class=>"spLeft" }, [
|
|
|
250 |
]),
|
|
|
251 |
$h->div ({ class=>"spRight" }, [
|
|
|
252 |
$h->input ({ type=>"button", value=>"Home", onClick=>"window.location.href='$homeURL'" }),
|
|
|
253 |
]),
|
|
|
254 |
]),
|
|
|
255 |
]),
|
|
|
256 |
$h->div ({ class => "error" }, $msg),
|
|
|
257 |
$h->close ("html");
|
|
|
258 |
|
|
|
259 |
exit;
|
|
|
260 |
}
|