<=head title=>Support Requests body<= has_priv( 'supportclose', $filtercat ); # private cats/only this cat $can_close = 1 if $fcat->{public_read} && $remote && $remote->has_priv( 'supportclose', '' ); # public cats } my $append; if ($state eq "closed") { $ret .= ""; $ret .= " "href=\"$LJ::SITEROOT/support/help?cat=$filtercat\"" } ) ." p?>"; } elsif ($state eq "youreplied") { return " " unless $remote; $ret .= ""; $ret .= ""; } else { $ret .= ""; $ret .= BML::ml('.state.else.text', {'statelink'=>"href=\"$LJ::SITEROOT/support/help?state=closed&cat=$filtercat\""}) ; $append = 1; } my @support_log; # if we have a cat to filter to and we have abstracts for it my $rct = 0; my $abstracts = 0; if ($filtercat && $LJ::SUPPORT_ABSTRACTS{$filtercat} && $fcat && $can_read && $state ne 'youreplied') { # yes, we should show abstracts for this category, so do so if ($state eq "closed") { $sth = $dbr->prepare("SELECT s.*, SUBSTRING(sl.message, 1, 200) AS 'message' " . "FROM support s, supportlog sl " . "WHERE s.state='closed' AND s.spid = sl.spid AND sl.type = 'req' " . "AND s.timeclosed > (UNIX_TIMESTAMP() - (3600*168)) " . "AND s.spcatid = ?"); } else { # triggers on green, open $sth = $dbr->prepare("SELECT s.*, SUBSTRING(sl.message, 1, 200) AS 'message' " . "FROM support s, supportlog sl " . "WHERE s.state='open' AND s.spid = sl.spid AND sl.type = 'req' " . "AND s.spcatid = ?"); } $sth->execute($fcat->{spcatid}); push @support_log, $_ while $_ = $sth->fetchrow_hashref(); $rct = scalar(@support_log); $abstracts = 1; } else { my $filterwhere; if ($filtercat eq "_nonpublic") { $filterwhere = " AND s.spcatid IN (0"; foreach my $cat (values %$cats) { $filterwhere .= ", $cat->{'spcatid'}" if !$cat->{'public_read'} && LJ::Support::can_read_cat($cat, $remote); } $filterwhere .= ")"; } elsif ($filtercat eq "_nonprivate") { $filterwhere = " AND s.spcatid IN (0"; foreach my $cat (values %$cats) { $filterwhere .= ", $cat->{'spcatid'}" if $cat->{public_read}; } $filterwhere .= ")"; } elsif ($filtercat =~ /,/) { my %filtercats = map { $_ => 1 } split(",", $filtercat); $filterwhere .= " AND s.spcatid IN (0"; foreach my $cat (values %$cats) { next unless $filtercats{$cat->{'catkey'}}; $filterwhere .= ", $cat->{'spcatid'}" if LJ::Support::can_read_cat($cat, $remote); }; $filterwhere .= ")"; } else { if ($can_read) { $filterwhere = " AND s.spcatid=$fcat->{'spcatid'}"; } else { $filtercat = ""; } } my $dbr = LJ::get_db_reader(); if ($state eq "closed") { $sth = $dbr->prepare("SELECT s.* FROM support s WHERE s.state='closed' AND " . "s.timeclosed>UNIX_TIMESTAMP()-(3600*168) $filterwhere"); } elsif ($state eq "youreplied") { $sth = $dbr->prepare("SELECT s.* FROM support s, support_youreplied yr " . "WHERE yr.userid=$remote->{'userid'} AND s.spid=yr.spid $filterwhere " . "AND (s.state='open' OR (s.state='closed' AND s.timeclosed>UNIX_TIMESTAMP()-(3600*168)))"); } else { # triggers on green, open $sth = $dbr->prepare("SELECT s.* FROM support s WHERE s.state='open' $filterwhere"); } $sth->execute; # For the You Replied filter, we might be getting some rows multiple times (when # multiple log rows exist for $remote), which is still better than using DISTINCT # in the query which uses a temporary table, so ensure uniqueness here. my %spids_seen; while (my $sprow = $sth->fetchrow_hashref) { next if $spids_seen{$sprow->{'spid'}}; $spids_seen{$sprow->{'spid'}} = 1; push @support_log, $sprow; $rct++; } } my $sort = lc $FORM{sort} || ''; $sort = 'date' unless grep { $_ eq $sort } qw( id summary area recent ); if ($append) { # Counts of requests in differing states my $gct = 0; my $snhct = 0; my $aacct = 0; foreach (@support_log) { if ($_->{'timelasthelp'} > $_->{'timetouched'}+5) { $aacct++; } elsif ($_->{'timelasthelp'} && $_->{'timetouched'} > $_->{'timelasthelp'}+5) { $snhct++; } else { $gct++; } } $ret .= "

[ $gct $ML{'.status.unanswered'}, $snhct $ML{'.status.needhelp'}, "; $ret .= "$aacct $ML{'.status.awaitingclose'}, $rct $ML{'.status.totalopen'} ]

"; } my $can_view_nonpublic_modtime = $remote && ( $remote->has_priv( 'supportviewinternal' ) || $remote->has_priv( 'supporthelp' ) ); my $time_active = sub { # timemodified is updated when ICs/screened answers are made, so first check priv return $_[0]->{timemodified} if $can_view_nonpublic_modtime && $_[0]->{timemodified}; my $touched = $_[0]->{timetouched}; my $lasthelp = $_[0]->{timelasthelp}; return $lasthelp > $touched ? $lasthelp : $touched; }; if ($sort eq 'id') { @support_log = sort { $a->{spid} <=> $b->{spid} } @support_log; } elsif ($sort eq 'date') { @support_log = sort { $b->{timecreate} <=> $a->{timecreate} } @support_log; } elsif ($sort eq 'summary') { @support_log = sort { $a->{subject} cmp $b->{subject} } @support_log; } elsif ($sort eq 'area') { @support_log = sort { $cats->{$a->{spcatid}}->{catname} cmp $cats->{$b->{spcatid}}->{catname} } @support_log; } elsif ( $sort eq 'recent' ) { @support_log = sort { $time_active->($b) <=> $time_active->($a) } @support_log; } # filter line: $ret .= "
$ML{'.showonlyhelp'}"; $ret .= ""; $ret .= ""; $ret .= " $ML{'.requests.type'}: \n"; $ret .= "
"; # /filter line # mass closing table $ret .= "
" . LJ::form_auth() if $can_close && $rct; # start the rest of the table my %marked = map { $_ => 1 } split( ',', $GET{mark} ); my $uri = "$LJ::SITEROOT/support/help?cat=$filtercat&state=$state"; $ret .= "

\n"; if ( $can_close ) { my $link = "$uri&sort=$sort&closeall=" . ( $GET{closeall} ? 0 : 1 ); $ret .= "\n"; } my @headers = ( id => "ID#", summary => $ML{'.th.summary'}, area => $ML{'.th.problemarea'}, date => $ML{'.th.posted'}, recent => $ML{'.th.recent'} ); while (my ($sorttype, $desc) = splice(@headers, 0, 2)) { if ($sort eq $sorttype) { $ret .= "\n"; } else { $ret .= "\n"; } } $ret .= "\n"; $ret .= ""; foreach my $sp (@support_log) { LJ::Support::fill_request_with_cat($sp, $cats); next unless (LJ::Support::can_read($sp, $remote)); my $status = $sp->{'state'} eq "closed" ? "closed" : LJ::Support::open_request_status($sp->{'timetouched'}, $sp->{'timelasthelp'}); my $barbg; if ($status eq "open") { $barbg = "green"; } elsif ($status eq "closed") { $barbg = "red"; } elsif ($status eq "awaiting close") { $status = "answered
awaiting close"; $barbg = "yellow"; } elsif ($status eq "still needs help") { $status = "answered
still needs help"; $barbg = "green"; } my $original_barbg = $barbg; $barbg = 'clicked' if ( $GET{closeall} && $original_barbg eq 'yellow' ) || $marked{$sp->{spid}}; next if $state eq "green" && $barbg ne "green"; # fix up the subject if needed eval { if ($sp->{'subject'} =~ /^=\?(utf-8)?/i) { my @subj_data; require MIME::Words; @subj_data = MIME::Words::decode_mimewords($sp->{'subject'}); if (scalar(@subj_data)) { if (!$1) { $sp->{'subject'} = Unicode::MapUTF8::to_utf8({-string=>$subj_data[0][0], -charset=>$subj_data[0][1]}); } else { $sp->{'subject'} = $subj_data[0][0]; } } } }; # fix up the message if we have one my $temp = LJ::text_trim($sp->{message}, 0, 100); # 100 character max if ($temp ne $sp->{message}) { $sp->{message} = LJ::ehtml($temp) . " ..."; } else { $sp->{message} = LJ::ehtml($sp->{message}) . " "; } my $des = $abstracts ? "
$sp->{message}" : ''; # other content for this request my $summary = LJ::ehtml($sp->{'subject'}); my $secs = sub { return time() - $_[0] }; my $time_display = sub { return LJ::mysql_time( $_[0] ) if $GET{rawdates}; return LJ::ago_text( $secs->( $_[0] ) || 1 ); }; my $age = $time_display->( $sp->{timecreate} ); my $untouched = $time_display->( $time_active->( $sp ) ); my $probarea = $sp->{_cat}->{'catname'}; unless ($status eq "closed") { my $points = LJ::Support::calc_points( $sp, $secs->( $sp->{timecreate} ) ); $status .= "
($points point"; if ($points > 1) { $status .= "s"; } $status .= ")"; } my ($style, $js) = ("class='$barbg'", ''); if ($can_close) { $js = "id='r$sp->{spid}' onclick='doClick($sp->{spid});'"; } # generate the HTML for this row $ret .= "\n"; if ($can_close) { $ret .= "\n"; $js = "onclick='return doClick($sp->{spid});'"; } $ret .= ""; $ret .= "\n"; $ret .= "\n"; $ret .= "\n"; $ret .= "\n"; $ret .= "\n"; $ret .= ""; } $ret .= "
 X$desc$desc$ML{'.th.status'}
"; $ret .= LJ::html_check( { name => "check_$sp->{spid}", id => "check_$sp->{spid}", onclick => "doClick($sp->{spid});", selected => $barbg eq 'clicked' } ); $ret .= ""; $ret .= "{'spid'}\" $js>$sp->{'spid'}$summary$des$probarea$age$untouched$status
\n"; # mass close button if ($can_close && $rct) { my $time = time(); $ret .= LJ::html_hidden('ids', join(':', map { $_->{spid} } @support_log), 'spcatid', $fcat->{spcatid}, 'ret', "/support/help?state=$state&cat=$filtercat&time=$time%s"); $ret .= "
"; $ret .= LJ::html_submit('action:move', 'Move Marked Requests'); $ret .= " to "; $ret .= LJ::html_select({ 'name' => 'changecat', selected => '' }, '', '(no change)', map { $_->{'spcatid'}, "---> $_->{'catname'}" } LJ::Support::sorted_cats($cats)); $ret .= "

"; $ret .= LJ::html_submit('action:close', 'Close Marked Requests', { onclick => 'return confirm("Are you sure you want to close the marked requests?");' }); $ret .= " (this is permanent)"; $ret .= "

"; $ret .= LJ::html_submit('action:closewithpoints', 'Close Marked Requests, granting points to last responses', { onclick => 'return confirm("Are you sure you want to close the marked requests?");' }); $ret .= "

"; } $ret .= ""; $ret .= "

".BML::ml('.notifylink', {url=>'href="./changenotify"'})."

"; $ret .= "

".BML::ml('.backlink', {backurl=>'href="./"'})."

"; return $ret; _code?> <=body page?>