--- loncom/interface/portfolio.pm 2007/07/10 20:51:46 1.186 +++ loncom/interface/portfolio.pm 2020/09/08 23:54:40 1.262 @@ -1,7 +1,7 @@ # The LearningOnline Network # portfolio browser # -# $Id: portfolio.pm,v 1.186 2007/07/10 20:51:46 albertel Exp $ +# $Id: portfolio.pm,v 1.262 2020/09/08 23:54:40 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -38,7 +38,7 @@ use Apache::lonnet; use Apache::longroup; use Apache::lonhtmlcommon; use HTML::Entities; -use LONCAPA; +use LONCAPA qw(:DEFAULT :match); sub group_args { my $output; @@ -63,7 +63,7 @@ sub group_form_data { return $output; } -# receives a file name and path stub from username/userfiles/portfolio/ +# receives a filename and path stub from username/userfiles/portfolio/ # returns an anchor tag consisting encoding filename and currentpath sub make_anchor { my ($url, $anchor_fields, $inner_text) = @_; @@ -80,71 +80,90 @@ sub make_anchor { my $dirptr=16384; sub display_common { - my ($r,$url,$current_path,$is_empty,$dir_list,$can_upload)=@_; + my ($r,$url,$current_path,$is_empty,$dir_list,$can_upload,$group)=@_; my $namespace = &get_namespace(); my $port_path = &get_port_path(); if ($can_upload) { my $groupitem = &group_form_data(); my $iconpath= $r->dir_config('lonIconsURL') . "/"; - my %text=&Apache::lonlocal::texthash( - 'upload' => 'Upload', - 'upload_label' => - 'Upload file to current directory:', - 'createdir' => 'Create Subdirectory', - 'createdir_label' => - 'Create subdirectory in current directory:'); + my %lt=&Apache::lonlocal::texthash( + 'upload' => 'Upload', + 'upload_label' => 'Upload file to current directory', + 'createdir' => 'Create Subdirectory', + 'createdir_label' => 'Create subdirectory in current directory', + 'parse' => 'Upload embedded images/multimedia/css/linked files if HTML file', + ); my $escuri = &HTML::Entities::encode($r->uri,'&<>"'); my $help_fileupload = &Apache::loncommon::help_open_topic('Portfolio AddFiles'); my $help_createdir = &Apache::loncommon::help_open_topic('Portfolio CreateDirectory'); - - # FIXME: This line should be deleted once Portfolio uses breadcrumbs - $r->print(&Apache::loncommon::help_open_topic('Portfolio About', 'Help on the portfolio')); + my $help_portfolio = &Apache::loncommon::help_open_topic('Portfolio About', &mt('Help on the portfolio')); + $r->print(&display_portfolio_usage($group,$help_portfolio)); + my $parse_check; + if (!&suppress_embed_prompt()) { + $parse_check = <<"END"; +
+ + + +END + } + + # Find space available before uploading + my $free_space = &free_space($group); + + # Upload File + $r->print('
' + .'
' + .'
' + .''.$lt{'upload_label'}.'' + .$groupitem + .'' + .'' + .'' + .'' + .'' + .'' + .'' + .'' + .$help_fileupload + .$parse_check + .'
' + .'
' + .'
' + ); + # Create Subdirectory + $r->print('
' + .'
' + .'
' + .''.$lt{'createdir_label'}.'' + .''.$groupitem + .'' + .'' + .'' + .'' + .'' + .'' + .$help_createdir + .'
' + .'
' + .'
' + ); + } # end "if can_upload" - $r->print(<<"TABLE"); - - - - - - - - - -
- $text{'upload_label'} - -
- $groupitem - - - - - - $help_fileupload -
-
- $text{'createdir_label'} - -
- $groupitem - - - - - $help_createdir -
-
-TABLE - } my @tree = split (/\//,$current_path); my %anchor_fields = ( 'selectfile' => $port_path, 'currentpath' => '/', 'mode' => $env{"form.mode"}, + 'symb' => $env{"form.symb"}, 'fieldname' => $env{"form.fieldname"}, 'continue' => $env{"form.continue"} ); + $r->print('
'); $r->print(''.&make_anchor($url,\%anchor_fields,$port_path).'/'); if (@tree > 1){ my $newCurrentPath = '/'; @@ -154,6 +173,7 @@ TABLE 'selectfile' => $tree[$i], 'currentpath' => $newCurrentPath, 'mode' => $env{"form.mode"}, + 'symb' => $env{"form.symb"}, 'fieldname' => $env{"form.fieldname"}, 'continue' => $env{"form.continue"} ); @@ -163,27 +183,45 @@ TABLE $r->print(''); $r->print(&Apache::loncommon::help_open_topic('Portfolio ChangeDirectory')); &Apache::lonhtmlcommon::store_recent($namespace,$current_path,$current_path); - $r->print('
print('">'. &Apache::lonhtmlcommon::select_recent($namespace,'currentpath', 'this.form.submit();')); $r->print("
"); } +sub display_portfolio_usage { + my ($group,$helpitem) = @_; + my $disk_quota = &get_quota($group); + my $getpropath = 1; + my $portfolio_root = &get_portfolio_root(); + my ($uname,$udom) = &get_name_dom($group); + my $current_disk_usage = + &Apache::lonnet::diskusage($udom,$uname,$portfolio_root,$getpropath); + return &Apache::loncommon::head_subbox( + '
' + .$helpitem + .'
' + .'
' + .&Apache::lonhtmlcommon::display_usage($current_disk_usage, + $disk_quota,'portfolio') + .'
'); +} + sub display_directory_line { my ($r,$select_mode, $filename, $mtime, $size, $css_class, $line, $access_controls, $curr_access, $now, $version_flag, $href_location, $url, $current_path, $access_admin_text, $versions)=@_; my $fullpath = &prepend_group($current_path.$filename); - $r->print(''); + $r->print(&Apache::loncommon::start_data_table_row()); $r->print($line); # contains first two cells of table my $lock_info; if ($version_flag) { # versioned can't be versioned, so TRUE when root file - $r->print(''); + $r->print(''); $r->print(''.$version_flag.''); } else { # this is a graded or handed back file - my ($user,$domain) = &get_name_dom(); + my ($user,$domain) = &get_name_dom($env{'form.group'}); my $permissions_hash = &Apache::lonnet::get_portfile_permissions($domain,$user); if (defined($$permissions_hash{$fullpath})) { foreach my $array_item (@{$$permissions_hash{$fullpath}}) { @@ -199,7 +237,7 @@ sub display_directory_line { if ($lock_info) { my %anchor_fields = ('lockinfo' => $fullpath); if ($versions) { # hold the folder open - my ($fname,$version,$extension) = &Apache::grades::file_name_version_ext($fullpath); + my ($fname,$version,$extension) = &Apache::lonnet::file_name_version_ext($fullpath); $fname =~ s|^/||; $anchor_fields{'showversions'} = $fname.'.'.$extension; } @@ -212,26 +250,29 @@ sub display_directory_line { $r->print(''.$size.''); $r->print(''.&Apache::lonlocal::locallocaltime($mtime).''); if ($select_mode ne 'true') { - $r->print(''. - &mt($curr_access).'   '); + $r->print('  '); # Display status + $r->print('' + .&mt($curr_access).'   ' + ); my %anchor_fields = ( 'access' => $filename, 'currentpath' => $current_path ); $r->print(&make_anchor($url, \%anchor_fields, $access_admin_text).''); + } else { + $r->print('  '); # Display status } - $r->print(''.$/); + $r->print(&Apache::loncommon::end_data_table_row().$/); } sub display_directory { my ($r,$url,$current_path,$is_empty,$dir_list,$group,$can_upload, $can_modify,$can_delete,$can_setacl)=@_; my $iconpath= $r->dir_config('lonIconsURL') . "/"; - my $display_out; my $select_mode; my $checked_files; my $port_path = &get_port_path(); - my ($uname,$udom) = &get_name_dom(); + my ($uname,$udom) = &get_name_dom($group); my $access_admin_text = &mt('View Status'); if ($can_setacl) { $access_admin_text = &mt('View/Change Status'); @@ -244,65 +285,105 @@ sub display_directory { my %access_controls = &Apache::lonnet::get_access_controls($current_permissions,$group); my $now = time; if ($env{"form.mode"} eq 'selectfile') { - &select_files($r); - $checked_files =&Apache::lonnet::files_in_path($uname,$env{'form.currentpath'}); - $select_mode = 'true'; - } - if ($is_empty && ($current_path ne '/') && $can_delete) { - $display_out = '
'. - &group_form_data(). - ''. - ''. - ''. - ''. - '
'; - - $r->print($display_out); - return; + &select_files($r,$dir_list); + $checked_files =&Apache::lonnet::files_in_path($uname,$env{'form.currentpath'}); + $select_mode = 'true'; } if ($select_mode eq 'true') { $r->print('
'); - $r->print(''. - ''); + $r->print(&Apache::loncommon::start_data_table() + .&Apache::loncommon::start_data_table_header_row() + .'' + .'' + .'' + .'' + .'' + .'' + .'' + .&Apache::loncommon::end_data_table_header_row() + ); } else { $r->print(''); - $r->print(&Apache::loncommon::help_open_topic('Portfolio FileList', - 'Using the portfolio file list')); - $r->print('
Select  NameSizeLast Modified
'.&mt('Select').'  '.&mt('Name').''.&mt('Size').''.&mt('Last Modified').' 
'. - ''); + $r->print( + '

' + .&Apache::loncommon::help_open_topic( + 'Portfolio FileList', + &mt('Using the portfolio file list')) + .'

' + ); + $r->print(&Apache::loncommon::start_data_table() + .&Apache::loncommon::start_data_table_header_row() + .'' + .'' + .'' + .'' + .'' + .'' + .'' + .'' + .&Apache::loncommon::end_data_table_header_row()); } + + # Empty directory? + if ($is_empty && ($current_path ne '/') && $can_delete) { + my $cols = ($select_mode eq 'true') ? 7 : 9; + # Empty message + $r->print( + &Apache::loncommon::start_data_table_row() + .'' + .&Apache::loncommon::end_data_table_row() + .&Apache::loncommon::end_data_table() + .'' + ); + # Delete button + $r->print( + ''. + &group_form_data(). + ''. + '

'. + ''. + '

'. + ''. + ''. + '' + ); + # Directory is empty, so nothing else to display + return; + } + $r->print("\n".&group_form_data()."\n"); my $href_location="/uploaded/$udom/$uname/$port_path".$current_path; my $href_edit_location="/editupload/$udom/$uname/$port_path".$current_path; my @dir_lines; my %versioned; - foreach my $dir_line (sort - { - my ($afile)=split('&',$a,2); - my ($bfile)=split('&',$b,2); - return (lc($afile) cmp lc($bfile)); - } (@$dir_list)) { - my ($filename,$dom,undef,$testdir,undef,undef,undef,undef,$size,undef,$mtime,undef,undef,undef,$obs,undef)=split(/\&/,$dir_line,16); - $filename =~ s/\s+$//; - my ($fname,$version,$extension) = &Apache::grades::file_name_version_ext($filename); - if ($version) { - my $fullpath = &prepend_group($current_path.$fname.'.'.$extension); - push(@{ $versioned{$fullpath} }, - [$filename,$dom,$testdir,$size,$mtime,$obs,]); - } else { - push(@dir_lines, [$filename,$dom,$testdir,$size,$mtime,$obs]); - } + if (ref($dir_list) eq 'ARRAY') { + foreach my $dir_line (sort + { + my ($afile)=split('&',$a,2); + my ($bfile)=split('&',$b,2); + return (lc($afile) cmp lc($bfile)); + } (@{$dir_list})) { + my ($filename,$dom,undef,$testdir,undef,undef,undef,undef,$size,undef,$mtime,undef,undef,undef,$obs,undef)=split(/\&/,$dir_line,16); + $filename =~ s/\s+$//; + my ($fname,$version,$extension) = &Apache::lonnet::file_name_version_ext($filename); + if ($version) { + my $fullpath = &prepend_group($current_path.$fname.'.'.$extension); + push(@{ $versioned{$fullpath} }, + [$filename,$dom,$testdir,$size,$mtime,$obs,]); + } else { + push(@dir_lines, [$filename,$dom,$testdir,$size,$mtime,$obs]); + } + } } + my $zerobyte; foreach my $dir_line (@dir_lines) { my ($filename,$dom,$testdir,$size,$mtime,$obs) = @$dir_line; - my ($fname,$version,$extension) = &Apache::grades::file_name_version_ext($filename); + my ($fname,$version,$extension) = &Apache::lonnet::file_name_version_ext($filename); if (($filename ne '.') && ($filename ne '..') && ($filename !~ /\.meta$/ ) && ($filename !~ /(.*)\.(\d+)\.([^\.]*)$/)) { my $version_flag; my $show_versions; @@ -333,36 +414,49 @@ sub display_directory { $version_flag = ' '; } if ($dirptr&$testdir) { - my $colspan='colspan="2"'; + my $colspan_folder=''; + my $colspan_fill=''; if ($select_mode eq 'true'){ - undef($colspan); + $colspan_fill=' colspan="3"'; + } else { + $colspan_folder=' colspan="2"'; + $colspan_fill=' colspan="4"'; } - $r->print(''); - $r->print(''); + $r->print(''); + $r->print(''.&mt('closed folder').'' + .''); my %anchor_fields = ( 'selectfile' => $filename.'/', 'currentpath' => $current_path.$filename.'/', 'mode' => $env{"form.mode"}, + 'symb' => $env{"form.symb"}, 'fieldname' => $env{"form.fieldname"}, 'continue' => $env{"form.continue"} ); - $r->print(''); + $r->print('' + .''); + $r->print(' '); $r->print(''); } else { my $css_class = 'LC_browser_file'; my $line; if ($select_mode eq 'true') { - $line=''; + $line.=''; $css_class= 'LC_browser_file_locked'; } else { if (!$can_modify) { @@ -374,13 +468,12 @@ sub display_directory { $line .= ''; } if ($can_modify) { - my $cat=''.&mt('Catalog Information').
-                            ''; + my $cat=''.&mt('Metadata').''; my %anchor_fields = ( 'rename' => $filename, currentpath => $current_path ); - $line .= &make_anchor($url,\%anchor_fields,'Rename'); + $line .= &make_anchor($url,\%anchor_fields,&mt('Rename')); $line .= '
Actions'. - &Apache::loncommon::help_open_topic('Portfolio FileAction'). - '  Name'. - &Apache::loncommon::help_open_topic('Portfolio OpenFile'). - 'SizeLast ModifiedCurrent Access Status'. - &Apache::loncommon::help_open_topic('Portfolio ShareFile'). - '
'.&mt('Actions'). &Apache::loncommon::help_open_topic('Portfolio FileAction').'  '.&mt('Name').&Apache::loncommon::help_open_topic('Portfolio OpenFile').''.&mt('Size').''.&mt('Last Modified').' '.&mt('Current Access Status').&Apache::loncommon::help_open_topic('Portfolio ShareFile').'' + .'

' + .&mt('This directory is empty.') + .'

' + .'
'.&mt('closed folder').'Go to ...
'.&mt('Go to ...').''.$version_flag.''.&make_anchor($url,\%anchor_fields,$filename.'/').''.$version_flag.''.&make_anchor($url,\%anchor_fields,$filename.'/').'
0) { + $line=' $fullpath ); - $line.=''.&make_anchor($url,\%anchor_fields,'Locked').''.&make_anchor($url,\%anchor_fields,&mt('Locked')).''.&make_anchor($href_edit_location.$filename.'.meta',\%anchor_fields,$cat); # ''.$cat.''; } @@ -437,20 +530,29 @@ sub display_directory { } } if ($select_mode eq 'true') { - $r->print('
+ $r->print(&Apache::loncommon::end_data_table()); + if ($zerobyte) { + $r->print('

'.&mt('[quant,_1,file] in list not selectable as file size is 0 bytes.',$zerobyte).'

'); + } + $r->print(' + -
- +

+
+ +

'); } else { - $r->print(''); + $r->print(&Apache::loncommon::end_data_table()); if ($can_delete) { $r->print(' - '. +

+ '. &Apache::loncommon::help_open_topic('Portfolio DeleteFile').' +

' @@ -515,37 +617,43 @@ sub display_file { } sub done { - my ($message,$url)=@_; - unless (defined $message) { - $message='Done'; + my ($linktext,$url)=@_; + unless (defined($linktext)) { + $linktext='Return to directory'; } my %anchor_fields = ( 'showversions' => $env{'form.showversions'}, 'currentpath' => $env{'form.currentpath'}, 'fieldname' => $env{'form.fieldname'}, + 'symb' => $env{'form.symb'}, 'mode' => $env{'form.mode'} ); - my $result = '

'.&make_anchor($url,\%anchor_fields,&mt($message)).'

'; + my $result = &Apache::lonhtmlcommon::actionbox( + [&make_anchor($url,\%anchor_fields,&mt($linktext))]); return $result; } sub delete { - my ($r,$url)=@_; + my ($r,$url,$group)=@_; my @check; my $file_name = $env{'form.currentpath'}.$env{'form.selectfile'}; $file_name = &prepend_group($file_name); my @files=&Apache::loncommon::get_env_multiple('form.selectfile'); - my ($uname,$udom) = &get_name_dom(); + my ($uname,$udom) = &get_name_dom($group); if (&Apache::lonnet::is_locked($file_name,$udom,$uname) eq 'true') { - $r->print("The file is locked and cannot be deleted.
"); - $r->print(&done('Back',$url)); + $r->print( + '

' + .&mt('The file is locked and cannot be deleted.') + .'

' + .&done(undef,$url) + ); } else { if (scalar(@files)) { &open_form($r,$url); - $r->print('

'.&mt('Delete').' '.&display_file(undef,\@files).'?

'); + $r->print('

'.&mt('Delete [_1]?',&display_file(undef,\@files)).'

'); &close_form($r,$url); } else { - $r->print("No file was checked to delete.
"); + $r->print('

'.&mt('No file was checked to delete.').'

'); $r->print(&done(undef,$url)); } } @@ -555,22 +663,25 @@ sub delete_confirmed { my ($r,$url,$group)=@_; my @files=&Apache::loncommon::get_env_multiple('form.selectfile'); my $result; - my ($uname,$udom) = &get_name_dom(); + my ($uname,$udom) = &get_name_dom($group); my $port_path = &get_port_path(); my $current_permissions = &Apache::lonnet::get_portfile_permissions($udom, $uname); + my @msg; foreach my $delete_file (@files) { - $result=&Apache::lonnet::removeuserfile($uname,$udom,$port_path. - $env{'form.currentpath'}. - $delete_file); + $result = + &Apache::lonnet::removeuserfile( + $uname,$udom,$port_path. + $env{'form.currentpath'}. + $delete_file); if ($result ne 'ok') { - $r->print(''. - &mt('An error occurred ([_1]) while trying to delete - [_2].',$result,&display_file(undef, $delete_file)). - '

'); - } else { - $r->print(&mt('File: [_1] deleted.', - &display_file(undef,$delete_file))); + push(@msg, &Apache::lonhtmlcommon::confirm_success( + &mt('An error occurred ([_1]) while trying to delete [_2].' + ,$result,&display_file(undef, $delete_file)),1)); + } else { + push(@msg, &Apache::lonhtmlcommon::confirm_success( + &mt('File: [_1] deleted.' + ,&display_file(undef,$delete_file)))); my $file_name = $env{'form.currentpath'}.$delete_file; $file_name = &prepend_group($file_name); my %access_controls = @@ -586,46 +697,52 @@ sub delete_confirmed { &Apache::lonnet::modify_access_controls($file_name,\%changes, $udom,$uname); if ($outcome ne 'ok') { - $r->print('
'.&mt("An error occurred ([_1]) while ". - "trying to delete access controls for the file.",$outcome). - '

'); + push(@msg, &Apache::lonhtmlcommon::confirm_success( + &mt('An error occurred ([_1]) while '. + 'trying to delete access controls for the file.',$outcome),1)); } else { if ($deloutcome eq 'ok') { - $r->print('
'.&mt('Access controls also deleted for the file.').'

'); + push(@msg, &mt('Access controls also deleted for the file.')); # FIXME: Does the user really need this message? } else { - $r->print(''.'
'. - &mt("An error occurred ([_1]) while ". - "trying to delete access controls for the file.",$deloutcome). - '


'); + push(@msg, &Apache::lonhtmlcommon::confirm_success( + &mt('An error occurred ([_1]) while '. + 'trying to delete access controls for the file.' + ,$deloutcome),1)); } } } } } } + $r->print(&Apache::loncommon::confirmwrapper(join('
',@msg))); $r->print(&done(undef,$url)); } sub delete_dir { my ($r,$url)=@_; &open_form($r,$url); - $r->print('

'.&mt('Delete').' '.&display_file().'?

'); + $r->print('

'.&mt('Delete [_1]?',&display_file()).'

'); &close_form($r,$url); } sub delete_dir_confirmed { - my ($r,$url)=@_; + my ($r,$url,$group)=@_; my $directory_name = $env{'form.currentpath'}; $directory_name =~ s|/$||; # remove any trailing slash - my ($uname,$udom) = &get_name_dom(); + my ($uname,$udom) = &get_name_dom($group); my $namespace = &get_namespace(); my $port_path = &get_port_path(); my $result=&Apache::lonnet::removeuserfile($uname,$udom,$port_path. $directory_name); - + if ($result ne 'ok') { - $r->print(' An error occurred (dir) ('.$result. - ') while trying to delete '.$directory_name.'
'); + $r->print( + &Apache::loncommon::confirmwrapper( + &Apache::lonhtmlcommon::confirm_success( + &mt('An error occurred (dir) ([_1]) while trying to delete [_2].' + ,$result,$directory_name),1))); + $r->print(&done(undef,$url)); + return; } else { # now remove from recent &Apache::lonhtmlcommon::remove_recent($namespace,[$directory_name.'/']); @@ -636,21 +753,29 @@ sub delete_dir_confirmed { } $env{'form.currentpath'} = $directory_name; } + $r->print( + &Apache::loncommon::confirmwrapper( + &Apache::lonhtmlcommon::confirm_success( + &mt('Directory successfully deleted')))); $r->print(&done(undef,$url)); } sub rename { - my ($r,$url)=@_; + my ($r,$url,$group)=@_; my $file_name = $env{'form.currentpath'}.$env{'form.rename'}; - my ($uname,$udom) = &get_name_dom(); + my ($uname,$udom) = &get_name_dom($group); $file_name = &prepend_group($file_name); if (&Apache::lonnet::is_locked($file_name,$udom,$uname) eq 'true') { - $r->print("The file is locked and cannot be renamed.
"); + $r->print( + '

' + .&mt('The file is locked and cannot be renamed.') + .'

' + ); $r->print(&done(undef,$url)); } else { &open_form($r,$url); - $r->print('

'.&mt('Rename').' '.&display_file().' to - ?

'); + $r->print('

'.&mt('Rename [_1] to [_2]?', &display_file() + , '').'

'); &close_form($r,$url); } } @@ -658,15 +783,34 @@ sub rename { sub rename_confirmed { my ($r,$url,$group)=@_; my $filenewname=&Apache::lonnet::clean_filename($env{'form.filenewname'}); - my ($uname,$udom) = &get_name_dom(); + my ($uname,$udom) = &get_name_dom($group); my $port_path = &get_port_path(); + + # Display warning in case of filename cleaning has changed the filename + if ($filenewname ne $env{'form.filenewname'}) { + $r->print( + '

' + .&mt('Invalid characters') + .'
' + .&mt('The new filename was changed from [_1] to [_2].' + ,''.&display_file('',$env{'form.filenewname'}).'' + ,''.&display_file('',$filenewname).'') + .'

' + ); + + } + + # Filename empty? if ($filenewname eq '') { - $r->print(''. - &mt("Error: no valid filename was provided to rename to."). - '
'); - $r->print(&done(undef,$url)); - return; + $r->print( + &Apache::loncommon::confirmwrapper( + &Apache::lonhtmlcommon::confirm_success( + &mt('Error: no valid filename was provided to rename to.'),1))); + $r->print(&done(undef,$url)); + return; } + + # Rename the file my $chg_access; my $result= &Apache::lonnet::renameuserfile($uname,$udom, @@ -675,18 +819,20 @@ sub rename_confirmed { if ($result eq 'ok') { $chg_access = &access_for_renamed($filenewname,$group,$udom,$uname); } else { - $r->print(''. - &mt('An error occurred ([_1]) while trying to rename [_2]' - .' to [_3]',$result,&display_file(), - &display_file('',$filenewname)).'
'); + $r->print( + &Apache::loncommon::confirmwrapper( + &Apache::lonhtmlcommon::confirm_success( + &mt('An error occurred ([_1]) while trying to rename [_2] to [_3].' + ,$result,&display_file(),&display_file('',$filenewname)) + ,1))); + $r->print(&done(undef,$url)); return; } - if ($filenewname ne $env{'form.filenewname'}) { - $r->print(&mt("The new file name was changed from:
[_1] to [_2]", - ''.&display_file('',$env{'form.filenewname'}).'', - ''.&display_file('',$filenewname).'')); - } $r->print($chg_access); + $r->print( + &Apache::loncommon::confirmwrapper( + &Apache::lonhtmlcommon::confirm_success( + &mt('File successfully renamed')))); $r->print(&done(undef,$url)); } @@ -742,7 +888,7 @@ sub access_for_renamed { sub display_access { my ($r,$url,$group,$can_setacl,$port_path,$action) = @_; - my ($uname,$udom) = &get_name_dom(); + my ($uname,$udom) = &get_name_dom($group); my $file_name = $env{'form.currentpath'}.$env{'form.access'}; $file_name = &prepend_group($file_name); my $current_permissions = &Apache::lonnet::get_portfile_permissions($udom, @@ -751,21 +897,27 @@ sub display_access { my $aclcount = keys(%access_controls); my ($header,$info); if ($action eq 'chgaccess') { - $header = '

'.&mt('Allowing others to retrieve file: [_1]',$port_path.$env{'form.currentpath'}.$env{'form.access'}).'

'; + $header = + '

' + .&mt('Allowing others to retrieve file: [_1]' + ,'' + .$port_path.$env{'form.currentpath'}.$env{'form.access'} + .'') + .'

'; $info .= &mt('Access to this file by others can be set to be one or more of the following types: public, passphrase-protected or conditional.'); $info .= '
'. - &mt('A listing of files viewable without log-in is available at: ')."http://$ENV{'SERVER_NAME'}/adm/$udom/$uname/aboutme/portfolio.
"; + &mt('A listing of files viewable without log-in is available at: ')."".&Apache::lonnet::absolute_url($ENV{'SERVER_NAME'})."/adm/$udom/$uname/aboutme/portfolio.
"; if ($group eq '') { $info .= &mt("For logged in users a 'Display file listing' link will also appear (when there are viewable files) on your personal information page:"); } else { $info .= &mt("For logged in users a 'Display file listing' link will also appear (when there are viewable files) on the course information page:"); } - $info .= "
http://$ENV{'SERVER_NAME'}/adm/$udom/$uname/aboutme
"; + $info .= "
".&Apache::lonnet::absolute_url($ENV{'SERVER_NAME'})."/adm/$udom/$uname/aboutme
"; if ($group ne '') { - $info .= &mt("Users with privileges to edit course contents may add a course information page to a course using the 'Course Info' button in DOCS").'
'; + $info .= &mt("Users with course editing rights may add a 'Group Portfolio' item using the Course Editor (Collaboration tab), to provide access to viewable group portfolio files.").'
'; } } else { $header = '

'.&mt('Conditional access controls for file: [_1]',$port_path.$env{'form.currentpath'}.$env{'form.access'}).'

'. @@ -774,14 +926,14 @@ sub display_access { if ($can_setacl) { &open_form($r,$url); $r->print($header.$info); - $r->print('
'.&Apache::loncommon::help_open_topic('Portfolio ShareFile SetAccess', 'Help on setting up share access')); - $r->print(&Apache::loncommon::help_open_topic('Portfolio ShareFile ChangeSetting', 'Help on changing settings')); - $r->print(&Apache::loncommon::help_open_topic('Portfolio ShareFile StopAccess', 'Help on removing share access')); + $r->print('
'.&Apache::loncommon::help_open_topic('Portfolio ShareFile SetAccess', &mt('Help on setting up share access'))); + $r->print(&Apache::loncommon::help_open_topic('Portfolio ShareFile ChangeSetting', &mt('Help on changing settings'))); + $r->print(&Apache::loncommon::help_open_topic('Portfolio ShareFile StopAccess', &mt('Help on removing share access'))); &access_setting_table($r,$url,$file_name,$access_controls{$file_name}, $action); my $button_text = { 'continue' => &mt('Proceed'), - 'cancel' => &mt('Back to directory listing'), + 'cancel' => &mt('Return to directory'), }; &close_form($r,$url,$button_text); } else { @@ -795,9 +947,11 @@ sub display_access { sub explain_conditionals { return - &mt('Conditional files are accessible to logged-in users with accounts in the LON-CAPA network, who satisfy the conditions you set.').'
'."\n". - &mt('The conditions can include affiliation with a particular course, or a user account in a specific domain.').'
'."\n". - &mt('Alternatively access can be granted to people with specific LON-CAPA usernames and domains.'); + &mt('Conditional files are accessible to users who satisfy the conditions you set.').'
'; } sub view_access_settings { @@ -809,7 +963,7 @@ sub view_access_settings { $todisplay{$scope}{$key} = $$access_controls{$key}; } if ($aclcount) { - $r->print(&mt('

Current access controls defined for this file:

')); + $r->print('

'.&mt('Current access controls defined for this file:').'

'); $r->print(&Apache::loncommon::start_data_table()); $r->print(&Apache::loncommon::start_data_table_header_row()); $r->print(''.&mt('Access control').''.&mt('Dates available'). @@ -820,12 +974,12 @@ sub view_access_settings { &build_access_summary($r,$count,$chg,%todisplay); $r->print(&Apache::loncommon::end_data_table()); } else { - $r->print(&mt('No access control settings currently exist for this file.
' )); + $r->print(&mt('No access control settings currently exist for this file.').'
'); } my %anchor_fields = ( 'currentpath' => $env{'form.currentpath'} ); - $r->print('
'.&make_anchor($url, \%anchor_fields, &mt('Return to directory listing'))); + $r->print('
'.&make_anchor($url, \%anchor_fields, &mt('Return to directory'))); return; } @@ -837,9 +991,10 @@ sub build_access_summary { guest => 'Passphrase-protected', domains => 'Conditional: domain-based', users => 'Conditional: user-based', - course => 'Conditional: course-based', + course => 'Conditional: course/community-based', + ip => 'Conditional: IP-based', ); - my @allscopes = ('public','guest','domains','users','course'); + my @allscopes = ('public','guest','domains','users','course','ip'); foreach my $scope (@allscopes) { if ((!(exists($todisplay{$scope}))) || (ref($todisplay{$scope}) ne 'HASH')) { next; @@ -854,19 +1009,24 @@ sub build_access_summary { $showstart = &mt('Deleted'); $showend = $showstart; } else { - $showstart = localtime($start); + $showstart = &Apache::lonlocal::locallocaltime($start); if ($end == 0) { $showend = &mt('No end date'); } else { - $showend = localtime($end); + $showend = &Apache::lonlocal::locallocaltime($end); } } $r->print(''.&mt($scope_desc{$scope})); + my $crstype; if ($scope eq 'course') { if ($chg ne 'delete') { my $cid = $content->{'domain'}.'_'.$content->{'number'}; my %course_description = &Apache::lonnet::coursedescription($cid); $r->print('
('.$course_description{'description'}.')'); + $crstype = 'Course'; + if ($course_description{'type'} ne '') { + $crstype = $course_description{'type'}; + } } } $r->print(''.&mt('Start: ').$showstart. @@ -886,8 +1046,6 @@ sub build_access_summary { foreach my $item ('role','access','section','group') { $r->print(''); if ($item eq 'role') { - my $ucscope = $scope; - $ucscope =~ s/^(\w)/uc($1)/e; my $role_output; foreach my $role (@{$content->{'roles'}{$id}{$item}}) { if ($role eq 'all') { @@ -895,7 +1053,7 @@ sub build_access_summary { } elsif ($role =~ /^cr/) { $role_output .= (split('/',$role))[3].','; } else { - $role_output .= &Apache::lonnet::plaintext($role,$ucscope).','; + $role_output .= &Apache::lonnet::plaintext($role,$crstype).','; } } $role_output =~ s/,$//; @@ -913,6 +1071,9 @@ sub build_access_summary { } elsif ($scope eq 'users') { my $curr_user_list = &sort_users($content->{'users'}); $r->print(&mt('Users: ').$curr_user_list); + } elsif ($scope eq 'ip') { + my $curr_ips_list = &sort_ips($content->{'ip'}); + $r->print(&mt('IP(s):').' '.$curr_ips_list); } else { $r->print(' '); } @@ -953,10 +1114,10 @@ sub update_access { } } my $file_name = $env{'form.currentpath'}.$env{'form.selectfile'}; - $r->print('

'.&mt('Allowing others to retrieve file: [_1]', - $port_path.$file_name).'

'."\n"); + $r->print('

'.&mt('Allowing others to retrieve file: [_1]', + ''.$port_path.$file_name.'').'

'."\n"); $file_name = &prepend_group($file_name); - my ($uname,$udom) = &get_name_dom(); + my ($uname,$udom) = &get_name_dom($group); my ($errors,$outcome,$deloutcome,$new_values,$translation); if ($totalprocessed) { ($outcome,$deloutcome,$new_values,$translation) = @@ -1021,26 +1182,38 @@ sub update_access { my $totalnew = 0; my $status = 'new'; my ($firstitem,$lastitem); - foreach my $newitem ('course','domains','users') { + my @types = ('course','domains','users','ip'); + foreach my $newitem (@types) { $allnew += $env{'form.new'.$newitem}; } if ($allnew > 0) { my $now = time; my $then = $now + (60*60*24*180); # six months approx. &open_form($r,$url); - foreach my $newitem ('course','domains','users') { - if ($env{'form.new'.$newitem} > 0) { - $r->print('
'.&mt('Add new [_1]-based access control for portfolio file: [_2]',$newitem,$env{'form.currentpath'}.$env{'form.selectfile'}).'

'); - $firstitem = $totalnew; - $lastitem = $totalnew + $env{'form.new'.$newitem}; - $totalnew = $lastitem; - my @numbers; - for (my $i=$firstitem; $i<$lastitem; $i++) { - push (@numbers,$i); - } - &display_access_row($r,$status,$newitem,\@numbers, - $access_controls{$file_name},$now,$then); + my %showtypes = ( + course => 'course/community', + domains => 'domain', + users => 'user', + ip => 'IP', + ); + foreach my $newitem (@types) { + next if ($env{'form.new'.$newitem} <= 0); + $r->print( + '

' + .&mt('Add new [_1]'.$showtypes{$newitem}.'-based[_2] access control for portfolio file: [_3]', + '','', + '' + .$env{'form.currentpath'}.$env{'form.selectfile'}.'') + .'

'); + $firstitem = $totalnew; + $lastitem = $totalnew + $env{'form.new'.$newitem}; + $totalnew = $lastitem; + my @numbers; + for (my $i=$firstitem; $i<$lastitem; $i++) { + push(@numbers,$i); } + &display_access_row($r,$status,$newitem,\@numbers, + $access_controls{$file_name},$now,$then); } &close_form($r,$url); } else { @@ -1048,9 +1221,11 @@ sub update_access { 'currentpath' => $env{'form.currentpath'}, 'access' => $env{'form.selectfile'} ); - $r->print('
'.&make_anchor($url, \%anchor_fields, &mt('Display all access settings for this file'))); + my @actions; + push(@actions, &make_anchor($url, \%anchor_fields, &mt('Display all access settings for this file'))); delete $anchor_fields{'access'}; - $r->print('     '.&make_anchor($url,\%anchor_fields,&mt('Return to directory listing'))); + push(@actions, &make_anchor($url,\%anchor_fields,&mt('Return to directory'))); + $r->print('
'.&Apache::lonhtmlcommon::actionbox(\@actions)); } return; } @@ -1123,6 +1298,13 @@ sub build_access_record { 'udom' => $udom }); } + } elsif ($scope eq 'ip') { + my $ipslist = $env{'form.ips_'.$num}; + $ipslist =~ s/\s+//sg; + my %ipshash = map { ($_,1) } (split(/,/,$ipslist)); + foreach my $ip (keys(%ipshash)) { + push(@{$record->{'ip'}},$ip); + } } return $record; } @@ -1148,6 +1330,13 @@ sub sort_users { return $curr_user_list; } +sub sort_ips { + my ($ips) = @_; + if (ref($ips) eq 'ARRAY') { + return join(",\n",sort(@{$ips})); + } +} + sub access_setting_table { my ($r,$url,$filename,$access_controls,$action) = @_; my ($public,$publictext); @@ -1157,6 +1346,7 @@ sub access_setting_table { my @courses = (); my @domains = (); my @users = (); + my @ips = (); my $now = time; my $then = $now + (60*60*24*180); # six months approx. my ($num,$scope,$publicnum,$guestnum); @@ -1179,6 +1369,8 @@ sub access_setting_table { push(@domains,$key); } elsif ($scope eq 'users') { push(@users,$key); + } elsif ($scope eq 'ip') { + push(@ips,$key); } } $acl_count{$scope} ++; @@ -1190,7 +1382,7 @@ sub access_setting_table { $guesttext,$access_controls,%conditionals); } else { &condition_setting($r,$access_controls,$now,$then,\%acl_count, - \@domains,\@users,\@courses); + \@domains,\@users,\@courses,\@ips); } $r->print(''); } @@ -1198,7 +1390,7 @@ sub access_setting_table { sub standard_settings { my ($r,$now,$then,$url,$filename,$acl_count,$start,$end,$public,$publicnum, $publictext,$guest,$guestnum,$guesttext,$access_controls,%conditionals)=@_; - $r->print('

'.&mt('Public access: [_1]',$publictext).'

'); + $r->print('

'.&mt('Public access: [_1]',&mt($publictext)).'

'); $r->print(&Apache::loncommon::start_data_table()); $r->print(&Apache::loncommon::start_data_table_header_row()); $r->print(''.&mt('Action').''.&mt('Dates available').''); @@ -1214,7 +1406,7 @@ sub standard_settings { $r->print(&Apache::loncommon::end_data_table_row()); $r->print(&Apache::loncommon::end_data_table()); $r->print(' '); - $r->print('

'.&mt('Passphrase-protected access: [_1]',$guesttext).'

'); + $r->print('

'.&mt('Passphrase-protected access: [_1]',&mt($guesttext)).'

'); $r->print(&Apache::loncommon::start_data_table()); $r->print(&Apache::loncommon::start_data_table_header_row()); $r->print(''.&mt('Action').''.&mt('Dates available'). @@ -1235,14 +1427,14 @@ sub standard_settings { $r->print(&Apache::loncommon::end_data_table_row()); $r->print(&Apache::loncommon::end_data_table()); $r->print(' '. - ''); + ''); my $numconditionals = 0; my $conditionstext; my %cond_status; - foreach my $scope ('domains','users','course') { + foreach my $scope ('domains','users','course','ip') { $numconditionals += $acl_count->{$scope}; if ($acl_count->{$scope} > 0) { - if ($conditionstext ne 'Active') { + if ($conditionstext ne 'Active') { foreach my $key (keys(%{$conditionals{$scope}})) { $conditionstext = &acl_status($start->{$key},$end->{$key},$now); if ($conditionstext eq 'Active') { @@ -1260,7 +1452,7 @@ sub standard_settings { 'action' => 'chgconditions', 'currentpath' => $env{'form.currentpath'}, ); - $r->print('

'.&mt('Conditional access: [_1]',$conditionstext).'

'); + $r->print('

'.&mt('Conditional access: [_1]',&mt($conditionstext)).'

'); if ($numconditionals > 0) { my $count = 1; my $chg = 'none'; @@ -1273,24 +1465,20 @@ sub standard_settings { &build_access_summary($r,$count,$chg,%conditionals); $r->print(&Apache::loncommon::end_data_table()); } else { - $r->print(&make_anchor($url,\%anchor_fields,&mt('Add conditional access')).' '.&mt('based on domain, username, or course affiliation.')); + $r->print(&make_anchor($url,\%anchor_fields,&mt('Add conditional access')).' '.&mt("based on domain, username, course/community affiliation or user's IP address.")); } } sub condition_setting { - my ($r,$access_controls,$now,$then,$acl_count,$domains,$users,$courses) = @_; + my ($r,$access_controls,$now,$then,$acl_count,$domains,$users,$courses,$ips) = @_; $r->print(''); &access_element($r,'domains',$acl_count,$domains,$access_controls,$now,$then); $r->print(' '); &access_element($r,'users',$acl_count,$users,$access_controls,$now,$then); - $r->print(''); - if ($acl_count->{course} > 0) { - $r->print(''); - } else { - $r->print(''); - } + $r->print(''); &access_element($r,'course',$acl_count,$courses,$access_controls,$now,$then); - $r->print(''); + $r->print(' '); + &access_element($r,'ip',$acl_count,$ips,$access_controls,$now,$then); $r->print(''); } @@ -1307,17 +1495,15 @@ sub acl_status { sub access_element { my ($r,$type,$acl_count,$items,$access_controls,$now,$then) = @_; - my $title = $type; - $title =~ s/s$//; - $title =~ s/^(\w)/uc($1)/e; - $r->print('

'.&mt('[_1]-based conditional access: ',$title)); + my %typetext = ( + domains => 'Domain', + users => 'User', + course => 'Course/Community', + ip => 'IP', + ); + $r->print('

'.&mt($typetext{$type}.'-based conditional access:').' '); if ($$acl_count{$type}) { - $r->print($$acl_count{$type}.' '); - if ($$acl_count{$type} > 1) { - $r->print(&mt('conditions')); - } else { - $r->print(&mt('condition')); - } + $r->print(&mt('[quant,_1,condition]',$$acl_count{$type})); } else { $r->print(&mt('Off')); } @@ -1328,17 +1514,29 @@ sub access_element { sub display_access_row { my ($r,$status,$type,$items,$access_controls,$now,$then) = @_; + my ($showtype, $infotype); + if ($type eq 'course') { + $showtype = &mt('Courses/Communities'); + $infotype = 'Course/Community'; + } elsif ($type eq 'domains') { + $showtype = &mt('Domains'); + $infotype = 'Domain'; + } elsif ($type eq 'users') { + $showtype = &mt('Users'); + $infotype = 'User'; + } elsif ($type eq 'ip') { + $showtype = &mt('IP-based'); + $infotype = 'IP'; + } if (@{$items} > 0) { my @all_doms; my $colspan = 3; - my $uctype = $type; - $uctype =~ s/^(\w)/uc($1)/e; $r->print(&Apache::loncommon::start_data_table()); $r->print(&Apache::loncommon::start_data_table_header_row()); - $r->print(''.&mt('Action?').''.&mt($uctype).''. + $r->print(''.&mt('Action?').''.$showtype.''. &mt('Dates available').''); if ($type eq 'course' && $status eq 'old') { - $r->print(''.&mt('Allowed [_1] member affiliations',$type). + $r->print(''.&mt('Allowed course/community affiliations'). ''); $colspan ++; } elsif ($type eq 'domains') { @@ -1354,6 +1552,8 @@ sub display_access_row { $then); } elsif ($type eq 'users') { &users_row($r,$status,$key,$access_controls,$now,$then); + } elsif ($type eq 'ip') { + &ips_row($r,$status,$key,$access_controls,$now,$then); } $r->print(&Apache::loncommon::end_data_table_row()); } @@ -1365,8 +1565,12 @@ sub display_access_row { } $r->print(&Apache::loncommon::end_data_table()); } else { - $r->print(&mt('No [_1]-based conditions defined.
',$type). - &additional_item($type)); + $r->print( + '

' + .&mt('No '.$infotype.'-based conditions defined') + .'

' + .&additional_item($type) + ); } return; } @@ -1374,6 +1578,7 @@ sub display_access_row { sub course_js { return qq| |; } @@ -1427,17 +1633,20 @@ sub course_row { } my $js = &Apache::loncommon::coursebrowser_javascript($defdom) .&course_js(); - my $uctype = $type; - $uctype =~ s/^(\w)/uc($1)/e; + my $showtype = &mt('Course/Community'); + my $crstype = 'Course'; my ($num,$scope,$end,$start) = &set_identifiers($status,$item,$now,$then, $type); $r->print(''.$js.&actionbox($status,$num,$scope).''); if ($status eq 'old') { my $cid = $content->{'domain'}.'_'.$content->{'number'}; my %course_description = &Apache::lonnet::coursedescription($cid); + if ($course_description{'type'} ne '') { + $crstype = $course_description{'type'}; + } $r->print(''.$course_description{'description'}.''); } elsif ($status eq 'new') { - $r->print(''.&Apache::loncommon::selectcourse_link('portform','crsnum_'.$num,'crsdom_'.$num,'description_'.$num,$num.'_1',undef,$uctype).'  '); + $r->print(''.&Apache::loncommon::selectcourse_link('portform','crsnum_'.$num,'crsdom_'.$num,'description_'.$num,$num.'_1',undef,$showtype).'  '); } $r->print(''.&dateboxes($num,$start,$end)); my $newrole_id = 1; @@ -1455,19 +1664,19 @@ sub course_row { $max_id = $role_id; } $max_id ++; - my $role_selects = &role_selectors($num,$role_id,$type,$content,'display'); - $r->print('
'.$role_selects.''); + my $role_selects = &role_selectors($num,$role_id,$crstype,$content,'display'); + $r->print('
'.$role_selects.''); } $r->print(''); } $r->print('
'.&mt('Add a roles-based condition'). - ' {'domain'}','$content->{'number'}', - '$uctype'".')" value="" />'); + '$showtype'".')" value="" />'); $newrole_id = $max_id; } else { - $r->print(''); + $r->print(''); } $r->print(&add_course_role($num,$newrole_id)); $r->print(''); @@ -1488,14 +1697,14 @@ sub domains_row { my ($r,$status,$item,$all_doms,$access_controls,$now,$then) = @_; my ($num,$scope,$end,$start) = &set_identifiers($status,$item,$now,$then, 'domains'); - my $dom_select = ''. ' '; if ($status eq 'old') { my $content = $$access_controls{$item}; foreach my $dom (@{$all_doms}) { if ((@{$content->{'dom'}} > 0) && (grep(/^\Q$dom\E$/,@{$content->{'dom'}}))) { - $dom_select .= ''; } else { $dom_select .= ''; @@ -1523,18 +1732,47 @@ sub users_row { $r->print(''.&actionbox($status,$num,$scope).''.&mt("Format for users' username:domain information:").'
sparty:msu,illini:uiuc ... etc.
'.&dateboxes($num,$start,$end).''); } +sub ips_row { + my ($r,$status,$item,$access_controls,$now,$then) = @_; + my ($num,$scope,$end,$start) = &set_identifiers($status,$item,$now,$then, + 'ip'); + my $curr_ips_list; + if ($status eq 'old') { + my $content = $$access_controls{$item}; + $curr_ips_list = &sort_ips($content->{'ip'}); + } + $r->print(''.&actionbox($status,$num,$scope).''.&mt('Format for IP controls').'
'. + &mt('[_1] or [_2] or [_3] or [_4] or [_5]','35.8.*','35.8.3.[34-56]', + '*.msu.edu','35.8.3.34','somehostname.pa.msu.edu').'
'. + &mt('Use a comma to separate different ranges.').'
'. + ''. + ''.&dateboxes($num,$start,$end).''); +} + sub additional_item { my ($type) = @_; - my $output = &mt('Add new [_1] condition(s)?',$type).' '.&mt('Number to add: ').''; - return $output; + my $showtype; + if ($type eq 'course') { + $showtype = 'course/community'; + } elsif ($type eq 'domains') { + $showtype = 'domain'; + } elsif ($type eq 'users') { + $showtype = 'user'; + } elsif ($type eq 'ip') { + $showtype = 'IP'; + } + return + &mt('Add new '.$showtype.'-based condition(s)?') + .' '.&mt('Number to add: ') + .''; } sub actionbox { my ($status,$num,$scope) = @_; - my $output = '
'. ''; + $output .= ''; return $output; } @@ -1561,7 +1799,7 @@ sub dateboxes { undef,undef,1); my $enddate = &Apache::lonhtmlcommon::date_setter('portform', 'enddate_'.$num,$end,undef,undef,undef,1,undef, - undef,undef,1). '