--- loncom/publisher/lonpubdir.pm	2014/05/31 13:55:17	1.154
+++ loncom/publisher/lonpubdir.pm	2019/08/13 17:01:24	1.160.2.4
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Authoring Space Directory Lister
 #
-# $Id: lonpubdir.pm,v 1.154 2014/05/31 13:55:17 raeburn Exp $
+# $Id: lonpubdir.pm,v 1.160.2.4 2019/08/13 17:01:24 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -60,22 +60,78 @@ sub handler {
     my $thisdisfn=$fn;
 
     my $docroot=$r->dir_config('lonDocRoot');     # Apache  londocument root.
+    if ($thisdisfn eq "$docroot/priv/$udom") {
+        if ((-d "/home/$uname/public_html/") && (!-e "$docroot/priv/$udom/$uname")) {
+            my ($version) = ($r->dir_config('lonVersion') =~ /^\'?(\d+\.\d+)\./);
+            &Apache::loncommon::content_type($r,'text/html');
+            $r->send_http_header;
+
+            &Apache::lonhtmlcommon::clear_breadcrumbs();
+            $r->print(&Apache::loncommon::start_page('Authoring Space').
+                      '<div class="LC_error">'.
+                      '<br /><p>'.
+                      &mt('Your Authoring Space is currently in the location used by LON-CAPA version 2.10 and older, but your domain is using a newer LON-CAPA version ([_1]).',$version).'</p>'.
+                      '<p>'.
+                      &mt('Please ask your Domain Coordinator to move your Authoring Space to the new location.').
+                      '</p>'.
+                      '</div>'.
+                      &Apache::loncommon::end_page());
+            return OK;
+        }
+    }
     $thisdisfn=~s/^\Q$docroot\E\/priv//;
-    
+
     my $resdir=$docroot.'/res'.$thisdisfn; # Resource directory
     my $targetdir='/res'.$thisdisfn; # Publication target directory.
     my $linkdir='/priv'.$thisdisfn;      # Full URL name of constr space.
 
     my %bombs=&Apache::lonmsg::all_url_author_res_msg($uname,$udom);
 
-    &startpage($r, $uname, $udom, $thisdisfn);  # Put out the start of page.
-    &dircontrols($r,$uname,$udom,$thisdisfn);   # Put out actions for directory, 
-                                                # browse/upload + new file page.
+    my $londocroot = $Apache::lonnet::perlvar{'lonDocRoot'};
+    my $current_disk_usage = &Apache::lonnet::diskusage($udom,$uname,
+                                "$londocroot/priv/$udom/$uname"); # expressed in kB
+    my $disk_quota = &Apache::loncommon::get_user_quota($uname,$udom,
+                                                 $cstr,$crstype); # expressed in MB
+
+    # Put out the start of page.
+    &startpage($r, $uname, $udom, $thisdisfn, $current_disk_usage, $disk_quota, $crsauthor);
+
+    if (!-d $fn) {
+        if (-e $fn) {
+            $r->print('<p class="LC_info">'.&mt('Requested item is a file not a directory.').'</p>');
+        } else {
+            $r->print('<p class="LC_info">'.&mt('The requested subdirectory does not exist.').'</p>');
+        }
+        $r->print(&Apache::loncommon::end_page());
+        return OK;
+    }
+    my @files;
+    if (opendir(DIR,$fn)) {
+        @files = grep(!/^\.+$/,readdir(DIR));
+        closedir(DIR);
+    } else {
+        $r->print('<p class="LC_error">'.&mt('Could not open directory.').'</p>');
+        $r->print(&Apache::loncommon::end_page());
+        return OK;
+    }
+
+    # Put out actions for directory, browse/upload + new file page.
+    &dircontrols($r,$uname,$udom,$thisdisfn, $current_disk_usage, $disk_quota);
     &resourceactions($r,$uname,$udom,$thisdisfn); # Put out form used for printing/deletion etc.
 
     my $numdir = 0;
     my $numres = 0;
   
+    if ((@files == 0) && ($thisdisfn =~ m{^/$match_domain/$match_username})) {
+        if ($thisdisfn =~ m{^/$match_domain/$match_username$}) {
+            $r->print('<p class="LC_info">'.&mt('This Authoring Space is currently empty.').'</p>');
+        } else {
+            $r->print('<p class="LC_info">'.&mt('This subdirectory is currently empty.').'</p>');
+        }
+        $r->print(&Apache::loncommon::end_page());
+        return OK;
+    }
+
     # Retrieving value for "sortby" and "sortorder" from QUERY_STRING
     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
         ['sortby','sortorder']);
@@ -83,58 +139,80 @@ sub handler {
     # Sort by name as default, not reversed
     if (! exists($env{'form.sortby'})) { $env{'form.sortby'} = 'filename' }
     if (! exists($env{'form.sortorder'})) { $env{'form.sortorder'} = '' }
-
     my $sortby = $env{'form.sortby'};
     my $sortorder = $env{'form.sortorder'};
 
-    opendir(DIR,$fn);
-    my @files = readdir(DIR);
-    closedir(DIR);
-
-    if ((@files == 0) && ($thisdisfn =~ m{^/$match_domain/$match_username})) {
-        $r->print('<p class="LC_info">'.&mt('This Authoring Space is currently empty.').'</p>');
-        $r->print(&Apache::loncommon::end_page());
-        return OK;
+    # Order in which columns are displayed from left to right
+    my @order = ('filetype','actions','filename','title',
+                    'pubstatus','cmtime','size');
+
+    # Up and down arrows to indicate sort order
+    my @arrows = ('&nbsp;&#9650;','&nbsp;&#9660;','');
+
+    # Default sort order and column title
+    my %columns = (
+        filetype =>     {
+                            order => 'ascending',
+                            text  => &mt('Type'),
+                        },
+        actions =>      {
+                            # Not sortable
+                            text  => &mt('Actions'),
+                        },
+        filename =>     {
+                            order => 'ascending',
+                            text  => &mt('Name'),
+                        },
+        title =>        {
+                            order => 'ascending',
+                            text  => &mt('Title'),
+                        },
+        pubstatus =>    {
+                            order => 'ascending',
+                            text  => &mt('Status'),
+                            colspan => '2',
+                        },
+        cmtime =>       {
+                            order => 'descending',
+                            text  => &mt('Last Modified'),
+                        },
+        size =>         {
+                            order => 'ascending',
+                            text  => &mt('Size').' (kB)',
+                        },
+    ); 
+
+    # Print column headers
+    my $output = '';
+    foreach my $key (@order) {
+        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 is not sorted
+        $output .= (($columns{$key}{order}) ?
+            '<th'.($columns{$key}{colspan} ? ' colspan="'.$columns{$key}{colspan}.'"' : '')
+            .'><a href="'.$linkdir.'/?sortby='.$key.'&amp;sortorder='
+            .((($sortby eq $key) && ($sortorder ne 'rev')) ? 'rev' : '').'">'
+            .$columns{$key}{text}.$arrows[$idx].'</a></th>' :
+            '<th>'.$columns{$key}{text}.'</th>');
     }
-
-    # Start off the directory table.
     $r->print(&Apache::loncommon::start_data_table()
-        .&Apache::loncommon::start_data_table_header_row()
-        .'<th><a href="'.$linkdir.'/?sortby=filetype&sortorder='
-            .((($sortby eq "filetype") && ($sortorder ne 'rev')) ? 'rev' : '') 
-            .'">'.&mt('Type')
-            .'<span class="LC_fontsize_small"> &#9660;</span></a></th>'
-        .'<th>'.&mt('Actions').'</th>'
-        .'<th><a href="'.$linkdir.'/?sortby=filename&sortorder='
-            .((($sortby eq "filename") && ($sortorder ne 'rev')) ? 'rev' : '') 
-            .'">'.&mt('Name')
-            .'<span class="LC_fontsize_small"> &#9660;</span></a></th>'
-        .'<th><a href="'.$linkdir.'/?sortby=title&sortorder='
-            .((($sortby eq "title") && ($sortorder ne 'rev')) ? 'rev' : '') 
-            .'">'.&mt('Title')
-            .'<span class="LC_fontsize_small"> &#9660;</span></a></th>'
-        .'<th colspan="2"><a href="'.$linkdir.'/?sortby=pubstatus&sortorder='
-            .((($sortby eq "pubstatus") && ($sortorder ne 'rev')) ? 'rev' : '') 
-            .'">'.&mt('Status')
-            .'<span class="LC_fontsize_small"> &#9660;</span></a></th>'
-        .'<th><a href="'.$linkdir.'/?sortby=cmtime&sortorder='
-            .((($sortby eq "cmtime") && ($sortorder ne 'rev')) ? 'rev' : '') 
-            .'">'.&mt('Last Modified')
-            .'<span class="LC_fontsize_small"> &#9660;</span></a></th>'
-        .'<th><a href="'.$linkdir.'/?sortby=size&sortorder='
-            .((($sortby eq "size") && ($sortorder ne 'rev')) ? 'rev' : '') 
-            .'">'.&mt('Size').' (kB)'
-            .'<span class="LC_fontsize_small"> &#9660;</span></a></th>'
+        .&Apache::loncommon::start_data_table_header_row() . $output
         .&Apache::loncommon::end_data_table_header_row()
     );
 
     my $dirptr=16384;		# Mask indicating a directory in stat.cmode.
     my $filehash = {};
     foreach my $filename (@files) {
-        # Skip .DS_Store and hidden files
+        # Skip .DS_Store, .DAV and hidden files
         my ($extension) = ($filename=~/\.(\w+)$/);
-        next if (($filename eq '.DS_Store') 
-                || &Apache::loncommon::fileembstyle($extension) eq 'hdn');
+        next if (($filename eq '.DS_Store')
+                || ($filename eq '.DAV')
+                || (&Apache::loncommon::fileembstyle($extension) eq 'hdn')
+                || ($filename =~ /^\._/));
 
         my ($cmode,$csize,$cmtime)=(stat($fn.'/'.$filename))[2,7,9];
         my $linkfilename = &HTML::Entities::encode('/priv'.$thisdisfn.'/'.$filename,'<>&"');
@@ -240,14 +318,17 @@ sub handler {
 #   - The HTML header 
 #   - The H1/H3  stuff which includes the directory.
 #
-#     startpage($r, $uame, $udom, $thisdisfn);
+#     startpage($r, $uame, $udom, $thisdisfn, $current_disk_usage, $disk_quota);
 #      $r     - The apache request object.
 #      $uname - User name.
 #      $udom  - Domain name the user is logged in under.
 #      $thisdisfn - Displayable version of the filename.
+#      $current_disk_usage - User's current disk usage (in kB).
+#      $disk_quota - Disk quota for user's authoring space (in MB).
+#      $crstype - Course type, if this is for "course author"
 
 sub startpage {
-    my ($r, $uname, $udom, $thisdisfn) = @_;
+    my ($r, $uname, $udom, $thisdisfn, $current_disk_usage, $disk_quota) = @_;
     &Apache::loncommon::content_type($r,'text/html');
     $r->send_http_header;
 
@@ -269,11 +350,12 @@ sub startpage {
     my $londocroot = $Apache::lonnet::perlvar{'lonDocRoot'};
     my $current_disk_usage = &Apache::lonnet::diskusage($udom,$uname,"$londocroot/priv/$udom/$uname");
     my $disk_quota = &Apache::loncommon::get_user_quota($uname,$udom,'author'); #expressed in MB
-    $disk_quota = 1000 * $disk_quota; # convert from MB to kB
+    $disk_quota = 1024 * $disk_quota; # convert from MB to kB
 
     $r->print(&Apache::loncommon::head_subbox(
                      '<div style="float:right;padding-top:0;margin-top;0">'
-                    .&Apache::lonhtmlcommon::display_usage($current_disk_usage,$disk_quota)
+                    .&Apache::lonhtmlcommon::display_usage($current_disk_usage,
+                                                           $disk_quota,'authoring')
                     .'</div>'
                     .&Apache::loncommon::CSTR_pageheader()));
 
@@ -391,7 +473,7 @@ ENDPUBDIRSCRIPT
 }
 
 sub dircontrols {
-    my ($r,$uname,$udom,$thisdisfn) = @_;
+    my ($r,$uname,$udom,$thisdisfn, $current_disk_usage, $disk_quota) = @_;
     my %lt=&Apache::lonlocal::texthash(
                                        cnpd => 'Cannot publish directory',
                                        cnrd => 'Cannot retrieve directory',
@@ -427,6 +509,9 @@ sub dircontrols {
 				       pick => 'Please select an action to perform using the new filename',
                                       );
     my $mytype = $lt{'type'}; # avoid conflict with " and ' in javascript
+    # Calculate free space in bytes.
+    # $disk_quota is in MB and $current_disk_usage is in kB
+    my $free_space = 1024 * ((1024 * $disk_quota) - $current_disk_usage);
     $r->print(<<END);
 <div class="LC_columnSection">
   <div>
@@ -452,12 +537,13 @@ sub dircontrols {
     </form>
   </div>
 
-  <div>
+  <div style="padding-bottom: 2px">
     <form name="upublisher" enctype="multipart/form-data" method="post" action="/adm/upload" target="_parent">
       <fieldset>
         <legend>$lt{'updc'}</legend>
         <input type="hidden" name="filename" value="/priv$thisdisfn/" />
-        <input type="file" name="upfile" size="20" />
+        <input type="file" name="upfile" class="LC_flUpload" size="20" />
+        <input type="hidden" id="LC_free_space" value="$free_space" />
         <input type="button" value="$lt{'uplo'}"  onclick="checkUpload(this.form)" />
       </fieldset>
     </form>
@@ -491,7 +577,44 @@ sub dircontrols {
                     <option value="newtaskfile">$lt{'nbt'}:</option>
                     <option value="newlibraryfile">$lt{'nlib'}:</option>
 	            <option value="newdir">$lt{'nsub'}:</option>
-		  </select>&nbsp;<input type="text" name="newfilename" value="$lt{'type'}" onfocus="if (this.value == '$mytype') this.value=''" />&nbsp;<input type="button" value="Go" onclick="validate_go();" />
+		  </select>&nbsp;<input type="text" name="newfilename" placeholder="$lt{'type'}" value="" onfocus="if (this.value == is.empty()) this.value=''" />&nbsp;<input type="button" value="Go" onclick="validate_go();" />
+                <br />
+                <span>Quickactions:
+                 <input type="hidden" name="mode"/>
+                 <a href="javascript:void(0)" onclick="javascript:validate_action('blank')">
+                    <img src="/adm/lonIcons/unknown.gif" title="Create blank problem file"></a>
+                 <a href="javascript:void(0)" onclick="javascript:validate_action('problemtempl')">
+                    <img src="/adm/lonIcons/problem.gif" title="Create new problem from template"></a>
+                 <a href="javascript:void(0)" onclick="javascript:validate_action('blankhtml')">
+                    <img src="/adm/lonIcons/html.gif" title="Create new blank HTML file"></a>
+                 <a href="javascript:void(0)" onclick="javascript:validate_action('folder')">
+                    <img src="/adm/lonIcons/navmap.folder.closed.gif" title="Create new subdirectory"></a>
+                </span>
+                 <script type="text/javascript">
+                     function validate_action(action){
+
+                         if (document.getElementsByName(\'newfilename\')[0].value != \'\'){
+                             if (action == "blank") {
+                                                                 document.fileaction.action.value=\'newproblemfile\';
+                                                                 document.fileaction.mode.value=\'blank\';
+                                                         } else if (action == "problemtempl") {
+                                                                 document.fileaction.action.value=\'newproblemfile\';
+                                 validate_go();
+                             } else if (action == "blankhtml") {
+                                 document.fileaction.action.value=\'newhtmlfile\';
+                                 validate_go();
+                             } else if (action == "folder") {
+                                 document.fileaction.action.value=\'newdir\';
+                                 document.fileaction.mode.value=\'folder\';
+                             }
+                             fileaction.submit();
+                         } else {
+                             alert(\'Please specify file name.\');
+                             // TODO: ask for filename? if so, do some refactoring
+
+                         }
+                     }
+                 </script>
 		 </span>
       </fieldset>
     </form>