--- loncom/cgi/quotacheck.pl 2014/03/17 02:37:13 1.1 +++ loncom/cgi/quotacheck.pl 2021/09/03 21:37:38 1.9 @@ -6,7 +6,7 @@ $|=1; # requested domain, or current server should belong to requested # domain. # -# $Id: quotacheck.pl,v 1.1 2014/03/17 02:37:13 raeburn Exp $ +# $Id: quotacheck.pl,v 1.9 2021/09/03 21:37:38 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -36,6 +36,7 @@ use strict; use lib '/home/httpd/lib/perl/'; use Apache::lonnet(); use Apache::loncommon(); +use Apache::courseclassifier(); use Apache::lonlocal(); use LONCAPA::Configuration(); use LONCAPA::loncgi(); @@ -51,6 +52,8 @@ if (ref($perlvar) eq 'HASH') { } undef($perlvar); +my $script = "/cgi-bin/quotacheck.pl"; + print &LONCAPA::loncgi::cgi_header('text/html',1); &main($lonhost); @@ -59,7 +62,7 @@ sub main { if ($lonhost eq '') { &Apache::lonlocal::get_language_handle(); &Apache::lonhtmlcommon::add_breadcrumb - ({href=>"/cgi-bin/quotacheck.pl", + ({href=>$script, text=>"Content disk usage"}); print(&Apache::loncommon::start_page('Course/Community disk usage and quotas'). &Apache::lonhtmlcommon::breadcrumbs('Course/Community status'). @@ -83,7 +86,7 @@ sub main { return; } } - my (%gets,%posted,$reqdom,$crstype,%params); + my ($reqdom,$crstype,$type,%params); # # Get domain -- if this is for an authenticated user (i.e., not IP-based access) @@ -91,19 +94,18 @@ sub main { # (b) value of domain item in query string # (c) default login domain for current server # - if (($Apache::lonnet::env{'user.name'}) && ($Apache::lonnet::env{'user.domain'})) { my $q = CGI->new; %params = $q->Vars; $crstype = 'Course'; if ($params{'type'} eq 'Community') { $crstype = $params{'type'}; + $type = $crstype; } - if ($params{'fixeddom'}) { - $reqdom = $params{'fixeddom'}; - } + if ($params{'fixeddom'}) { $reqdom = $params{'fixeddom'} } } if (($reqdom eq '') && ($ENV{'QUERY_STRING'})) { + my %gets; &LONCAPA::loncgi::cgi_getitems($ENV{'QUERY_STRING'},\%gets); if (ref($gets{'domain'}) eq 'ARRAY') { $gets{'domain'}->[0] =~ s/^\s+|\s+$//g; @@ -114,33 +116,81 @@ sub main { } } } + if (($crstype eq '') && (ref($gets{'type'}) eq 'ARRAY')) { + $gets{'type'}->[0] =~ s/^\s+|\s+$//g; + if (lc($gets{'type'}->[0]) eq 'community') { + $crstype = 'Community'; + } elsif ($gets{'type'}->[0] =~ /^(un|)official$/) { + $crstype = $gets{'type'}->[0]; + } + } + if (($params{'sortby'} eq '') && (ref($gets{'sortby'}) eq 'ARRAY')){ + $gets{'sortby'}->[0] =~ s/^\s+|\s+$//g; + if ($gets{'sortby'}->[0] =~ /^(quota|current_disk_usage|percent|quotatype|instcode)$/) { + $params{'sortby'} = $1; + } + } + if (($params{'sortorder'} eq '') && (ref($gets{'sortorder'}) eq 'ARRAY')){ + $gets{'sortorder'}->[0] =~ s/^\s+|\s+$//g; + if ($gets{'sortorder'}->[0] eq 'rev') { + $params{'sortorder'} = $gets{'sortorder'}->[0]; + } + } } if ($reqdom eq '') { $reqdom = &Apache::lonnet::default_login_domain(); } - + my $knownuser; + if (($Apache::lonnet::env{'user.name'}) && ($Apache::lonnet::env{'user.domain'})) { + $knownuser = 1; + } &Apache::lonlocal::get_language_handle(); &Apache::lonhtmlcommon::add_breadcrumb - ({href=>"/cgi-bin/quotacheck.pl?domain=$reqdom", + ({href=>$script."?domain=$reqdom", text=>"Content disk usage"}); - if ($params{'gosearch'}) { + if ((($params{'gosearch'}) || ($params{'sortby'})) && ($knownuser)) { &Apache::lonhtmlcommon::add_breadcrumb - ({href=>"/cgi-bin/quotacheck.pl?domain=$reqdom", + ({href=>$script."?domain=$reqdom", text=>"Result"}); } my $domdesc = &Apache::lonnet::domain($reqdom,'description'); - print(&Apache::loncommon::start_page('Course/Community disk usage and quotas'). + my $starthash; + unless ($crstype eq 'Community') { + $starthash = { + add_entries => {'onload' => "javascript:courseSet(document.filterpicker.official, 'load');"}, + }; + } + print(&Apache::loncommon::start_page('Course/Community disk usage and quotas', undef, $starthash). &Apache::lonhtmlcommon::breadcrumbs('Course/Community status'). '

'.&Apache::lonlocal::mt('Quotas for uploaded course content').'

'. '

'.$domdesc.'

'); +# Sort by course title (cdesc) as default, not reversed + my $sortby = $params{'sortby'}; + unless ($sortby =~ m{^(quota|current_disk_usage|percent|quotatype|instcode)$}) { + $sortby = 'cdesc'; + } + my $sortorder; + if ($params{'sortorder'} eq 'rev') { $sortorder = 'rev'; } + # # If this is for an authenticated user (i.e., not IP-based access) # create display to choose filters to restrict courses/communities displayed # (e.g., recent activity, recently created, institutional code, course owner etc.) # - if (($Apache::lonnet::env{'user.name'}) && ($Apache::lonnet::env{'user.domain'})) { + if ($knownuser) { + print <<"ENDSCRIPT"; + +ENDSCRIPT my ($numtitles,@codetitles); print(&Apache::loncommon::js_changer()); my ($filterlist,$filter) = &get_filters($reqdom,\%params); @@ -151,35 +201,68 @@ sub main { foreach my $item (@standardnames) { if ($params{'official'} eq 'on') { $Apache::lonnet::env{'form.'.$item} = $params{$item}; + $type = 'official'; } else { $Apache::lonnet::env{'form.'.$item} = 0; + $type = 'unofficial'; } } $Apache::lonnet::env{'form.state'} = $params{'state'}; } print(&Apache::loncommon::build_filters($filterlist,$crstype,undef,undef,$filter, - '/cgi-bin/quotacheck.pl',\$numtitles, + $script,\$numtitles, 'quotacheck',undef,undef,undef, \@codetitles,$reqdom,'quotacheck',$reqdom)); - if ($params{'gosearch'}) { + if ( ($params{'gosearch'}) || ($params{'sortby'}) ) { if ($params{'official'} eq 'on') { $Apache::lonnet::env{'form.state'} = $params{'state'}; } my %courses = &Apache::loncommon::search_courses($reqdom,$crstype,$filter,$numtitles, undef,undef,undef,\@codetitles); my @showcourses = keys(%courses); - &print_usage($lonhost,$reqdom,\@showcourses); + &print_usage($lonhost,$reqdom,\@showcourses,$sortby,$sortorder,$type, + $knownuser,$script); } - print(&Apache::loncommon::end_page()); - return; + } else { + my ($instcodefilter,$regexpok,@showcourses); + $instcodefilter = '.'; + if ($crstype eq '') { + $crstype = '.'; + } elsif ($crstype =~ /^(un|)official$/) { + $type = $crstype; + my ($numtitles,@codetitles,%cat_items,%cat_titles,%cat_order); + (undef,undef,$numtitles) = + &Apache::courseclassifier::instcode_selectors_data($reqdom,'filterpicker', + \%cat_items,\@codetitles, + \%cat_titles,\%cat_order); + foreach my $item (@codetitles) { + $Apache::lonnet::env{'form.'.$item} = 0; + } + $instcodefilter = + &Apache::courseclassifier::instcode_search_str($reqdom,$numtitles,\@codetitles); + if ($crstype eq 'official') { + $regexpok = 1; + } elsif ($crstype eq 'unofficial') { + unless ($instcodefilter eq '') { + $regexpok = -1; + } + } + $crstype = 'Course'; + } + my %courseshash = &Apache::lonnet::courseiddump($reqdom,'.',1,$instcodefilter,'.','.', + undef,undef,$crstype,$regexpok); + if (keys(%courseshash)) { + @showcourses = keys(%courseshash); + } + &print_usage($lonhost,$reqdom,\@showcourses,$sortby,$sortorder,$type,$knownuser, + $script); } - &print_usage($lonhost,$reqdom); print(&Apache::loncommon::end_page()); return; } sub print_usage { - my ($lonhost,$dom,$courses) = @_; + my ($lonhost,$dom,$courses,$sortby,$sortorder,$type,$knownuser,$script) = @_; my @domains = &Apache::lonnet::current_machine_domains(); my @ids=&Apache::lonnet::current_machine_ids(); my $domain = &Apache::lonnet::host_domain($lonhost); @@ -197,7 +280,7 @@ sub print_usage { '

'."\n". '

'. &Apache::lonlocal::mt('Show quotas for the domain being coordinated: [_1]', - ''. + ''. $otherdomdesc.''). '

'); return; @@ -220,16 +303,74 @@ sub print_usage { @showcourses = keys(%courseshash); } } + if (@showcourses) { - print(&Apache::loncommon::start_data_table(). - &Apache::loncommon::start_data_table_header_row(). - ''.&Apache::lonlocal::mt('Course Type').''. - ''.&Apache::lonlocal::mt('Course Title').''. - ''.&Apache::lonlocal::mt('Institutional Code').''. - ''.&Apache::lonlocal::mt('Quota (MB)').''. - ''.&Apache::lonlocal::mt('Usage (MB)').''. - ''.&Apache::lonlocal::mt('Percent usage').''. - &Apache::loncommon::end_data_table_header_row()); + # Order in which columns are displayed from left to right + my @order = ('quotatype','cdesc','instcode','quota', + 'current_disk_usage','percent'); + + # Up and down arrows to indicate sort order + my @arrows = (' ▲',' ▼',''); + + # Default sort order and column title + my %columns = ( + quotatype => { + order => 'ascending', + text => &Apache::lonlocal::mt('Course Type'), + }, + cdesc => { + order => 'ascending', + text => &Apache::lonlocal::mt('Course Title'), + }, + instcode => { + order => 'ascending', + text => &Apache::lonlocal::mt('Institutional Code'), + }, + quota => { + order => 'descending', + text => &Apache::lonlocal::mt('Quota (MB)'), + }, + current_disk_usage => { + order => 'descending', + text => &Apache::lonlocal::mt('Usage (MB)'), + }, + percent => { + order => 'descending', + text => &Apache::lonlocal::mt('Percent usage'), + }, + ); + + # Print column headers + my $output = ''; + foreach my $key (@order) { + next if (($key eq 'instcode') && ($type ne 'official') && ($type ne '')); + my $idx; + # Append an up or down arrow to sorted column + if ($sortby eq $key) { + $idx = ($columns{$key}{order} eq 'ascending') ? 0:1; + if ($sortorder eq 'rev') { $idx ++; } + $idx = $idx%2; + } else { $idx = 2; } # No arrow if column not sorted + my $link = 'javascript:changeSort('."'$key'".');'; + if (!$knownuser) { + $link = $script.'?domain='.$dom.'&sortby='.$key; + if ($type =~ /^((un|)official)|(C|c)ommunity/) { + $link .='&type='.$type; + } + if ($sortby eq $key) { + unless ($sortorder) { + $link .= '&sortorder=rev'; + } + } + } + $output .= ''.$columns{$key}{text} + .$arrows[$idx].''; + } + print(&Apache::loncommon::start_data_table() + .&Apache::loncommon::start_data_table_header_row().$output + .&Apache::loncommon::end_data_table_header_row()); + + my $usagehash = {}; # Sortable hash of courses foreach my $cid (@showcourses) { my %courseinfo=&Apache::lonnet::coursedescription($cid,{'one_time' => '1'}); my $cdesc = $courseinfo{'description'}; @@ -255,7 +396,7 @@ sub print_usage { $quotatype = 'textbook'; } if ($quota eq '') { - $quota = $domdefs{$crstype.'quota'}; + $quota = $domdefs{$quotatype.'quota'}; } $quota =~ s/[^\d\.]+//g; if ($quota eq '') { @@ -280,6 +421,7 @@ sub print_usage { foreach my $subdir ('docs','supplemental') { $current_disk_usage += &Apache::lonnet::diskusage($dom,$cnum,"userfiles/$subdir",1); } + $current_disk_usage = $current_disk_usage/1024; } my $percent; if (($quota == 0) || ($quota =~ /[^\d\.]/)) { @@ -290,13 +432,63 @@ sub print_usage { $current_disk_usage = sprintf("%.0f",$current_disk_usage); $quota = sprintf("%.0f",$quota); $percent = sprintf("%.0f",$percent); + + # Enter sortable data into hash + $usagehash->{ $cid } = { + "quotatype" => $quotatype, + "cdesc" => $cdesc, + "instcode" => $instcode, + "quota" => $quota, + "current_disk_usage" => $current_disk_usage, + "percent" => $percent, + }; + } + + # Sort courses by $sortby. "cdesc" is the default. + my @sorted_courses; + if ($sortby =~ m{^(quota|current_disk_usage|percent)$}) { + # Numerical fields + if ($sortorder eq "rev") { + @sorted_courses = sort { + $usagehash->{$a}->{$sortby} <=> $usagehash->{$b}->{$sortby} + or + uc($usagehash->{$a}->{"cdesc"}) cmp uc($usagehash->{$b}->{"cdesc"}) + } (keys(%{$usagehash})); + } else { + @sorted_courses = sort { + $usagehash->{$b}->{$sortby} <=> $usagehash->{$a}->{$sortby} + or + uc($usagehash->{$a}->{"cdesc"}) cmp uc($usagehash->{$b}->{"cdesc"}) + } (keys(%{$usagehash})); + } + } elsif ($sortby =~ m{^(cdesc|quotatype|instcode)$}) { + # String fields + if ($sortorder eq "rev") { + @sorted_courses = sort { + uc($usagehash->{$b}->{$sortby}) cmp uc($usagehash->{$a}->{$sortby}) + or + uc($usagehash->{$a}->{"cdesc"}) cmp uc($usagehash->{$b}->{"cdesc"}) + } (keys(%{$usagehash})); + } else { + @sorted_courses = sort { + uc($usagehash->{$a}->{$sortby}) cmp uc($usagehash->{$b}->{$sortby}) + or + uc($usagehash->{$a}->{"cdesc"}) cmp uc($usagehash->{$b}->{"cdesc"}) + } (keys(%{$usagehash})); + } + } + + # Print data for each course. + foreach my $course (@sorted_courses) { print(&Apache::loncommon::start_data_table_row(). - ''.$quotatype.''. - ''.$cdesc.''. - ''.$instcode.''. - ''.$quota.''. - ''.$current_disk_usage.''. - ''.$percent.''. + ''.$usagehash->{$course}->{"quotatype"}.''. + ''.$usagehash->{$course}->{"cdesc"}.''); + if (($type eq 'official') || (!$type)) { + print(''.$usagehash->{$course}->{"instcode"}.''); + } + print(''.$usagehash->{$course}->{"quota"}.''. + ''.$usagehash->{$course}->{"current_disk_usage"}.''. + ''.$usagehash->{$course}->{"percent"}.''. &Apache::loncommon::end_data_table_row() ); }